LUCI配置文件简介
LUCI的配置文件一般存储在 /etc/config目录下。比如网络配置文件则是 /etc/config/network 无线的配置文件是 /etc/config/wireless. 跟多配置文件的含义参考官方 WIKI
基本概念
UCI上下文: struct uci_context *
包(Package): 一个包对应一个UCI格式的文件.类型是 struct uci_package *
节(Section): 一个配置文件的节点. 类型是 struct uci_list *
值(Value):一个节下面可能包含多个值 一个值具有一个名字.
UCI配置文件的基本操作.
首先您需要引入头文件
#include
#include
#include
#include
ledctrl通过配置文件/etc/config/ledctrl 对各个led灯进行控制
root@TL-WR843Nv2:/etc/init.d# cat /etc/config/ledctrl
config rule 'USB1_ON'
option ledname 'USB1'
option style 'default'
option ledon '1'
config rule 'USB1_OFF'
option ledname 'USB1'
option style 'default'
option ledon '0'
config rule 'WIFI2G_ON'
option ledname 'WIFI_2G'
option style 'default'
option ledon '1'
config rule 'WIFI2G_OFF'
option ledname 'WIFI_2G'
option style 'default'
option ledon '0'
config rule 'WAN0_ON'
option ledname 'WAN_LINK'
option style 'default'
option ledon '1'
config rule 'WAN0_OFF'
option ledname 'WAN_LINK'
option style 'default'
option ledon '0'
config rule 'WAN1_ON'
option ledname 'WAN_INET'
option style 'default'
option ledon '1'
config rule 'WAN1_OFF'
option ledname 'WAN_INET'
option style 'default'
option ledon '0'
config rule 'STATUS_ON'
option ledname 'STATUS'
option style 'default'
option ledon '1'
config rule 'STATUS_OFF'
option ledname 'STATUS'
option style 'default'
option ledon '0'
config rule 'STATUS_BLINK'
option ledname 'STATUS'
option style 'blink'
option delayon '350'
option delayoff '350'
config rule 'WPS_ON'
option ledname 'WPS'
option style 'default'
option ledon '1'
config rule 'WPS_OFF'
option ledname 'WPS'
option style 'default'
option ledon '0'
config rule 'WPS_SUCCESS'
option ledname 'WPS'
option style 'blink'
option delayon '300000'
option delayoff '0'
option duration '300000'
config rule 'WPS_ERROR'
option ledname 'WPS'
option style 'blink'
option delayon '250'
option delayoff '250'
option duration '60000'
config rule 'WPS_OVERLAP'
option ledname 'WPS'
option style 'mix'
option delayon '250'
option delayoff '250'
option delaylast '2000'
option interval '500'
option duration '30000'
config rule 'WPS_INPROGRESS'
option ledname 'WPS'
option style 'blink'
option delayon '2000'
option delayoff '1000'
option duration '120000'
config rule 'WPS_LED'
option start 'on'
option style 'auto'
option apps 'wps_led'
在文件/etc/profile.d/profile中定义了支持哪些LED灯
config ledctrl
list ledname 'USB1'
list ledname 'WIFI_2G'
list ledname 'WPS'
list ledname 'WAN_LINK'
list ledname 'WAN_INET'
list ledname 'STATUS'
Private RSS: 映射到内存中的页面, 这些页面仅由进程单独使用. 这也是我们最关心地方: 进程实际占用的内存数,该功能通过宏
CONFIG_PROC_PAGE_MONITOR控制。
RSS
: "Resident Set Size", 实际驻留"在内存中"的内存数
# cat /proc/568/maps
00008000-0036a000 r-xp 00000000 00:0e 236 /home/hik/hicore
00372000-003a5000 rw-p 00362000 00:0e 236 /home/hik/hicore
003a5000-00e28000 rwxp 003a5000 00:00 0 [heap]
40000000-40005000 r-xp 00000000 01:00 94 /lib/ld-uClibc.so.0
416db000-41770000 rw-s c2005000 00:0f 68 /dev/mem
b51fc000-b5200000 rwxp b51fc000 00:00 0
…….
be1fc000-be200000 rwxp be1fc000 00:00 0
be93b000-be950000 rwxp befeb000 00:00 0 [stack]
第一行:从r-xp可知其权限为只读、可执行,该段内存地址对应于执行文件的代码段,程序的代码段需加载到内存中才可以执行。由于其只读,不会被修改,所以在整个系统内共享。
第二行:从rw-p可知其权限为可读写,不可执行,该段内存地址对应于执行文件的数据段,存放执行文件所用到的全局变量、静态变量。
第三行:从rwxp可知其权限是可读写,可执行,地址空间向上增长,而且不对应文件,是堆段,进程使用malloc申请的内存放在堆段。每个进程只有一个 堆段,不论是主进程,还是不同的线程申请的内存,都反映到到进程的堆段。堆段向上增长,最大可以增长到1GB的位置,即0x40000000,如果大于 1GB,glibc将采用mmap的方式,为堆申请一块内存。
第四行:是程序连接的共享库的内存地址。
第五行:是以mmap方式映射的虚拟地址空间。
第六、七行:是线程的栈区地址段,每个线程的栈大小都是16K。
第八行:是进程的栈区。关于栈段,每个线程都有一个,如果进程中有多个线程,则包含多个栈段。
2015.12.04周五
昨天错误的操作,导致最近大半年的笔迹都给清了,备份只能备份到3月的。
今天跟踪一个免费ARP的问题,超找过免费ARP的作用:
免费
ARP
报文是一种特殊的
ARP
报文,该报文中携带的发送端
IP
地址和目标
IP
地址都是本机
IP
地址,报文源
MAC
地址是本机
MAC
地址,报文的目的
MAC
地址是广播地址。更换IP时,如果节点发送一个发往自己IP地址的ARP请求,结果收到ARP回应,这样就可以判断有另外一个机器使用与自己更换的IP地址相同的IP地址。如果发送了3个免费ARP后,都没有收到ARP回应,机器就假定此IP地址在此网络段中是唯一的。---地址冲突检测
设备通过对外发送免费ARP报文来实现以下功能:
- 确定其它设备的IP地址是否与本机的IP地址冲突。当其它设备收到免费ARP报文后,如果发现报文中的IP地址和自己的IP地址相同,则给发送免费ARP报文的设备返回一个ARP应答,告知该设备IP地址冲突。
- 设备改变了硬件地址,通过发送免费ARP报文通知其它设备更新ARP表项。
2015.12.9 周三
今天检查了软件中关于字节序隐藏的问题,发现好几个地方都没有处理字节序,qca9533 2.0使用的是大端的字节训,MTK使用小端字节顺序,这个会存在问题。
下午认证跟踪了时区显示的问题,发现是数组
gnTimeZoneValue的长度宏
HTTP_TIME_ZONE_NUM少了1,导致遍历时最后一个元素没有遍历到。
2015.12.10 周四
今天要跟进4230P CCA问题,找回以前读写寄存器的命令:
ethreg -g addr或ethreg -g addr=value
获取国家码(国家码表allCountry):
iwpriv ath0 get_countrycode
ath0 get_countrycode:276
设置信道命令:iwconfig ath0 channel 6
设置工作模式和频率:iwconfig ath0 mode master freq 6
xp添加MAC地址绑定
arp -s 192.168.0.254 60-E3-27-F1-49-88
2015.12.15 周二
设置guest network的SSID 对- 和‘ 这两个字符生效,但是对主网络是没问题的
3.单引号和双引号的区别
单引号‘’:取消除单引号以外的任何字符的特殊含义。
如:echo ‘my name is $name’其结果为:my name is $name,此时$只作为一个普通字符使用了。
双引号“”:取消除双引号、$号以及_号以外的所有字符的特殊含义
单引号是强引用,引号里的值是什么,变量的值就是什么;
双引号是弱引用,引号里的值若再包含变量,那在赋值的时候,所有这些变量就被立即替换了。
2015.12.16 周三
通过python函数调用生成,命令行中输入python,回车后输入以下命令:
import random
int(random.uniform(100000, 999999))
wifi克隆只是将rootap的ssid和加密方式进行了克隆,但是不能进行无线连接,所以实际使用的组网必须PLC网线连接到前端的RootAP。另外,PLC必须设置网关为RootAP的LAN IP,否则PLC上层的包转发不出去,比如GMT时间的NTP包;
2015.12.21 周一
11na_ht20代表802.11na的20兆频宽,连接速率有130M,11na_ht40代表802.11na的40兆频宽,连接速率有300M。由于802.11n有个特性是40M频宽,该频宽是通过以前的两个20M信道叠加起来后生成的,并且叠加时两信道一个是主信道一个是副信道,这里的plus和minus都是针对主信道说的,所以11na_ht40plus代表40M频宽时的2个信道叠加向上加的叠加,例如当前信道是149,配成40M频宽需要叠加另外一个信道,就是149+153两个信道组成的40MHz频宽,11na_ht40minus代表信道叠加时是向下减的叠加,例如配了这个,信道161,就等于是161+157组成了40M频宽的新信道。
802.11g也如a是一样的意思,只不过。由于802.11g只有1、6、11这3个信道,所以使用40M频宽的信道时只剩下了一个不重叠信道,所以在使用802.11ng时,不建议使用40MHz的频宽,使用默认的20MHz频宽即可
2015.12.22 周二
特殊字符转ascii码,在特殊字符前加\,对其他常规字符没有影响。
iwpriv ath0 hide_ssid 1 隐藏ssid命令
无线RPM的初始化入口函数httpWirelessInit
2015.12.23
在文件prereq.mk中,将BOARD_TYPE的值进行修改,编译脚本BOARD_TYPE=ap152,在这里进行更换:
ifneq (,$(findstring $(BOARD_TYPE),ap151-020 ap151 ap152 cus249 tb753 tb754 tb755 dragonflyemu))
override BOARD_TYPE = board956x
export REAL_BOARD_TYPE := $(BOARD_TYPE)
endif
GI:(Guard Interval)
保护间隔(Short Guard Interval):是OFDM符号中用于减少符号间干扰的时间。
·在多径环境下,后一符号的前端有可能比前一符号的末端更快到达接收机,从而导致符号间产生干扰。保护间隔是前后符号间的一段空白时间,可以为延迟信号提供更长的缓冲时间。
·保护间隔长度根据多径状态选择,802.11a/g使用800ns的保护间隔,802.11n默认也采用800ns的保护间隔,但一定环境下可以采用400ns的保护间隔
static const struct ath_hal_private ar9300hal 定义了hal层的函数,
ath_desc 用于hal层发送数据
,
用于硬件发送时送交硬件。
2015.12.25 周五
ucLite 是一个独立的进程,用于处理UI或者app提交到DUT的请求,其中
ucm_msgTaskCreate函数用于创建接收来自httpd的请求,接收通过TCP套接字,
_ucmMsgTask就是这个动作的全过程。
一个消息体的格式:
typedef struct _UCM_MSG_BODY
{
u32 owner;
u16 type;
u16 length;
u8 data[0];
} __attribute ((packed)) UCM_MSG_BODY;
所有模块的初始化函数都在表uclOpModInitArray中,这个表主要是一个index和一个函数指针,这个函数指针中包含了该模块的setup函数。setup函数只是将表中列好的模块按照实际的调用顺序进行排序,放在pOpapiData-> pOpModArray中。
2015.12.28
今天将LinuxPlat QCA平台的代码移植到plc_platform中,两者差异甚大。plc_platform 代码中
1)在board 目录下存在三个芯片方案的目录,但是这个目录的名称是公司名+芯片名称,感觉不合理;
2)每个机型都有自身的Makefile.***;
2015.12.29
今天和锋哥讨论关于board 目录是否应该带方案的问题,个人觉得不带为好,但是bcm和mkt的都带了,所以qca的暂时也带方案名称。
在Makefile.kernelmodules文件中定义了编译模块的函数。但是这些模块不完整,可以和LinuxPlat比较。
ipv4_module下cp *.ko出错的
Z:\plc_platform\tp-software\develop\private\apps\common\util\util.c中增加头文件的引用,否则memset报错。
*** [_dir_/home/project/plc_platform/tp-software/develop/private/apps/uclite/modules/uclite-ledschedule] Error 2
先执行clean操作。
Z:\plc_platform\tp-software\develop\private\apps\uclite的Makefile中修改:
uclite.o: clean uclite_prep subdirs
/home/project/plc_platform/board/model_qca_apxxx/toolchain/gcc-4.3.3/build_mips/staging_dir/usr/bin/../lib/gcc/mips-linux-uclibc/4.3.3/../../../../mips-linux-uclibc/bin/ld: cannot find -lplcapi
kernel_modules_%:printf_echo $(addsuffix _%, $(kernel_modules_target))
make 提示kernel_modules_ 找不到目标,其实是后面的$(addsuffix _%, $(kernel_modules_target)) 找不到目标,在Makefile.kernelmodules中增加每个驱动的编译目标。
can not be used when making a shared object; recompile with -fPIC
./hpAVCommon.o: could not read symbols: Bad value
can not be used when making a shared object; recompile with -fPIC
Makefile 中的CFLAGS没有
/home/project/plc_platform/board/model_qca_apxxx/build/../../../util/fakeroot: line 166: 16247 Segmentation fault FAKEROOTKEY=$FAKEROOTKEY LD_LIBRARY_PATH="$PATHS" LD_PRELOAD="$LIB" "$@"
2015.12.30
fakeroot 可以用来模拟 root 权限,以便建立特定权限与档案拥有者的压缩文件案(tar, ar, .deb 等)。透过 LD_PRELOAD 的 dynamic loader 功能,用户不必实际拥有 root 权限。fakeroot最初是为了创建debian包使用的。
例如Debian在生成package的时候,编译完之后,不能立刻在当前环境执行make install,需要执行make install DESTDIR=$(pwd)/debian/tmp把生成的文件安装到build目录的里面$(pwd)/debian/tmp。然后使用那个目录里面的全部内容生成Debian包(实际上包里面还会包含control和maintainer script等)。这个包里面的文件所有者必须是root,所以需要以root来执行打包命令。但是应该避免在制作Debian包的时候使用root权限。为了解决这个矛盾,fakeroot被开发出来了。在fakeroot环境中,操作文件就像使用root操作文件一样。但是,实际上系统中文件的权限还是原来的权限。这个包里面的文件所有者必须是root,所以需要以root来执行打包命令。
fakeroot与sudo的区别编辑
fakeroot不能获得root的权限,sudo可以。
fakeroot只是伪装成root,它不能改变需要root权限才能改变的文件,它只是让程序执行时按照有root权限的情况来运行,而对文件的操作实际上是在普通用户下进行的。
1 fakeroot tar cvf /tmp/local.tar /usr/local
2 sudo tar cvf /tmp/local.tar /usr/local
上面两条命令都会在/tmp下建立local.tar,tar内的文件名都会以/开头,但前一条命令生成的文件属于当前用户,后一条命令生成的文件是root的。
2015.12.31 周四
测试反馈:
样机经过校准后,DUT不断电,测试发送功率,可以达到12.5dBm(目标是13dBm,正负1.5dBm正常),但是DUT重启后,在一个测试功率的拓扑(LAN->WLAN)下测试,发现功率只有-12dBm
将qca移植到plc的新平台后,烧写uboot,样机挂了。
2016.1.4 周一
放假回来第一日上班,今天主要合并QCA代码到PLC代码分支,原来锋哥给的代码是RE组的代码,和LinuxPlat的不一样,经过尝试和评估,觉得还是将LinuxPlat的代码合并到PLC分支比较好,可以保证SDK代码的和makefile结构的完整,uboot出现问题会导致板子变砖。主要的修改是上层的apps的代码路径的makefile组织代码。
2016.1.5 周二
今天跟进了4220反馈的在veriwave上测试的问题,该测试工具使用card进行硬件接口管理,上午测试了UDP的丢包使用的是waveApp,下午测试了throughput,使用的是waveQoE,在waveQoE中,服务器端只能配置成有线,这点和技术支持反馈回来的不一样。
2016.1.6 周三
今天跟进4230p无线发射功率低的问题,FAE对比了ini文件后发现现在使用的是
QCA9561 (Dragonfly ap151)
的无线驱动,而不是horny BEE 2.0的驱动。另外,晚上尝试将qca的驱动编译到4230上,但是发现编译的驱动不生效。还有配置文件中校准数据的位置错了,正确的是:
AH_CAL_LOCATIONS_AHB=0xbf7f0000
2016.1.12 周二
今天解决4230的bug,PLC在组网后出现LAN灯灭掉的现象,原因是在
blinkAllLeds中对所有的灯进行亮灭操作,这个是8630的要求,而4230是不需要的。
2016.1.18 周一
shell脚本参数可以任意多,但只有前9各可以被访问,使用shift命令可以改变这个限制。参数从第一个开始,在第九个结束。
$0 程序名字
$n 第n个参数值,n=1..9
$* 所有命令行参数
$@ 所有命令行参数,如果它被包含在引号里,形如”$@”,则每个参数也各自被引号包括
$# 命令行参数个数
$$ 当前进程的进程ID(PID)
$! 最近后台进程的进程ID
$? 最近使用命令的退出状态
sed -i '/^Tolstoy/d' shell.txt 删除以Tolstoy开头的第一行;
sed -i 's/zhouqiqiu/ZQQ/g' shell.txt 用ZQQ替换所有zhouqiqiu
2016.1.20 周三
plc_platform 的busybox中有两个版本的busybox代码,一个是1.01,另外一个是1.19.4,需要在makefile中区分不同的项目使用的busybox版本。
需要将libmsglogd放在apps目录下
arm-uclibc-linux-2.6.36-strip -s --remove-section=.note --remove-section=.comment busybox
make[3]: arm-uclibc-linux-2.6.36-strip: Command not found
在文件./include/config.h 中定义了#define CROSS_COMPILER_PREFIX "arm-uclibc-linux-2.6.36-"
将LinuxPlat中的busybox 拷贝到plc_platform中,然后修改Makefile,注意busybox的目录层次。
2016.1.22 周五
/home/project/plc_platform/tp-software/develop/private/apps/uclite/modules/uclite-wifiSched/uclite-wifiSched.h:5:22: error: tp_linux.h: No such file or directory
2016.1.25 周一
RPT_FLASH_PARTITION_TABLE_IN_SRC 必须在配置文件中定义,而且Z:\plc_platform\tp-software\develop\private\apps\uclite\public\opt.h文件要删除,配置才能重新写入文件。
/home/project/plc_platform/board/model_qca_apxxx/toolchain/buildroot-2009.08/build_mips/staging_dir/usr/bin-ccache/../lib/gcc/mips-linux-uclibc/4.3.3/../../../../mips-linux-uclibc/bin/ld: cannot find -lz
INSTALL_ROOT 在rules.mk中重新赋值了,路径是错误的。
uclite.o: In function `opTddp_eraseRadio':
(.text+0x2051c): undefined reference to `eraseRadioFlash'
在basic.config中定义RPT_PLATFORM_QCA
./include/wrn/wm/common/wmData.h:241: error: two or more data types in declaration specifiers
修改一下这个文件,重新编译即可
make[1]: *** No rule to make target `/home/project/plc_platform/tp-software/develop/private/apps/wifid/src/qca/wifi_cmd_qca.o', needed by `wifi'. Stop.
plc_platform\tp-software\develop\private\apps\wifid\src\qca 这个目录是空的,
/home/project/plc_platform/board/model_qca_qca95xx/sdk/ap143/apps/wrapd/main.c:144: undefined reference to `wpa_ctrl_open'
make: *** No rule to make target `kernel_modules_build', needed by `everything_build'. Stop.
其实是Makefile.kernelmodules中缺了两个编译目标,添加就可以了:
$(call mkrule, br_guest_filter):
@$(call makemod, $(TP_KERNEL_MODULES)/br_guest_filter, br_guest_filter.ko);
$(call mkrule, parentCtrl):
@$(call makemod, $(TP_KERNEL_MODULES)/parentCtrl, parentCtrl.ko);
2015.1.28 周四
跟踪MTD驱动中分析分区信息的代码
2015.1.29 周五
编译后的8730软件需要整个flash进行烧录,
setenv serverip 192.168.1.104
tftp 80800000 wpa8730v1_eu-flash-ver1-0-0-P1[20160307-rel63124].bin
erase 9f000000 +800000
cp.b 80800000 9f000000 800000
烧写后发现DUT的网络不通,而看lsmod驱动已经加载,进一步跟进,发现是KERNEL_MODULES_TARGET_COMMON中的驱动被屏蔽了,使用的驱动不是编译而来的,打开参数后编译,可以Ping通。
2016.2.14 周日
农历新年后的第一天上班。
#define PRINT_ERR(fmt, args...) printf("[Err] %s(%d): "fmt, __FILE__, __LINE__, ##args)
所有LED的控制灯通过一个CONFIG_HAVE_LED_POWER_CTRL宏进行控制,该宏可以
2016.2.19
1. 加载ath_pktlog.ko,insmod /lib/modules/2.6.31/net/ath_pktlog.ko
2. pktlogconf -a wifi1 -s 0 (缓存清零) //pktlogconf -a wifi1 -s 10000000 (将缓存设置为10M)
3. pktlogconf -a wifi1 -e (开始记录)
4. pktlogconf -d wifi1 (停止记录)
5. cd /proc/ath_pktlog
6. tftp -p -l wifi1 -r pktlog 192.168.0.100 (把pktlog导出来)
7. 安装perl解析工具,安装包放在了\\file.tp-link.net\Public\z周建兴\ActivePerl-5.12.2.1202-MSWin32-x86-293621.rar
8. 如果是11n的数据,使用附件的pktlogdecoder.pl对pktlog进行解析,如果是11ac,请使用pktlogdecoder_11ac.pl:在cmd命令行,执行命令pktlogdecoder.pl -R pktlog(pktlogdecoder.pl和pktlog需要在同一文件夹下,cmd路径也要在此目录下,-R是看rate统计,pktlog是导出来的文件名)
9. 如果想查看其他统计信息,请使用pktlogdecoder.pl -h查看帮助。
2016.2.22 周一
工作安排:
1.跟进4230P测试进程,安排提测;
2.新平台无线部分;
3.无线驱动学习;
2016.2.23 周二
上无准备样机提测,发现测试无线WLAN->LAN的时候 throughput只有80MBps,而且波动幅度非常大,怀疑是屏蔽箱中其他信号干扰的问题,需要到屏蔽房中测试。
样机需要重新烧PLC的bin和无线校准。
下午看无线驱动手册,硬件工程师将样机拿去烧PLC的bin和无线校准了。
2016.2.24 周三
上午提测,出现了一个低级错误,测试申请单中的硬件配置表,硬件工程师反馈了一份,我也更新都本地了,但是没有检查OA上的是否更新,结果OA上用的还是旧的,太不小心了。多检查一下就发现的问题,导致重新提交。
文档反馈一个版本问题,顺带检查软件的版本,发现是1.0.0,经过讨论后,应该是1.2.0,而bugzilla上反馈的目录也是1.2.0,这个其实我之前发现,但是没有追究是什么原因。修改后软件重编,但是build server卡死了,重启后提示工程locked,下载后要重新编译toolchain。晕死~~~
2016.2.26 周五
今天调试4220的GPIO问题,power control 被拉低了,导致所有灯不亮,在Uboot中修改了代码
#ifdef CONFIG_HAVE_LED_POWER_CTRL
ath_gpio_config_output (GPIO_LED_POWER);
//LOW LEVEL TURN ON ALL
ath_gpio_out_val(GPIO_LED_POWER, 1);//ZQQ
#endif
可以量,但是一旦修改了manage_led后,又不亮了。
2016.2.29 周一
今天调试gpio,看了datasheet中关于GPIO的操作,修改,调试,发现问题依旧,后来在系统日志中发现有个打印将LED灯打开,跟进后发现有个定时器会定期调用函数setLedAccordingToCfg将LED由关闭到打开,
使用的方法是文件操作fopen打开文件和
fputc写入字符
,奇怪的这个写入和echo的写入不一样,后者可以打印出write函数中打印信息,前者不可以。
2016.3.1 周二
上午调试4220的灯的控制问题,该机型的灯的控制0/1和其他机型不一样,0表示亮,1表示灭;
下午协助调试TATA反馈IPv6拨号后PC不能访问IPv6网站的问题,通过tracet 看包的发送路径,不能到达ISP的路由器,可能是IP地址错误或者路由的问题,对比其他机型,发现WAN口的IP地址前缀是128bit,设置了WAN IP地址是128bit后,ok!
2016.3.2 周三
2016.3.3 周四
上午跟进测试部反馈LAN->WLAN性能偏低的问题,PC连接无线,3个以太网口分别连接PC,在使用10个pairs测试时,速率只能达到120Mbps,但是增加paris数目或者使用high_performance_throughput.src可以提高性能。
2016.3.4 周五
发布软件
2016.3.7 周一
./include/wrn/wm/common/wmData.h:29: error: two or more data types in declaration specifiers
./include/wrn/wm/common/wmData.h:29: warning: useless type name in empty declaration
./include/wrn/wm/common/wmData.h:30: error: two or more data types in declaration specifiers
./include/wrn/wm/common/wmData.h:30: warning: useless type name in empty declaration
重复的定义,将tpyedef 修改成#defined 可以解决
2016.3.8 周二
上无web server自动化测试的介绍,下午看新平台的web server代码。web 模块的初始化入口函数:
web_Web_Start
httpRpmInit注册各种RPM函数
WRP_TRANS_START uclite发送读或者写的消息;
WRP_TRANS_COMMIT 发送命令并检查返回的结果;
apps/wifid下没有qca对应的实现部分。
2016.3.9 周三
编译新平台的web server遇到编译出错
/home/project/plc_platform/tp-software/develop/private/apps/web_server/rpm/wps/httpWps.c:41: undefined reference to `utl_bandMode_bandMode2band'
rpm/wps/httpWps.o: In function `_writeWifiCloneJson':
/home/project/plc_platform/tp-software/develop/private/apps/web_server/rpm/wps/httpWps.c:67: undefined reference to `utl_bandMode_band2bandMode'
原因是在Z:\plc_platform\board\model_qca_qca95xx\images\wpa8730v1\rootfs.build\lib中存在libutil.so和libutil.a两个文件,而实际要使用的是libutil.a,这里编译命令-lutil应该优先匹配了libutil.so
将libutil.so换个名字。
2016.3.10 周四
make[1]: *** No rule to make target `/home/project/plc_platform/tp-software/develop/private/apps/gpio/src/gpio_qca/gpio_qca_wpa8730v1.o', needed by `gpiod'. Stop.
850re 2.0使用的是horneybee 2.0的方案,和8730一样,暂时先使用这个接口文件,但是发现有很多宏没有定义。
GPIO_LED_PORT_WIFI_SIGNAL1 这些宏在机型的config中定义,暂时去掉函数中的实现。
wpsd.c:(.text+0x26c): undefined reference to `g_wpsd_ops' , 在wpsd中暂时没有qca的实现,先屏蔽这个app
8730的kernel配置中很多kernel的模块都配置成y,导致拷贝ko出错,在拷贝的shell脚本中增加对被拷贝文件的判断:
export makemod = if [ -z "$(@:%_install=)" ]; then \
cd $(1) && (if test -f $(2); then cp -f $(2) $(if $(3), $(3), $(LINUX_MODULES_INSTALL));fi); \
elif [ -z "$(@:%_clean=)" ]; then $(MAKEMODULES) clean SUBDIRS=$(strip $(1)); \
else $(MAKEMODULES) SUBDIRS=$(strip $(1)) modules; fi
2016.3.11 周五
无线的app使用了原来ap143的,不是board956x的。因为使用board956x出现问题:/src/drivers/driver_atheros.c:46:32: error: ieee80211_external.h: No such file or directory
需要配置config.athr_supplicant和config.athr_hostapd两个文件,同时如果支持wpa2的话,是要编译Z:\plc_platform\board\model_qca_qca95xx\sdk\board956x\wlan\apps\wpa2下的hostapd和wpa_supplicant,而这两个的编译配置,通过文件Z:\plc_platform\board\model_qca_qca95xx\sdk\board956x\wlan\apps\wpa2\common\Makefile.common进行。
export PERF_PWR_OFFLOAD_DIR_PATH=$(TOPDIR)/target/$(BOARD_TYPE)/wlan/drivers/firmware 这个宏是干什么的?
2016.3.14 周一
adf: version magic '2.6.31 mod_unload MIPS32_R2 32BIT ' should be '2.6.31--LSDK-9.2.0_U5.508 mod_unload MIPS32_R2 32BIT '
wifid[wifi_exec_cmd:1182]: insmod /lib/modules/2.6.31/net/asf.ko
asf: version magic '2.6.31 mod_unload MIPS32_R2 32BIT ' should be '2.6.31--LSDK-9.2.0_U5.508 mod_unload MIPS32_R2 32BIT '
wifid[wifi_exec_cmd:1182]: insmod /lib/modules/2.6.31/net/ath_hal.ko
TL-WPA8730 mips #1 Fri Jan 29 16:18:24 HKT 2016 (none)
TL-WPA8730 login: ath_hal: version magic '2.6.31 mod_unload MIPS32_R2 32BIT ' should be '2.6.31--LSDK-9.2.0_U5.508 mod_unload MIPS32_R2 32BIT '
wifid[wifi_exec_cmd:1182]: insmod /lib/modules/2.6.31/net/ath_rate_atheros.ko
ath_rate_atheros: version magic '2.6.31 mod_unload MIPS32_R2 32BIT ' should be '2.6.31--LSDK-9.2.0_U5.508 mod_unload MIPS32_R2 32BIT '
wifid[wifi_exec_cmd:1182]: insmod /lib/modules/2.6.31/net/ath_dfs.ko
ath_dfs: version magic '2.6.31 mod_unload MIPS32_R2 32BIT ' should be '2.6.31--LSDK-9.2.0_U5.508 mod_unload MIPS32_R2 32BIT '
wifid[wifi_exec_cmd:1182]: insmod /lib/modules/2.6.31/net/ath_dev.ko
ath_dev: version magic '2.6.31 mod_unload MIPS32_R2 32BIT ' should be '2.6.31--LSDK-9.2.0_U5.508 mod_unload MIPS32_R2 32BIT '
wifid[wifi_exec_cmd:1182]: insmod /lib/modules/2.6.31/net/umac.ko
umac: version magic '2.6.31 mod_unload MIPS32_R2 32BIT ' should be '2.6.31--LSDK-9.2.0_U5.508 mod_unload MIPS32_R2 32BIT '
Z:\LinuxPlat\target\board956x\linux\kernels\mips-linux-2.6.31\include\config\kernel.release文件中包含kernel的实际版本。这个版本必须驱动和kernel一致,否则出现上边的问题。
2016.3.15
make ARCH=mips CROSS_COMPILE=mips-linux-uclibc- EXTRAVERSION=--LSDK-10.2-00082-4 wpa8730v1_defconfig
2016.3.16
尝试更换新旧平台的squashfs文件系统,发现需要找lib下的zlib驱动,又尝试整个kernel更换,发现编译以太网驱动失败,头文件找不到。
跟踪出错打印的函数调用栈,发现在unlzma出错,研究make_flash源码:
[ 0.776000] Call Trace:
[ 0.776000] [<800f02c8>] unlzma+0xfb4/0x118c
2016.3.17
终于知道问题所在,新平台的文件打包工具使用的压缩方式是gzip,而不是lzma,在文件buildFS_LZ中:
$RPT_TOPDIR/util/mksquashfs4.0 $INSTALL_ROOT_FOR_BOARD $IMAGEPATH/$BOARD_TYPE-squashfs -noappend -always-use-fragments -all-root -b 1048576
关键是Z:\plc_platform\util目录下的
mksquashfs4是不支持lzma的,更换为旧平台的
mksquashfs4.0就可以了。
2016.3.18 周五
read tp partition address:0x00610100 partition_used_len:0xffffffff len:0x0
[NM_Error](nm_api_readPtnFromNvram) 00133: partition name not found([ 3.140000] Now flash open!
name:device-id).[ 3.140000] Erase from 0X630000 to 0X630460:
failed to read device id from flash
分区表中增加device-id分区。
read tp partition address:0x00610200 partition_used_len:0xffffffff len:0x0
[usrcfg_error: usrconf_load:916]md5 verify error[ 3.088000] Now flash open!
2016.3.21 周一
MD5错误,dut不断重启
原因是写默认设置是,没有将配置文件的长度作为头进行写入,这部分在drivers\mtd\devices\ath_flash_ioctl.c中机型操作,处理方式是将RE850的这部分代码移植过来。但是出现另外一个问题:
# cat /proc/meminfo
MemTotal: 15384 kB
MemFree: 3420 kB
Buffers: 12 kB
Cached: 1544 kB
SwapCached: 0 kB
内存大小不对。
2016.3.22 周二
昨天反馈产测软件缺少了CTL表和目标功率表。CTL是限制功率,是指符合各认证标准下的发射功率,目标功率是
产品无线发射性能够好情况下的功率,超过这个功率值,无线发射信号质量下降,影响产品性能。这个值一般参考
Atheros DEMO
的数据,性能余量很大的机型,增加发射功率,性能仍然能够满足要求。
现在的处理方法是重新提测产测软件。
新平台的wifid编译失败,但是还是需要先解决内存大小问题,
prom_init kernel中解析uboot传过来参数的解析参数
do_bootm_linux :uboot调用thekernel跳入到kernel的的函数
2016.3.25 周五
测试反馈产测标准中发现LAN2WLAN双向速率不对,对于产测标准要求的130Mbps,后来在我的位置上测试,发现ixchariot在统计速率的时候会出现一个方向的速率数据没有统计到,需要关闭再打开才可以,后来测试的数据是150+Mbps,符合要求。
新平台内存问题,是应为少了mem参数,uboot向kernel传参比较有意思,初步看是通过环境变量进行传参。在函数do_bootm_linux中调用函数theKernel (linux_argc, linux_argv, linux_env, 0);传入环境变量的参数。
2016.3.28 周一
要注意文件系统挂载的是哪个设备,一些机型的MTD分区,将uboot的64K分为两个32K,所以文件系统对应的设备号是32:3,
而如果只是128的uboot,文件系统挂载的mtd设备是31:2
就是宏:
#define MTDPARTS_DEFAULT
"mtdparts=ath-nor0:128k(u-boot),1024k(uImage),6912k(rootfs),64k(mib0),64k(ART)"
define ATH_ROOT_DEV
"31:02"
定义的值。
bootstrap_board_init_f 在文件start_bootstarp.S中被调用。
uboot文件生成过程
1.u-boot:由各目录的.a文件链接而成,最后通过命令
mips-linux-uclibc-objcopy --gap-fill=0xff -O binary u-boot u-boot.bin 设置各个section之间的值为0xff后输出为u-boot.bin,注意-Ttext 0x80010000,这个地址是内存的虚拟地址,所以这部分代码是在内存中运行的;
2.bootstrap.bin : 编译汇编文件start_bootstrap.S,编译libbootstrap.a(当中包括了lzma的解压缩文件),然后链接这些库,注意-Ttext 地址是0x9f000000,所以说这些代码是在flash中运行的。这部分相当于引导uboot.bin的前导文件;
3.tuboot.bin 这个文件通过bootstrap.bin和经过lzma压缩后的u-boot.bin并凑而成,其中
u-boot.lzimg: $(obj)u-boot.bin System.map
@echo ===$(obj)u-boot.bin===
@$(LZMA) e $(obj)u-boot.bin u-boot.bin.lzma
@./tools/mkimage -A mips -T firmware -C lzma \
-a 0x$(shell grep "T _start" $(TOPDIR)/System.map | awk '{ printf "%s", $$1 }') \
-e 0x$(shell grep "T _start" $(TOPDIR)/System.map | awk '{ printf "%s", $$1 }') \
-n 'u-boot image' -d $(obj)u-boot.bin.lzma $@
Usage: ./mkimage -l image
-l ==> list image header information
./mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image
-A ==> set architecture to 'arch'
-O ==> set operating system to 'os'
-T ==> set image type to 'type'
-C ==> set compression type 'comp'
-a ==> set load address to 'addr' (hex)
-e ==> set entry point to 'ep' (hex)
-n ==> set image name to 'name'
-d ==> use image data from 'datafile'
-x ==> set XIP (execute in place)
System.map文件:
00000101 A num_got_entries
80010000 T _start
80010030 T relocate_code
80010094 t in_ram
80010100 T ath_set_tuning_caps
800101a0 T do_go
800102c0 T print_image_hdr
800106c8 T do_bootd
80010718 T fake_image_header
800107f0 T do_bootm
800109c0 T flash_sect_erase
80010bc8 T do_flerase
80011000 T test_algorithm_t
800113ac T do_mem_mct
80011820 T do_mem_mtest
80011a04 T cmd_get_data_size
uboot中image_header定义
typedef struct image_header {
uint32_t ih_magic; /* Image Header Magic Number */
uint32_t ih_hcrc; /* Image Header CRC Checksum */
uint32_t ih_time; /* Image Creation Timestamp */
uint32_t ih_size; /* Image Data Size */
uint32_t ih_load; /* Data Load Address */
uint32_t ih_ep; /* Entry Point Address */
uint32_t ih_dcrc; /* Image Data CRC Checksum */
uint8_t ih_os; /* Operating System */
uint8_t ih_arch; /* CPU architecture */
uint8_t ih_type; /* Image Type */
uint8_t ih_comp; /* Compression Type */
uint8_t ih_name[IH_NMLEN]; /* Image Name */
} image_header_t;
image_header_t大小是64字节。
打开u-boot.lzimg文件,可以看到文件开头就是这个头的内容:
两个阶段:第一个是在引导阶段,主要在start_bootstrap.S中,两个关键函数:
bootstrap_board_init_f:初始化c执行环境
bootstrap_board_init_r函数中会读取这个头,并判断当中的参数并解压uboot
i = lzma_inflate ((unsigned char *)data, len, (unsigned char*)ntohl(hdr->ih_load), &destLen); 就是说要解压到内存地址ih_load指向的地方,就是0x80010000这个地址。
fn = ntohl(hdr->ih_load);
(*fn)(gd->ram_size);
跳到0x80010000内存开始执行,
80010000 T _start
80010030 T relocate_code
80010094 t in_ram
80010100 T ath_set_tuning_caps
800101a0 T do_go
800102c0 T print_image_hdr
800106c8 T do_bootd
80010718 T fake_image_header
800107f0 T do_bootm
800109c0 T flash_sect_erase
80010bc8 T do_flerase
这个表只是函数地址的编码表,并不是执行的顺序表,注意。
第二阶段
在汇编文件start.S中,第一个调用是board_init_f,board_init_f函数主要是根据配置对全局信息结构体gd进行初始化
relocate_code:在start.S中定义;
in_ram:
在start.S中定义;
然后跳到board_init_r中开始c代码环境的第一函数执行;这个函数初始化和好多东西,可以仔细看看
main_loop中调用了parse_string_outer 通过执行命令bootm 0x9f010000 进入到函数do_bootm;
2016.3.30 周三
整理uboot启动流程分析文档,新平台使用Linuxplat wlan apps,但是发现编译失败,缺少文件:
/src/drivers/driver_atheros.c:46:32: error: ieee80211_external.h: No such file or directory
在apps\athr-hostap\hostapd\.config中有CFLAG的定义,其中有ATHEROSPATH这个变量
在配置文件config.wpa8730v1
中增加:export ATHEROSPATH=$(BOARD_TOPDIR)/sdk/$(BOARD_NAME)/wlan/drivers/wlan_modules_$(BOARD_TYPE)即可
Z:\LinuxPlat\target\board956x\wlan\drivers\wlan_modules_ap135\os\linux\configs\.config.wlan.all 无线的配置文件
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("k0")
2016.4.1 星期五
#define WIFI_REGION_CHANNEL_INFO "/tmp/region.channel.info"
#define WIFI_CLIENTS_INFO "/tmp/clients.info"
#define WIFI_STATUS_INFO "/tmp/wifi.status.info"
#define WIFI_INTERFACE_INFO "/tmp/wifi.interface.info"
对wifid中qca目录,要实现对参数的读操作,参考mtk方案的数据格式和api,实现qca的api。
2016.4.5 星期二
wifi_register_ops 定义了无线驱动的初始化接口
2016.4.6 星期二
添加wifi_platform_qca.c中的函数接口。
2016.4.7 星期三
新平台需要在8630p上做,所以要移植ap152的无线驱动,真是日了狗了。
在编译board_type ap152时,出现: error: ol_txrx_osif_api.h: No such file or directory
./drivers/firmware/host/include/ol_txrx_osif_api.h
需要打开PERF_PWR_OFFLOAD_DIR_PATH的定义编译ok;
新平台的busybox使用1.19.4,旧平台使用1.01
以太网驱动的配置文件:Z:\plc_platform\board\model_qca_qca95xx\sdk\board956x\linux\drivers\ethernet\include\config.h
uboot的配置文件:Z:\plc_platform\board\model_qca_qca95xx\sdk\board956x\boot\u-boot\include
2016.4.8 星期五
在8630p上重新移植ap152无线驱动,uboot和kernel已经ok,无线可以看到wifi0设备,但是没有设置ath0,在/etc/rc.d/rcS中调用了脚本进行初始化,这个要看看无线是如何进行初始化操作的。
2016.4.10周日
wlanBootupAll 函数中对无线进行初始化,调用wlanWorkingNormalAp函数,
1.设置国家码(qca_wd_setup_cc);
iwpriv wifi0 setCoutryID %d
国家码由一个数组定义,region是这个数组的下标,
typedef struct CountryCodeToCountryRegion {
UINT32 CountryNum;
UINT8 IsoName[3];
char* pCountryName;
BOOL SupportABand;
UINT8 RegDomainNum11A;
BOOL SupportGBand;
UINT8 RegDomainNum11G;
} COUNTRY_CODE_TO_COUNTRY_REGION;
COUNTRY_CODE_TO_COUNTRY_REGION allCountry[] = {
{8, "AL", "ALBANIA" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{12, "DZ", "ALGERIA" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{32, "AR", "ARGENTINA" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{51, "AM", "ARMENIA" , TRUE, A_BAND_REGION_2, TRUE, G_BAND_REGION_1},
{533, "AW", "ARUBA" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{36, "AU", "AUSTRALIA" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{40, "AT", "AUSTRIA" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{31, "AZ", "AZERBAIJAN" , TRUE, A_BAND_REGION_2, TRUE, G_BAND_REGION_1},
{44, "BS", "BAHAMAS" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{48, "BH", "BAHRAIN" , TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1},
{50, "BD", "BANGLADESH" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{52, "BB", "BARBADOS" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{112, "BY", "BELARUS" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{56, "BE", "BELGIUM" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{84, "BZ", "BELIZE" , TRUE, A_BAND_REGION_4, TRUE, G_BAND_REGION_1},
{60, "BM", "BERUMUDA" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_0},
{68, "BO", "BOLIVIA" , TRUE, A_BAND_REGION_4, TRUE, G_BAND_REGION_1},
{70, "BA", "BOSNIA AND HERZEGOVINA" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{76, "BR", "BRAZIL" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{96, "BN", "BRUNEI DARUSSALAM" , TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1},
{100, "BG", "BULGARIA" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{116, "KH", "CAMBODIA" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{124, "CA", "CANADA" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_0},
{152, "CL", "CHILE" , TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1},
{156, "CN", "CHINA" , TRUE, A_BAND_REGION_4, TRUE, G_BAND_REGION_1},
{170, "CO", "COLOMBIA" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_0},
{188, "CR", "COSTA RICA" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{191, "HR", "CROATIA" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{196, "CY", "CYPRUS" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{203, "CZ", "CZECH REPUBLIC" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{208, "DK", "DENMARK" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{214, "DO", "DOMINICAN REPUBLIC" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_0},
{218, "EC", "ECUADOR" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{818, "EG", "EGYPT" , TRUE, A_BAND_REGION_2, TRUE, G_BAND_REGION_1},
{222, "SV", "EL SALVADOR" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{233, "EE", "ESTONIA" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{246, "FI", "FINLAND" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{250, "FR", "FRANCE" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{268, "GE", "GEORGIA" , TRUE, A_BAND_REGION_2, TRUE, G_BAND_REGION_1},
{276, "DE", "GERMANY" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{300, "GR", "GREECE" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{304, "GL", "GREENLAND" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{308, "GD", "GRENADA" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_0},
{316, "GU", "GUAM" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_0},
{320, "GT", "GUATEMALA" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_0},
{332, "HT", "HAITI" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{340, "HN", "HONDURAS" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{344, "HK", "HONG KONG" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{348, "HU", "HUNGARY" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{352, "IS", "ICELAND" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{356, "IN", "INDIA" , TRUE, A_BAND_REGION_0, TRUE, G_BAND_REGION_1},
{360, "ID", "INDONESIA" , TRUE, A_BAND_REGION_5, TRUE, G_BAND_REGION_1},
{364, "IR", "IRAN" , TRUE, A_BAND_REGION_4, TRUE, G_BAND_REGION_1},
{372, "IE", "IRELAND" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{376, "IL", "ISRAEL" , TRUE, A_BAND_REGION_2, TRUE, G_BAND_REGION_1},
{380, "IT", "ITALY" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{388, "JM", "JAMAICA" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{392, "JP", "JAPAN" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_5},
{400, "JO", "JORDAN" , TRUE, A_BAND_REGION_6, TRUE, G_BAND_REGION_1},
{398, "KZ", "KAZAKHSTAN" , TRUE, A_BAND_REGION_4, TRUE, G_BAND_REGION_1},
{404, "KE", "KENYA" , TRUE, A_BAND_REGION_4, TRUE, G_BAND_REGION_1},
{408, "KP", "NORTH KOREA" , TRUE, A_BAND_REGION_20, TRUE, G_BAND_REGION_1},
{412, "KR", "KOREA REPUBLIC" , TRUE, A_BAND_REGION_20, TRUE, G_BAND_REGION_1},
{414, "KW", "KUWAIT" , TRUE, A_BAND_REGION_2, TRUE, G_BAND_REGION_1},
{428, "LV", "LATVIA" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{422, "LB", "LEBANON" , TRUE, A_BAND_REGION_4, TRUE, G_BAND_REGION_1},
{438, "LI", "LIECHTENSTEIN" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{440, "LT", "LITHUANIA" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{442, "LU", "LUXEMBOURG" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{446, "MO", "MACAU SAR" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{807, "MK", "MACEDONIA, FYRO" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{458, "MY", "MALAYSIA" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{470, "MT", "MALTA" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{480, "MU", "MAURITIUS" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{484, "MX", "MEXICO" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{492, "MC", "MONACO" , TRUE, A_BAND_REGION_2, TRUE, G_BAND_REGION_1},
{504, "MA", "MOROCCO" , TRUE, A_BAND_REGION_10, TRUE, G_BAND_REGION_1},
{524, "NP", "NEPAL" , TRUE, A_BAND_REGION_4, TRUE, G_BAND_REGION_1},
{528, "NL", "NETHERLANDS" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{554, "NZ", "NEW ZEALAND" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{558, "NI", "NICARAGUA" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_0},
{578, "NO", "NORWAY" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{512, "OM", "OMAN" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{586, "PK", "PAKISTAN" , TRUE, A_BAND_REGION_4, TRUE, G_BAND_REGION_1},
{591, "PA", "PANAMA" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_0},
{598, "PG", "PAPUA NEW GUINEA" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{600, "PY", "PARAGUAY" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{604, "PE", "PERU" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{608, "PH", "PHILIPPINES" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{616, "PL", "POLAND" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{620, "PT", "PORTUGAL" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{630, "PR", "PUERTO RICO" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_0},
{634, "QA", "QATAR" , TRUE, A_BAND_REGION_4, TRUE, G_BAND_REGION_1},
{642, "RO", "ROMANIA" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{643, "RU", "RUSSIA" , TRUE, A_BAND_REGION_22, TRUE, G_BAND_REGION_1},
{646, "RW", "RWANDA" , TRUE, A_BAND_REGION_4, TRUE, G_BAND_REGION_1},
{682, "SA", "SAUDI ARABIA" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{688, "RS", "REPUBLIC OF SERBIA" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{499, "ME", "MONTENEGRO" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{702, "SG", "SINGAPORE" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{703, "SK", "SLOVAKIA" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{705, "SI", "SLOVENIA" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{710, "ZA", "SOUTH AFRICA" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{724, "ES", "SPAIN" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{144, "LK", "SRI LANKA" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{752, "SE", "SWEDEN" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{756, "CH", "SWITZERLAND" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{760, "SY", "SYRIAN ARAB REPUBLIC" , TRUE, A_BAND_REGION_23, TRUE, G_BAND_REGION_1},
{158, "TW", "TAIWAN" , TRUE, A_BAND_REGION_23, TRUE, G_BAND_REGION_0},
{834, "TZ", "TANZANIA" , TRUE, A_BAND_REGION_4, TRUE, G_BAND_REGION_1},
{764, "TH", "THAILAND" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{780, "TT", "TRINIDAD AND TOBAGO" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{788, "TN", "TUNISIA" , TRUE, A_BAND_REGION_2, TRUE, G_BAND_REGION_1},
{792, "TR", "TURKEY" , TRUE, A_BAND_REGION_2, TRUE, G_BAND_REGION_1},
{800, "UG", "UGANDA" , TRUE, A_BAND_REGION_21, TRUE, G_BAND_REGION_1},
{804, "UA", "UKRAINE" , TRUE, A_BAND_REGION_24, TRUE, G_BAND_REGION_1},
{784, "AE", "UNITED ARAB EMIRATES" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{826, "GB", "UNITED KINGDOM" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{841, "US", "UNITED STATES" , TRUE, A_BAND_REGION_9, TRUE, G_BAND_REGION_0},
{858, "UY", "URUGUAY" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{860, "UZ", "UZBEKISTAN" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_0},
{862, "VE", "VENEZUELA" , TRUE, A_BAND_REGION_7, TRUE, G_BAND_REGION_1},
{704, "VN", "VIET NAM" , TRUE, A_BAND_REGION_2, TRUE, G_BAND_REGION_1},
{887, "YE", "YEMEN" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{716, "ZW", "ZIMBABWE" , TRUE, A_BAND_REGION_1, TRUE, G_BAND_REGION_1},
{999, "", "", 0, 0, 0, 0}
};
设置tx queue的长度: ifconfig wifi0 txqueuelen 1000;
2.创建vap(wlanApVapSetup);
1)构造vap 名称wlanApVapName;wlanconfig ath0 create wlandev wifi0 wlanmode ap
2)设置vap模式wlanSetWirelessMode;iwpriv ath0 mode %s, 这里的模式是字符串,通过计算下标,从下面的数组中取值
static char *QCAwlanMode[] = {
"AUTO",
"11B",
"11G",
"11NGHT20",
"11NGHT40",
"11NGHT40PLUS",
"11NGHT40MINUS",
"11A",
"11NAHT20",
"11NAHT40",
"11NAHT40PLUS",
"11NAHT40MINUS",
"11ACVHT20",
"11ACVHT40",
"11ACVHT40PLUS",
"11ACVHT40MINUS",
"11ACVHT80",
};
3)配置ap参数wlanApConfig a.配置channel ,自动选择信道:
iwpriv ath0 blockdfschan 1; 设置信道:
iwconfig ath0 freq 1;
b.设置SSID,
iwconfig ath0 essid zhouqiqiu1982
c.设置高级参数, 设置是否隐藏ID:
iwpriv ath0 hide_ssid 0; 设置传输功率:
iwpriv ath0 tpscale 1;设置
shortgi,
iwpriv ath0 shortgi 1;设置wmm:
iwpriv ath0 wmm 1;设置加密方式:
iwpriv ath0 htweptkip 0;启用多播snoop
iwpriv ath0 mcastenhance 2
4)
将vap添加到bridge:
brctl addif br0 ath0
5)无线MAC地址过滤初始化wlanMacFiltInit;a. 删除旧的acl, iwpriv ath maccmd 3; b.设置模式 iwpriv ath0 maccmd 0, 0 disable,1,allow, 2, deny;c:插入mac条目:iwpriv ath0 addmac %s;
6)安全设置wlanApSecuritySetup;
有4中安全模式:
a)WEP ,密钥方式2种, open sys: iwpriv ath0 authmode 1; share key:iwpriv ath0 authmode 2; default :iwpriv ath0 authmode 4
b)WPA/WPA2,通过hostapd进程实现,参数配置主要通过配置文件的方式生效而不是使用iwpriv设置,hostapd -B -dd /tmp/wpa-wpa2.conf_ath0;
c)PSK, 和WPA/WEP2一样,也是通过hostapd实现,参数配置主要通过配置文件的方式生效而不是使用iwpriv设置,
hostapd -B -dd /tmp/psk-psk2.conf_ath0
d)无加密: 空,不需做任何处理;
7)生效vap netdevActivate;ifconfig ath0 up
8)生效wps wlanWpsUp; 设置pin :iwpriv ath0 WscVendorPinCode=%s
wps设置比较复杂,后面在看
3.设置guestnetwork(wlanGuestApSetup);
4.设置WPS的vap (wlanWdsVapSetup);
2016.4.12 周二
无线mode错误导致连接失败,要注意get_channel_mode中的模式值计算。
iwpriv ath0 mode 11NGHT20
2016.4.13 周三
分析RPM处理web发出请求的流程:
httpRpmWlan处理read和write请求,read调用_httpRpmWlanGet,write调用_httpRpmWlanSet,
wrpOpGrpDo函数发送请求给ucm,
ucm_msgTaskCreate 这个是uclite中监听51237的函数。
uclite-wifi.c中实现对无线参数的处理,包括reset,读,写。
wrpSockSendRequest 发送请求
串口打印信息:
/tmp # ====>>>>[opWifi_AP_saveCfg:1150]0 != 680 Inconsist inMsgLen!
[WRP][_wrpOpDo:81]Inconsist outMsgLen! opid = b0001 0 != 140
====>>>>[opWifi_AP_saveCfg:1150]0 != 680 Inconsist inMsgLen!
[WRP][_wrpOpDo:81]Inconsist outMsgLen! opid = b0001 0 != 140
====>>>>[opWifi_AP_saveCfg:1150]0 != 680 Inconsist inMsgLen!
[WRP][_wrpOpDo:81]Inconsist outMsgLen! opid = b0001 0 != 140
[17770.792000] FWLOG: [18201195] WHAL_ERROR_RESET_CHANNF1 ( )
[17770.800000] FWLOG: [18201195] WHAL_ERROR_RESET_ERRID ( 0x1 )
[18071.816000] FWLOG: [18509419] WHAL_ERROR_RESET_CHANNF1 ( )
[18071.820000] FWLOG: [18509419] WHAL_ERROR_RESET_ERRID ( 0x1 )
貌似是发送的信息长度是0.跟踪发送函数,看发送的长度。
[util.c:60:utl_file2json]utl_file2json 60 open file = /tmp/device.info
[util.c:60:utl_file2json]utl_file2json 60 open file = /tmp/region.channel.info
[util.c:62:utl_file2json]ERROR 0>(fd = open(filename, 00)) fail
EXPORT_SYMBOL(name);
EXPORT_SYMBOL_GPL(name);
2016.4.14 周四
#define qca_echom(cmd, ...) qca_echo("[%s:%s:%d]"cmd, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
svn添加二进制文件so,需要使用svn add --force
2016.4.15 周五
Wireless Extension (WE)是一组通用的API,能在用户空间对通用Wireless LANs进行配置和统计。它的好处在于仅通过一组单一的工具就能对各种各样的Wireless LANs进行管理,不过它们是什么类型,只要其驱动支持Wireless Extension就行;另一个好处就是不用重启驱动或Linux就能改变这些参数。
Wireless tools for Linux是一个Linux命令行工具包,用来设置支持Linux Wireless Extension的无线设备。
Wireless Tools (WT)就是用来操作Wireless Extensions的工具集,它包括以下工具:
iwconfig:设置基本无线参数
iwlist:扫描、列出频率,比特率,密钥等
iwspy:获取每个节点链接的质量
iwpriv:操作Wireless Extensions 特定驱动
2016.4.18 周一
今天感觉很累,可能是昨晚踢球造成的
今天主要是看QCA无线参数设置部分,发现现在的无线参数设置不能生效,是因为qca中缺少了这部分的处理。在代码中通过wifi restart是无线参数重新生效,而wifid中需要实现restart的响应部分。
2016.4.19 周二
opWifi_init(UCL_MOD_INDEX iModIndex)
{
int ret = 0;
ret = ucl_op_addUcMod(iModIndex, ucWifiInfo);
ret |= ucl_op_addMod(iModIndex, opWifiFun);
return ret;
}
nm_api_readPtnFromNvram 函数读取分区信息
#define WIFI_BAND_MODE_SELECTIVE 0
#define WIFI_BAND_MODE_2G 1
#define WIFI_BAND_MODE_5G (1 << 1)
#define WIFI_BAND_MODE_CONCURRENT 3
ifrename: 基于各种静态标准命名接口
bandmode和band是不一样的含义,bandmode是设置的模式,1表示2G,2表示5G,band是数据结构中数组的下标,0表示2G,1表示5G。
使用时需要转换一下。
2016.4.20 周三
整理了Linuxplat无线初始化的过程,整理详细后写成blog,wifi版上的无线是不能连接的,样机的可以。
2016.4.21 周四
上传了代码。
Channal With分为20MHz和40MHz,这个选择直接影响无线的Bit Rate参数,20MHz对应是144.4Mb/s,40MHz对应是300Mb/s
2016.4.22 日 周五
今天继续添加qca的无线部分功能,增加stop,和准备添加5G的支持。加密暂时先不添加。
重新看了uboot的实现,昨晚看了协处理器和在汇编中初始化的过程,今天将流程整理了一下,很多原来不明白的地方也弄明白了,后面写个文档。
2016.4.25 周一
实现WEP加密,测试。WEP加比较简单,首先
通过iwpriv ath0 authmode 1 设置认证方式,
WEP_AUTH_OPEN_SYS
1
WEP_AUTH_SHARED_KEY 2
WEP_AUTH_AUTO 4
然后通过命令iwconfig 命令设置密钥,密钥分为16进制和ACS码,两种格式命令不一样
16机制密钥:iwconfig %s key [%d] %s
ACS密钥:iwconfig %s key [%d] s:%s
最后设置key的 index
iwconfig %s key [%d]
2016.4.26 周二
2016.4.27 周三
DFS 需要计算信道,大概需要1分钟,这样导致5G的bit rate在这1分钟内为0;可以通过Makefile中的DFS宏进行控制。
WPA2 有两种风格:WPA2 个人版和 WPA2 企业版。WPA2 企业版需要一台具有 IEEE 802.1X 功能的 RADIUS (远程用户拨号认证系统) 服务器。没有 RADIUS 服务器的 SOHO 用户可以使用 WPA2 个人版,其口令长度为 20 个以上的随机字符,或者使用 McAfee 无线安全或者 Witopia Secure MyWiFi 等托管的 RADIUS 服务。
2016.4.28 周四
WEP用以保护数据的RC4秘密(cipher)属于对称性流密码,流密码用到称之为密钥流的位流,密钥流随后和信息结合,产生密文。为了还原原始信息,接收端会以相同的密钥流处理密文。RC4会利用异或(XOR)运算结合密钥流和密文。
流密码的与做方式通常是选用一把较短的密钥,然后将之展开成和信息等长的伪随机密码流。伪随机数生成器(pseudoradom number generator,PRNG)是一组用来将密钥展开为密钥流的规则。为了还原数据,收发双方必须拥有相同的密钥,并且使用相同的算法将密钥展开为伪随机数序列。
简单的过程就是:
Source Data---->Keystream---->Cipher stream---->Keystream---->Received data.
而Keystrem 是通过key 和Cipher PRNG生成的。
RC4加密算法是大名鼎鼎的 RSA
三人组中的头号人物Ron Rivest在1987年设计的密钥长度可变的流加密算法簇。只有授权才能使用RSA RC4的源代码。现在主要的无线芯片厂家取得RSA RC4的算法授权,并且将其继承到802.11芯片组,就是说该算法已经有硬件实现,上层的软件不需要担心授权问题。所以实现比较简单
EAP: 802.1X的基础是EAP(Extensible Authentication Protocol),EAP是一种框架协议,EAP本身未规范如何识别用户,但是允许协议设计人员打造自己的EAP认证方式。EAP是一种简单的封装方式,可以运行与任何的链路层,协议号是0xC227。
1)设置身份认证方式
iwpriv %s authmode 1, 1是开放是系统,2是共享密钥;
2)设置key,key分为acs码和16进制数两种
16进制:iwconfig %s key [%d] %s 接口名称,key序号,key值
ACS码:iwconfig %s key [%d] s:%s
3)设置生效的key
iwconfig %s key [%d]
WPA (Wi-Fi Protected Access, Wi-Fi 保护访问)
WPA2 (WPA 第二版) 是 Wi-Fi 联盟对采用 IEEE 802.11i 安全增强功能的产品的认证计划。简单一点理解,WPA2是基于WPA的一种新的
TKIP:Temporal Key Integrity Protocol(临时密钥完整性协议),被设计来尽可能强化pre-802.11i硬件安全性。TKIP保留了WEP的基本结构和操作方式,因为它本来就是一个设计来升级基于WEP的解决方案的软件;可以理解TKIP是对WEP的增强版;
AES:Advanced Encryption Standard(高级加密标准),安全性比 TKIP 好,推荐使用。
加密方式。
WPA = IEEE 802.11i draft 3 =IEEE802.1X/EAP+WEP(选择性项目)/TKIP WPA2 = IEEE 802.11i = IEEE802.1X/EAP+WEP(选择性项目)/TKIP/CCMP
CCMP(Counter CBC-MAC Protocol) 计数器模式密码块链消息完整码协议。CCMP主要是两个算法所组合而成的,分别是CTR mode以及CBC-MAC mode。CTR mode为加密算法,CBC-MAC用于讯息完整性的运算
WPA的实现需要适应开源软件hostapd
hostapd 是一个用户态用于AP和认证服务器的 守护进程
。它实现了IEEE 802.11相关的接入管理,IEEE 802.1X/WPA/WPA2/EAP 认证, RADIUS客户端,EAP服务器和RADIUS 认证服务器
需要构造hostapd的配置文件:
interface=ath0
bridge=br0
driver=atheros
logger_syslog=-1
logger_syslog_level=2
logger_stdout=-1
logger_stdout_level=2
dump_file=/tmp/hostapd.dump
ctrl_interface=/var/run/hostapd
ctrl_interface_group=0
ssid=TP-LINK_7B00_1111
max_num_sta=255
ignore_broadcast_ssid=0
wmm_enabled=1
wmm_ac_bk_cwmin=4
wmm_ac_bk_cwmax=10
wmm_ac_bk_aifs=7
wmm_ac_bk_txop_limit=0
wmm_ac_bk_acm=0
wmm_ac_be_aifs=3
wmm_ac_be_cwmax=10
wmm_ac_be_cwmin=4
wmm_ac_be_txop_limit=0
wmm_ac_be_acm=0
wmm_ac_vi_aifs=2
wmm_ac_vi_cwmax=4
wmm_ac_vi_cwmin=3
wmm_ac_vi_txop_limit=94
wmm_ac_vi_acm=0
wmm_ac_vo_aifs=2
wmm_ac_vo_cwmax=3
wmm_ac_vo_cwmin=2
wmm_ac_vo_txop_limit=47
wmm_ac_vo_acm=0
auth_algs=1 /*以上是公共部分*/
wpa=3
wpa_pairwise=CCMP
rsn_pairwise=CCMP
wpa_key_mgmt=WPA-PSK
wpa_passphrase=12345670
wpa_group_rekey=0
然后调用hostapd服务就可以了:hostapd -B -dd %s
%s是配置文件路径。
wifi
macreload
# iwpriv ath0 getmac
ath0 getmac:14:CC:20:16:FB:DA
14:CC:20:16:FB:DB
2016.4.29 周五
主要MAC地址两种格式的转换,一个是MAC[6] 6字节的格式,一种是字符串格式。
2016.5.5 周四
LinuxPlat中athrs27_phy_is_up 中设置LED的的up/down状态,但是model_qca中通过
export GMAC_QCA953x=1 该宏决定以太网中使用那个95xx.c文件,在LinuxPlat中,通过scrip目录中的board953x目录文件config.board953x进行设置,而这个script目录在prereq.mk脚本中通过编译命令中的board_type进行映射。
2016.5.6周五
5G 频率分为4个band,
(Band 1 ,Band 2,Band 3,Band 4),
5150MHz-5250MHz
5250MHz-5350MHz
5470MHz-5725MHz
5725MHz-5850MHz
每个band对应的信道范围不一样,band1是36,40,44,48,band2 band3需要DFS认证,band1和band4不需要;
2016.5.9 周一
网桥设备br0如果没有通过ifconfig 命令设置MAC地址,那么其MAC地址使用最后加入网桥的设备的MAC地址;
hostapd 会修改ssid。
2016.5.10 周二
2016.5.11周三
根据国家的ISO简写在qca_allCountry中查找该国家11AC支持的band值,不同国家不同的band值不同,得到band值后在wlan5GChannelTable中获取对应的信道数组;
11n有两种频宽模式:HT(High Throughput)20和HT40。
HT20是出于兼容性考虑:比如,一个区域内存在11b/g信号,那么为了尽量减少对它们的干扰,需要设定为HT20,以减少频带的重叠。
HT40是出于高性能考虑:HT40相当于两个HT20的捆绑,一个是主,一个是辅。主信道发送beacon报文和部分数据报文,辅信道发送其他报文。
由于HT40所需带宽为40M,在一个蜂窝式无线覆盖区域最好不要在2.4GHz使用,最好在5GHz使用。
在2.4G使用HT40,则有效通道有3~13,非重叠的只有3,11
2016.5.13 周五
11N 11GN 11BGN都使用模式11NGHT40PLUS,然后根据信道,大于等于6选择下偏,小于6信道上偏;
2016.5.16 周一
#define WIFI_CONFIG_MAC_FILTER (1 << 1)
#define WIFI_CONFIG_GUEST_NETWORK (1 << 2)
#define WIFI_CONFIG_PARENT_CTRL (1 << 3)
#define WIFI_CONFIG_REGION (1 << 4)
wifi命令由发送changecfg的命令,并且该命令会将cfg的类型作为status发送,但是接收的qca_event_handler并没有对changecfg命令类型的处理。
2016.5.20 周五
_ucWifi_cfg2Json中构造一个wifi.config文件,这个文件的格式是一个json。文件中的每一节用cJSON结构表示,包括字节和根,根需要申请
cJSON *root = cJSON_CreateObject();
然后各个字节添加到跟中
cJSON_AddItemToObject(root, "2G_Cfg", bandCfg[band]);
cJSON_AddItemToObject(root, "5G_Cfg", bandCfg[band]);
允许在字节中添加:
cJSON_AddItemToObject(bandCfg[band], "advCfg", advCfg[band])
对于长度为的数组,在gcc手册中,有如下一段代码片段:
struct line {
int length;
char contents[0];
};
struct line *thisline = (struct line *)malloc (sizeof (struct line) + this_length);
thisline->length = this_length;
这段代码的主要含义是定义了一个结构体,并对其进行初始化,上面结构体的第二个成员变量contents[0]事实上是不占内存空间的,因此整个结构体的长度sizeof(struct line)为4。当采用malloc为其申请内存空间时,如上所示,申请了一段长度为结构体长度加可变长度的内存空间给结构体类型的指针,这时contents就指向申请的可变长度的内存空间。由于是一次申请的,所以这段可变长度的内存空间和前面的结构体长度的内存空间是连续的。对于这段可变长度的内存空间,可以采用数组的方式对其进行访问。对于整个结构体,当不再使用时,可以使用free函数一次性对其进行释放,而不必像指针那样分别释放。
2016.5.23 周一
测试4220无线部分功能,阅读9533 2.0 datasheet。
在kernel驱动中,linux\kernels\mips-linux-2.6.31\arch\mips\include\asm\mach-atheros定义了寄存器地址。
2016.5.24 周二
上午例会,TR069的介绍。下午测试4220的无线,出4230的ECO.
2016.5.25 周三
2016.5.26 周四
测试访客网络,发现sta和sta之间的禁止和允许互访有问题,原因是设置参数时需要通过iwpriv ath1 ap_bridge 1 进行设置连接到同一ap之间的sta是否允许互相访问
另外,在br_guest_filter中要禁止来自guest network的sta对local network的访问。(这一点不能实现,因为有可能LAN端了解外网的Router)
[ 96.912000] eth0: received packet with own address as source address
[ 98.760000] eth0: received packet with own address as source address
[ 104.768000] eth0: received packet with own address as source address
[ 111.776000] eth0: received packet with own address as source address
[ 116.936000] eth0: received packet with own address as source address
[ 120.784000] eth0: received packet with own address as source address
2015.5.30 周一
跟踪wifi sched 功能时发现勾选有客户端连接时,不允许关闭wifi功能有问题,发现从jason中读取的参数有问题
~ # cat /config/wifiSched.config
{
"enable": 1,
"type": 1,
"entrySize": 1,
"Entry": [{
"stime": 0,
"etime": 1,
"days": 127,
"enable": 1
}]
}
~ # ====>>>>[/home/project/plc_platform/tp-software/develop/private/apps/wifiSched/src/wifiSched.c:_mainloop:946][_mainloop:946] call wifiSched_mainProc
====>>>>name = enable, node->valueint = 1
====>>>>name = type, node->valueint = 1
====>>>>[wifiSched_conf.c:_WifiSched_getData_fromJson:135][_WifiSched_getData_fromJson:135] wifiSchedCfg->offType = 0, wifiSchedCfg->enabled = 1
====>>>>[wifiSched_conf.c:_WifiSched_getData_fromJson:137][_WifiSched_getData_fromJson:137] wifiSchedCfg->offType = 0, wifiSchedCfg->enabled = 1
文件中的offType是1,但是读到结构中的是0,
原因是_get_jsonNumber中的参数发送了强制转换,
_get_jsonNumber(cJSON *data, const char *name, int *cfgEntry),
int *cfgEntry参数如果传入的是UINT8,那么在函数调用是进行了强制类型转换,UINT8型指针转成int32 型指针,qca是大端,所以负责到int指针的内存最高8bit,函数返回是,指针是内存的低8位,并没有赋值。
BOOL _get_jsonNumber(cJSON *data, const char *name, int *cfgEntry)调用时的一个bug,如果使用这个函数直接读取jason中一个UINT8类型的变量,会出现在大端字节顺序下因为强制类型转换而参数读取错误的问题。
具体是,读取wifi_sched中
offType字段
typedef struct {
BOOL enabled;
UINT8 offType;
TIME_CTRL_ENTRY entry[TIME_CTRL_ENTRY_MAX_SIZE];
int timeCtrlEntrySize;
} WIFI_SCHED_MOD_DATA;
时,直接使用如下方法:
_get_jsonNumber(data, "type", &wifiSchedCfg->offType); 调用时参数类型进行了强制转换,在函数_get_jsonNumber内部,是int的指针,大端顺序下赋值是对内存的最高8bit进行赋值,函数返回后,指针变回UINT8,指向低8bit。所以参数没有读出来。
可以通过临时变量读取
int tmp = 0;
_get_jsonNumber(data, "type", tmp);
wifiSchedCfg->offType = tmp;
一个数据结果定义如下:
typedef struct {
int enabled;
unsigned char type;
int size;
unsigned char name[8]
} MY_STRUCT;
然后定义一函数接口,本意是对MY_STRUCT中的int类型和string进行读取,这里函数接口的作者忽视了unsigned char,视为int类型
_get_my_struct_data(
MY_STRUCT *pD
ata, char *pName, int *
cfgEntry
)
{
...
*
cfgEntry
=
pD
ata->type;
...
}
然后调用:
MY_STRUCT cfg;
_get_my_struct_data(&initCfg
, "type", &
cfg.
type
); /*initCfg是一个全局的变量,initCfg.type = 1,这个并不是关键,关键是第三个参数
&
cfg.
type
*/
printf("
cfg.
type = %d\r\n
",
cfg.
type
); 发现值为0,而不是1;
为什么?
首先说明的 是这代码在大端字节顺序的cpu上运行,第三个参数
&
cfg.
type的地址原来是一个unsigned char类型,而到了函数内部变成了int类型,假设这个地址是a,那么在函数内部,由于大端字节顺序,数据高位置,放在内存低处,
所以内存分布如下:
+++++++++++++++++++
| a | a+1 |a+2| a+3 |
+++++++++++++++++++
赋值
*
cfgEntry
=
pD
ata->type;只对a+3 写入设置1,其他的还是0;而函数返回后打印是unsigned char类型,只是地址a的值,该数值是0;
如何避免这种不细心的函数参数类型强制变化导致的错误,第一,在函数接口定义和使用的时候要严格按照类型进行,第二,不要忽视编译过程的警告
warning: passing argument 3 of '
_get_my_struct_data
' from incompatible pointer type
或者在编译中使用
Werror参数将编译警告视作错误
2016.5.31
excess elements in struct initializer
discards qualifiers from pointer target type
struct in_addr tmpAddr;
tmp.s_addr = dhcpcCfg.ulIp;
inet_ntoa(tmpAddr);
2016.6.1
-Os 对生成文件大小进行优化。它会打开 -O2 开的全部选项,除了会那些增加文件大小的。
assignment discards qualifiers from pointer target type: 参数类型不一样
incompatible implicit declaration of built-in function 'strncpy'
ath_beacon_tasklet(sc, &needmark);发送becon的任务;
ath_pci_driver 设备驱动,当中的ath_pci_probe用于探测当前总线上挂载的设备。
ath_pci_probe:创建网络设备wifi0,
dev = alloc_netdev(sizeof(struct ath_pci_softc), "wifi%d", ether_setup);然后就是调用
__ath_attach函数进行绑定;
__ath_attach: 绑定处理函数接口,初始化中断:error = request_irq(dev->irq, ath_isr, SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
最后调用ath_hal_probe
__ath_attach中调用了
ath_attach,然后
ath_beaconq_setup:设置beacon的发送队列。
Remote Authentication Dial-In User Service
(
RADIUS
) is a networking protocol
that provides centralized Authentication, Authorization, and Accounting ( AAA
or Triple A) management for users who connect and use a network service
2016.6.12 周日
端午后第一次上班,解决无线6信道上偏问题,原因是使用了配置中的无线信道参数进行mode的选择,而不是计算后的随机信道。cca问题还没有确定。
2016.6.14 周二
在软件中增加ethreg的命令,busybox版本不一样,新平台使用的busybox版本是1.19.4,而旧平台是1.01,暂时将旧平台的替换,只能本地搞搞。
编译4220eu,通过宏RELEASE=us进行区分,buildserver的编译脚本要重新写,调试很慢;
使用
wlanconfig ath0 list查看关联到ap上的sta,发现sta关联后如果直接关闭wifi,ap中还保留sta信息一段时间,然后老化,这个后面看看驱动总如何管理node
2016.6.17 周五
上午遇到一个字符串赋值并保存的问题,一般我们印象中的字符串是可见的字符串,就是通过printf可以打印出来的。但是有时候我们通过字符串存储的并不一定是可见字符,比如:
str3[0] = 0;
str3[1] = 1; 这中方式的赋值
简单地,尝试打印ascii表,发现只能从31开始输出可见字符
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
2016.6.20 周一
在函数ieee80211_ifattach 中初始化定时器:
OS_INIT_TIMER(ic->ic_osdev, &(ic->ic_inact_timer), ieee80211_inact_timeout, (void *) (ic));该定时器15秒触发一次;
2016.6.21 周二
指针数组的长度
const char * hwmode_2g[5]= {"b","g","n","gn","ng"};
printf("%s %d: size = %d, num = %d\r\n", __FUNCTION__, __LINE__, sizeof(hwmode_2g), sizeof(hwmode_2g)/sizeof(const char*));
结果是:main 278: size = 20, num = 5
在无线设置页面中增加11b和11g的选项,需要修改wireless.region.json文件,这个文件是用来初始化页面选项的;还有webserver中hwmode_2g指针数组,这个是返回数据的。
断开连接但是DUT的驱动没有注销node,是因为网卡使用的是抓包的驱动,DUT中的调用free node的函数条件不成立。
if (ieee80211_node_dectestref(ni)) 这个条件不成立,导致没有调用_ieee80211_free_node函数
2016.6.23 周四
4220提测前编译软件,在buildserver上编译,发现很慢,原因是代码检查时需要检查MTK和BCM的代码,后面需要将这3个分开;
更新了checklist,重新自测,发现PLC部分修改网络名字失败,已经反馈;自测了Wi-Fi克隆,没什么问题。
当无线驱动绑定后,驱动会为这些设备请求一个中断并且注册一个中断服务例程,驱动同时初始化一个叫ath_tasklet的任务队列用于处理下半部。这个中断首先通过扫描来之无线硬件的不确定的中断检测是否是无线硬件的中断,一旦中断被确认是一个无线中断,他就会调度任务队列延迟处理通过中断状态寄存器。有一些时序严格要求的处理程序比如软件beacon警告处理和UAPSD触发处理需要在ISP上下文处理外。一些这些时序严格要求的处理函数可以通过编译时间选项要求可以在任务队列中执行。在中断例程的最后,如果tasklet被调度,所有的无线设备中断将会被禁止除了那些时序严格要求的服务例程的中断;
2016.6.24 周五
今天提测了4220,剩下的时间就是看无线驱动文档和代码,发现有时候很难长时间集中精力。
2016.6.27 周一
MLME:
MLME是 MAC Sublayer Management Entity,MAC子层管理实体。物理层(PHY)MAC状态机就位于MLME中。
在函数osif_vap_setup中调用函数wlan_vap_register_event_handlers(vap,&common_evt_handler);注册common_evt_handler,在common_evt_handler收发数据包的函数;
ni = ieee80211_find_txnode(vap, daddr); 根据目的地址查找该包发送到的目的node。
2016.6.29 周三
上午讨论关于iptables中关于NAT表执行优先级的问题,在prerouting链中,DNAT是在最后执行的,在conntrack中会根据连接跟踪的转台进行包的处理。
下午看新平台mtk的无线部分的代码,发现iwpriv命令和qca的完全不一样,而且支持的参数很少,传输功率的页面实现和实际设置的值是否对应上,这个要注意一下,测试了速率,WLAN2LAN可以到达87Mbps,还可以。
2016.6.30 周四
1)4530的信道选择auto,代码中使用命令设置为自动iwpriv %s%d set AutoChannelSel=2
2)开启了telnet功能;
3)无线传输功率的默认值错误,默认是middle,应该为high;
4)wifi-clone不会克隆前端Rootap的信道;
5)wifi-clone后,Rootap和DUTAP使用相同的SSID,但是无线客户单接入时,接入到的是RootAP的SSID;
6)连接到同一sta的访客网络的guest,如果不允许相互间的访问,是通过命令设置无线驱动,qca通过:iwpriv %s ap_bridge %d mtk通过:iwpriv %s%d set NoForwarding=%d,然后不同guest间的通过br_guest_filter.ko中实现。
2016.7.4 周一
在buid server上编译MTK的机型4530时,发现在编译云平台是,configure文件出现错误,但是奇怪的是在本地编译和在buildserver后台编译也是没问题的,在buildserver上编译qca也没有问题。而错误出现的地方:
Running make clean...
yes
./configure: line 28921: syntax error near unexpected token `done'
./configure: line 28921: `done'
也很奇怪,在configure文件中这一行的内容并不是done。编译过程中实际的configure文件并不是svn上的文件,而是通过auto config生成的文件
Generated by GNU Autoconf 2.63 for wolfssl 3.9.0.
实战Makefile.am
Makefile.am是一种比Makefile更高层次的规则。只需指定要生成什么目标,它由什么源文件生成,要安装到什么目录等构成。
表一列出了可执行文件、静态库、头文件和数据文件,四种书写Makefile.am文件个一般格式。
表 1Makefile.am一般格式
对于可执行文件和静态库类型,如果只想编译,不想安装到系统中,可以用noinst_PROGRAMS代替bin_PROGRAMS,noinst_LIBRARIES代替lib_LIBRARIES。
Makefile.am还提供了一些全局变量供所有的目标体使用:
表 2 Makefile.am中可用的全局变量
在Makefile.am中尽量使用相对路径,系统预定义了两个基本路径:
表 3Makefile.am中可用的路径变量
2016.7.5 日
今天在buildserver上跟进MTK编译的问题,发现直接checkout后,直接编译是会出现configure退出问题,但是如果编译一次失败,然后修改svn的源码管理为none,编译第二次,发现是可以的。
2016.7.6 日
以太网的收发包buf的大小居然在wireless.conf中定义, busybox中没有定义btctl,而文件系统中的brctl是一个完整的bin。文件系统是由build拷贝到board
export INSTALL_ROOT := $(IMAGEPATH)/rootfs.build
export INSTALL_ROOT_FOR_BOARD := $(IMAGEPATH)/rootfs.board
@cp -Rf $(INSTALL_ROOT) $(INSTALL_ROOT_FOR_BOARD)
2016.7.8 日周五
准备4225(FR)项目的编译选项,该项目和4220是一样的方案,所以image目录下可以共用,但是需要修改文件名字;测试发现备份功能和升级功能页面打不开,咨询王成君,是应为文案存在缺漏,导致缺少一些字段;
2016.7.13 周三
今天验证4220无线双LAN到WLAN速率刚开始时出现的速率骤降问题,对比过4230,也发现类似的问题,考虑单LAN口到WLAN没有,怀疑是打开流控导致的问题,另外可以使用high throughput脚本进行测试。
2016.7.20 周三
今天准备提测4220,但是发现svn上日志的提交时间比实际上传的时间早了1小时,导致buildserver更新不到最近一小时内的修改。
2016.7.21 周四
今天将uboot的初始化过程重新整理了一下,编写文档。
2016.7.25 周一
MIPS 起始地址是0xbfc00000,会有4Mbyte的大小限制,但一般MIPS芯片都会采取一些方法解决这个问题。
MIPS24K 起始地址改到了0xbf000000,现在有16Mbyte的空间了。
2016.7.26 周二
EU和UK的软件共用要考虑硬件(主要是灯)是否有做兼容设计,插座方向是反的。
2016.7.27 周三
11n有两种频宽模式:HT(High Throughput)20和HT40。
HT20是出于兼容性考虑:比如,一个区域内存在11b/g信号,那么为了尽量减少对它们的干扰,需要设定为HT20,以减少频带的重叠。
HT40是出于高性能考虑:HT40相当于两个HT20的捆绑,一个是主,一个是辅。主信道发送beacon报文和部分数据报文,辅信道发送其他报文。
由于HT40所需带宽为40M,在一个蜂窝式无线覆盖区域最好不要在2.4GHz使用,最好在5GHz使用。
在2.4G使用HT40,则有效通道有3~13,非重叠的只有3,11.
11na_ht20代表802.11na的20兆频宽,连接速率有130M,11na_ht40代表802.11na的40兆频宽,连接速率有300M。由于802.11n有个特性是40M频宽,该频宽是通过以前的两个20M信道叠加起来后生成的,并且叠加时两信道一个是主信道一个是副信道,这里的plus和minus都是针对主信道说的,所以11na_ht40plus代表40M频宽时的2个信道叠加向上加的叠加,例如当前信道是149,配成40M频宽需要叠加另外一个信道,就是149+153两个信道组成的40MHz频宽,11na_ht40minus代表信道叠加时是向下减的叠加,例如配了这个,信道161,就等于是161+157组成了40M频宽的新信道。
802.11g也如a是一样的意思,只不过。由于802.11g只有1、6、11这3个信道,所以使用40M频宽的信道时只剩下了一个不重叠信道,所以在使用802.11ng时,不建议使用40MHz的频宽,使用默认的20MHz频宽即可。
2016.8.2 周二
在函数wmnetTcpAccept中accept的socket设置了FD_CLOEXEC,表示对于这个socket,在执行exec函数时是关闭的。
mudConnPeek 接收数据包函数
httpServerRequestHandler 处理请求的函数
2016.8.8 周一
使用pktlog抓包步骤:
1.加载ath_pktlog.ko;
2.pktlogconfig -a wifi0 -s 0 清空缓存;
3.设置缓存大小pktlogconfig -a wifi0 -s 10485760 (10M) 这个内存太小,只能抓几秒的包;
4.关闭原有的统计功能 iwpriv wifi0 disablestats 0;
5.pktlogconfig -a wifi0 -e 开始抓包
6.pktlogconfig -d wifi0 停止抓包
7.进入目录cd /proc/ath_pktlog
8.tftp -p -l wifi0 -r pktlog 192.168.0.100
后面就用脚本分析pktlog文件。
2016.8.11 周四
测试家长控制对有线和无线的限制
1)登录的管理界面的主机不能设置控制自己的MAC
2)对于有线的主机,可能控制访问DUT的管理IP,但是不能管控外网的访问;
3)对无线的主机,可以管控访问DUT和访问外网;
2016.8.12 周五
uclOpModInitArray 模块初始化表,定义各个模块的初始化函数和序号;
2016.8.17 周三
uclited 中的_msgDoUi 函数处理http发来的请求
2016.8.18 周四
iwpriv wifi0 disp_tpc 1 查看发送功率
2016.8.24 周三
ahCmnRegDomainPairs根据国家码编号,确定2.4G和5G使用什么标准,其中world 对应的ETSI标准,就是CE的标准;
RTMPDeQueuePacket
2016.9.20 周二
跟进无线关联不上的问题,bug 135026发现是因为在11信道时,无线网卡在认证关联后,DUT 没有发出EAPOL key包,导致4次握手超时,问题反馈给MTK。
在MTK的驱动中,函数RTMPSetProfileParameters用于解析/tmp/wireless/RT2860.dat配置文件,当中有参数AutoChannelSkipList用于表示自动信道时跳过的信道列表,最多可以支持10个信道。
2016.9.21 周三
无线自动选择信道需要时间,大概6s
[2016:09:21:11:44:17]wifid[wifi_exec_cmd:491]: insmod /lib/modules/2.6.36.x/kernel/MT7610_ap.ko
[2016:09:21:11:44:19]ESW: Link Status Changed - Port3 Link UP
[2016:09:21:11:44:19]wifid[wifi_exec_cmd:491]: ifconfig ra0 up
[2016:09:21:11:44:20][PLCD_LOG][main:627]: start plcd OK!
[2016:09:21:11:44:20]ESW: Link Status Changed - Port1 Link UP
[2016:09:21:11:44:25]0x1300 = 00064300
[2016:09:21:11:44:25]wifid[wifi_exec_cmd:491]: brctl addif br0 ra0
在驱动初始化是调用pAd->CommonCfg.Channel = AP_AUTO_CH_SEL(pAd, pAd->ApCfg.AutoChannelAlg);自动选择信道;
2016.9.22周四
MTK的自动信道选择有两种方法,一种以信道上存在多少个AP和和脏数据,选取最少干扰的信道(SelectClearChannelApCnt
),另外一种是根据和RSSI计算dirtyness(
SelectClearChannelCCA
),
SelectClearChannelApCnt:2.4G 下偏信道,2.4G信道每个信道的带宽是5M,如果带宽是40MHz,避免信道干扰的偏移值是8M,4M主信道+4M第二信道;如果是20M带宽,则是4MHz。
下偏:
for (ll = channel_index + 1; ll < (channel_index + ChanOffset + 1); ll++)
{
if (ll < MAX_NUM_OF_CHANNELS)
pChannelInfo->dirtyness[ll]++;
}
上偏:
for (ll = channel_index - 1; ll > (channel_index - ChanOffset - 1); ll--)
{
if (ll >= 0)
pChannelInfo->dirtyness[ll]++;
}
选择规则:1)选取dirtyness 为 0 的信道;2)如果选不到,选取没有干扰的信道 dirtyness=30;3)如果选不到,选取最小干扰的信道,dirtynes=31或者32,如果有多个,选取最小RSSI的;4)如果选不到,随机选取;
SelectClearChannelCCA:
接收灵敏度 Rssi,高 > -50dbm, 低 < -80dbm, 中: -80dmb ~-50dbm;
检查相邻信道并计算dirtyness
/* check neighbor channel */
for (loop = (channel_idx+1); loop <= (channel_idx+AboveBound); loop++)
{
if (loop >= MAX_NUM_OF_CHANNELS)
break;
if (pAd->ChannelList[loop].Channel - pAd->ChannelList[loop-1].Channel > 4)
break;
pChannelInfo->dirtyness[loop] +=
((9 - (loop - channel_idx)) * 4);
}
/* check neighbor channel */
for (loop=(channel_idx-1); loop >= (channel_idx-BelowBound); loop--)
{
if (loop < 0)
break;
if (pAd->ChannelList[loop+1].Channel - pAd->ChannelList[loop].Channel > 4)
continue;
pChannelInfo->dirtyness[loop] +=
((9 - (channel_idx - loop)) * 4);
}
选择规则1)在False_CCA小于100的范围内,选择最小dirtyness的信道;2)在False_CCA > 100的范围内,选在falsecca最小的信道;3)如果选不到,随机选择;
在执行设置无线自动信道的时候,有5s时间是终止了MSDU的,所以在这个时间段内无线是无法响应sta的请求的。
[2016:09:22:17:21:56]~ # iwpriv ra0 set AutoChannelSel=2
[2016:09:22:17:21:56]APMlmeScanReqAction 1370 call RTMPSuspendMsduTransmission
[2016:09:22:17:21:56]RTMPSuspendMsduTransmission 2344 SCANNING, suspend MSDU transmission ...
[2016:09:22:17:22:01]~ # RTMPResumeMsduTransmission 2395 SCAN done, resume MSDU transmission ...
2016.9.23 周五
kernel中去掉
CONFIG_LBDAF=y
CONFIG_XFRM=y
CONFIG_INET_TUNNEL=y
CONFIG_FUSE_FS=y
后,kernel使用内存大小为:9072KB,省了84KB;
2016.10.8 周六
堆内存优化
1.堆内存最小单位16字节,尽量减少小块内存的申请,避免内存浪费;
2.调整M_MMAP_THRESHOLD,降低mmap的门槛,降低内存存在风洞的风险,但是会增加系统调用,性能减低;
3.调整M_TRIM_THRESHOLD,减少堆顶连续内存门槛,释放更多堆顶内存;
4.使用mtrace来跟踪内存的调度,使用hook函数以及backtrace函数,找到大内存的分配;
除了strip外,可以通过objcopy -R 命令将不需要的session去除,达到程序瘦身的目标。比如:
objcopy -R .comment -R .note.ABI-tag -R .gnu.version app app1 这个命令将app中的.commemt .note.ABI-tag-R .gnu.version三个session去掉。
减少数据段的方法:
1.将只读的全局变量,加上const,从而使其转移到代码段;
2.去除该全局变量;
3.减少全局变量的尺寸;
减少死代码,编译时带上-Wall 选项,去除unused variable 'i'之类的警告,有助于减少代码段占用的内存;
编译成库文件
gcc -fPIC -shared a.c -o liba.so
线程退出后,进程需要调用函数pthread_join结束,否则为每个线程分配的栈空间不会释放;
Linux内核中文件预读算法:对于每个文件的第一个请求,系统读入所请求的页面并读入紧随其后的少数几个页面,一般是3个;这个预读成为同步预读,对于第二次请求,如果所读页面不在Cache中,既是不在前次预读的group中,则表明文件访问不是顺序访问,系统继续采用同步预读; 如果所读页面在cache中,则表明预读命中,操作系统把预读group扩大一倍,并杨底层文件系统读入group中剩下不在Cache中的文件数据块,这是的预读成为异步预读。
内存回收过程中还有两个重要的方法,一个是LMR(Low on memory reclaiming),另外一个是OMK(Out of Memory Killer)。当分配内存失败的时候LMR会将会起作用,失败的原因是kswapd不能提供足够的空余内存,这时LMR每次释放1024个垃圾页直到内存分配成功。当LMR不能快速释放内存的时候,OMK就开始起作用,OMK会采用一个选择算法来杀死某些今晨。当选定进程时,就会发送SIGKILL信号,这就会使内存立即被释放。OMK选择进程的方法:
1)进程占用大量的内存;
2)进程只会损失小量工作;
3)进程具有低的静态优先级;
4)进程不属于root用户;
2016.10.13 周四
连接运算符##可以把两个独立的字符串连接成一个字符串。
#define SORT(X) sort_functon ## X
SORT(3)(array, elements, element_size); 展开后等于:sort_function3(array, elements,element_size);
将main函数的参数复制,当中使用了二维指针,值得学习
new_argv = (char **) calloc(argc + 1, sizeof(char*));
for (i = 0; i < argc; i++)
{
new_argv[i] = (char*)malloc(strlen(argv[i] +1));
strcpy(new_argv[i], argv[i]);
}
栈是存放函数所有动态局部变量和函数调用和返回的有关信息的一块内存;堆是供malloc,calloc和realloc等函数获取内存空间的一块内存;
把数组传给函数时,有值传递和地址传递两种方式,在值传递方式中,在说明和定义函数时,要在数组参数的尾部加上一对方括号([]),调用函数只需要将数组的地址(数组名)传递给函数。
void byval_func(int[]);
void main(void)
{
int x[10];
int y;
for (y = 0; y < 10; y++)
{
x[y] = y;
}
byval_func(x);
}
void byval_func(int i[])
{
int y;
....
}
数组名不能被放在赋值运算符的左边,一个数组是一个对象,数组名就是指向这个对象的第一个元素的指针。
2016.10.20
在jenkins中svn链接中增加@HEAD,可以不用理会服务器时间,直接更新到最新的版本
例如 https://192.168.0.100:18080/svn/WEB/trunk/项目名称@HEAD
2016.10.24
802.11b
+--- FHSS/DSSS: 1Mbps,2Mbps
+--- CCK: 5.5Mbps,11Mbps
802.11a/g/n/ac
+--- OFDM:
+--- HT MIX: 兼容11b/a/g 这些11n协议之前的设备
+--- GREEN Field: 只支持 11n 设备,不兼容 11b/a/g 这些老协议
2016.10.26
802.11n标准中采用A-MPDU聚合帧格式,即将多个MPDU聚合为一个A-MPDU,只保留一个PHY头,删除其余MPDU的PHY头,减少了传输每个MPDU的PHY头的附加信息,同时也减少了ACK帧的数目,从而降低了协议的负荷,有效的提高网络吞吐量
2016.10.28
1、wildcard : 扩展通配符
2、notdir : 去除路径
3、patsubst :替换通配符
Makefile 下删除目录中所有的某类型文件
DIRS :=$(shell find . -type d)
OBJS = $(foreach dir,$(DIRS),$(wildcard $(dir)/*.o $(dir)/*.a $(dir)/*.bin))
clean:
@rm -f $(OBJS)
2016.11.4
一个DMA映射是要分配的DMA缓冲区与为该缓冲区生成的,设备可访问地址的组合;建立流式DMA映射,必须告诉内核数据流动的方向,DMA_TO_DEVICE和DMA_FROM_DEVICE,如果数据被发送到设备,应当使用DMA_TO_DEVICE,如果数据被发送到CPU,则使用DMA_FROM_DEVICE,如果数据可以双向流动,则使用DMA_DIDIRECTIONAL;
2016.11.7
注册中断响应
error = request_irq(dev->irq, ath_isr, IRQF_DISABLED, dev->name, dev);
调用的函数接口:
OS_SYNC_SINGLE在文件osdep_adf.h OS_SYNC_SINGLE 839 中定义;
bus_dma_sync_single在文件if_bus.c bus_dma_sync_single 30 中定义
关键的ath_rx_intr_aponly函数,调用了:
OS_SYNC_SINGLE(sc->sc_osdev,
bf->bf_buf_addr[0], sc->sc_rxstatuslen, BUS_DMA_FROMDEVICE,
OS_GET_DMA_MEM_CONTEXT(bf, bf_dmacontext));
然后调用retval = ath_hal_rxprocdescfast(ah, NULL, 0, NULL, rxs, wbuf_raw_data(wbuf));
在OS_SYNC_SINGLE宏中,最后调用dma_cache_sync(devhandle->bdev, (void *)addr, size,
(direction == BUS_DMA_TODEVICE)? DMA_TO_DEVICE : DMA_FROM_DEVICE);
dma_cache_sync在linux\kernels\mips-linux-2.6.31\arch\mips\mm\dma-default.c中定义
void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
enum dma_data_direction direction)
{
BUG_ON(direction == DMA_NONE);
plat_extra_sync_for_device(dev);
if (!plat_device_is_coherent(dev))
__dma_sync((unsigned long)vaddr, size, direction);
}
在kernel的配置文件中CONFIG_DMA_NONCOHERENT=y设置成y
static inline void __dma_sync(unsigned long addr, size_t size, enum dma_data_direction direction)
{
switch (direction) {
case DMA_TO_DEVICE:
dma_cache_wback(addr, size);
break;
case DMA_FROM_DEVICE:
dma_cache_inv(addr, size);
break;
case DMA_BIDIRECTIONAL:
dma_cache_wback_inv(addr, size);
break;
default:
BUG();
}
}
对于DMA_TO_DEVICE方向,就是说要发送到设备,cache内容要写回到DMA 内存;对于BUS_DMA_FROMDEVICE,从device读取数据,要将cache置为无效;如果是双向,先设置成无效,再写回;
a、DMA_TO_DEVICE:把cache的数据刷回内存里,用于使能dma传输到外设之前。因为dma传输只会从内存拿数据,所以必须把cache的数据全部刷回到内存中;
b、DMA_FROM_DEVICE:把cache的数据置无效,用于dma已经传输完毕产生中断之后,准备从内存读取到驱动的buffer中。如果不把cache的数据置无效,
那么cpu就会直接从cache中取出旧的数据,不会到内存中去拿新的数据;
c、DMA_BIDIRECTIONAL跟DMA_TO_DEVICE的效果一样。
ath_edma_attach进行edma的绑定,当中初始化函数 ath_rx_edma_init中为两个队列HAL_RX_QUEUE_LP和HAL_RX_QUEUE_HP初始化buffer,然后进行dma映射
bf->bf_buf_addr[0] = wbuf_map_single(sc->sc_osdev, wbuf, BUS_DMA_FROMDEVICE,
OS_GET_DMA_MEM_CONTEXT(bf, bf_dmacontext));
wbuf_map_single调用了函数dma_map_single(devhandle->bdev, ptr, size,
(direction == BUS_DMA_TODEVICE)? DMA_TO_DEVICE : DMA_FROM_DEVICE);
参考DMA-API.txt可以看到,函数dma_map_single用于映射处理的一段虚拟地址使得硬件设备可以直接访问并返回这段地址的物理地址;就是说经过映射后的这段地址
Maps a piece of processor virtual memory so it can be accessed by the
device and returns the physical handle of the memory.
dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
enum dma_data_direction direction)
{
unsigned long addr = (unsigned long) ptr;
if (!plat_device_is_coherent(dev))
__dma_sync(addr, size, direction);
return plat_map_dma_mem(dev, ptr, size);
}
linux/kernels/mips-linux-2.6.31/arch/mips/include/asm/mach-generic/dma-coherence.h
static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
size_t size)
{
return virt_to_phys(addr);
}
rxedma->rxfifo = (wbuf_t *)OS_MALLOC(sc->sc_osdev, bsize, GFP_KERNEL); 这个是申请指针的数组,
/* push this buffer in the MAC Rx fifo */
ath_hal_putrxbuf(ah, bf->bf_buf_addr[0], qtype);
通过这个函数将物理地址bf->bf_buf_addr[0]写到寄存器AR_HP_RXDP中,AR_HP_RXDP寄存器用于设置MAC用于接收高优先级队列指针地址;
void ar9300_set_rx_dp(struct ath_hal *ah, u_int32_t rxdp, HAL_RX_QUEUE qtype)
{
HALASSERT((qtype == HAL_RX_QUEUE_HP) || (qtype == HAL_RX_QUEUE_LP));
if (qtype == HAL_RX_QUEUE_HP) {
OS_REG_WRITE(ah, AR_HP_RXDP, rxdp);
} else {
OS_REG_WRITE(ah, AR_LP_RXDP, rxdp);
}
}
概述:
无线驱动的收包过程是基于中断的处理方式。在准备接收数据之前,驱动需要先进行初始化接收数据使用到的相关结构( sc_rxbuf和rxfifo )。当数据包到达时,硬件会首先进行 DMA,完成以后产生Rx中断。中断处理过程又分为两个部分,首先是立即执行的上半段处理,负责将数据包从软件接收缓冲队列中取出,并补全接收缓冲区,以便继续接收数据;然后就是一个 tasklet机制的调度,进行数据包的分析处理,在 LMAC层中进行接收状态的分析和填充,在 UMAC层中对数据包本身进行分析,包括重组和包头转换等,最后将其转换为以太网帧的形式提交到 bridge上去。
中断开始
内核活动中有硬件中断和软件中断,对于无线网卡收包的第一步,是硬件中断,对于中断,内核中执行专门的例程,又叫中断处理程序,执行中断发生时的动作。中断处理可通过request_irq进行注册。
跟踪无线收包流程,就从中断处理开始:
error = request_irq(dev->irq, ath_isr, IRQF_DISABLED, dev->name, dev);
然后主要的目光集中在中断处理函数ath_isr中:
可以按照这个函数调用轨迹去看处理的过程,不详细说,重点集中在函数ath_rx_intr_aponly中
void
ath_rx_intr_aponly(ath_dev_t dev, HAL_RX_QUEUE qtype)
{
struct ath_softc *sc = ATH_DEV_TO_SC(dev);
struct ath_rx_edma *rxedma;
wbuf_t wbuf;
struct ath_buf *bf;
struct ath_rx_status *rxs;
HAL_STATUS retval;
struct ath_hal *ah = sc->sc_ah;
int frames;
#if !ATH_RESET_SERIAL
if(atomic_read(&sc->sc_in_reset))
return;
#endif
rxedma = &sc->sc_rxedma[qtype];
do {
printk("%s %d receive packet %d \r\n", __func__, __LINE__, rxedma->rxfifoheadindex);
wbuf = rxedma->rxfifo[rxedma->rxfifoheadindex];
if (unlikely(wbuf == NULL))
break;
bf = ATH_GET_RX_CONTEXT_BUF(wbuf);
/*清理一下cache,则个是cache一致性问题后续说 */
OS_SYNC_SINGLE(sc->sc_osdev,
bf->bf_buf_addr[0], sc->sc_rxstatuslen, BUS_DMA_FROMDEVICE,
OS_GET_DMA_MEM_CONTEXT(bf, bf_dmacontext));
bf->bf_status |= ATH_BUFSTATUS_SYNCED;
rxs = bf->bf_desc;
#ifdef CONFIG_COMCERTO_CUSTOM_SKB_LAYOUT
if (wbuf->mspd_data) {
__memcpy(wbuf->data, wbuf->mspd_data, sc->sc_rxstatuslen + sizeof(struct ieee80211_qosframe) + ATH_COMCERTO_CUSTOM_SKB_OFFSET);
wbuf->mspd_ofst = sc->sc_rxstatuslen + sizeof(struct ieee80211_qosframe) + ATH_COMCERTO_CUSTOM_SKB_OFFSET;
}
#endif
retval = ath_hal_rxprocdescfast(ah, NULL, 0, NULL, rxs, wbuf_raw_data(wbuf));
/*ath_hal_rxprocdescfast = ar9300_proc_rx_desc_fast*/
#ifdef ATH_RX_DESC_WAR
if (unlikely(HAL_EINVAL == retval)) {
struct ath_buf *next_bf;
wbuf_t next_wbuf;
u_int32_t next_idx = rxedma->rxfifoheadindex;
bf->bf_status |= ATH_BUFSTATUS_WAR;
INCR(next_idx, rxedma->rxfifohwsize);
next_wbuf = rxedma->rxfifo[next_idx];
if (next_wbuf == NULL)
break;
next_bf = ATH_GET_RX_CONTEXT_BUF(next_wbuf);
next_bf->bf_status |= ATH_BUFSTATUS_WAR;
DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s: Marking first DP 0x%x for drop\n",
__func__, (unsigned) bf->bf_buf_addr[0]);
DPRINTF(sc, ATH_DEBUG_RX_PROC, "%s: Marking second DP 0x%x for drop\n",
__func__, (unsigned) next_bf->bf_buf_addr[0]);
}
#endif
/* XXX Check for done bit in RxS */
if (HAL_EINPROGRESS == retval) {
break;
}
/* add this ath_buf for deferred processing, 将包放入到rxqueue,下半段部再处理*/
TAILQ_INSERT_TAIL(&rxedma->rxqueue, bf, bf_list);
/* clear this element before advancing */
rxedma->rxfifo[rxedma->rxfifoheadindex] = NULL;
/* advance the head pointer */
INCR(rxedma->rxfifoheadindex, rxedma->rxfifohwsize); /*处理下一个包*/
if (unlikely(rxedma->rxfifodepth == 0))
printk("ath_rx_intr: depth 0 PANIC\n");
rxedma->rxfifodepth--;
} while (TRUE);
/*将ath_bufs 从空闲的链表移到rxedma的rxfifo */
frames = rxedma->rxfifohwsize - rxedma->rxfifodepth;
if (frames > 0)
ath_rx_addbuffer_aponly(sc, qtype, frames);
}
这个函数主要做的就是将数据包从rxfifo中收上来,然后放入rxqueue,然后在空闲队列中找一个ath_bufs放回到rxfifo。
rxfifo
sc中对应的rxfifo 有两个,分别对应于硬件的两个不同优先级的队列( High-Priority和Low-Priority ,HP长队16,LP长度128);
这两个参数在函数ar9300_fill_capability_info中的:
p_cap->hal_rx_hp_depth = HAL_HP_RXFIFO_DEPTH;
p_cap->hal_rx_lp_depth = HAL_LP_RXFIFO_DEPTH;
赋值;
通过枚举变量:
enum RX_FIFO_DEPTH {
HAL_HP_RXFIFO_DEPTH = 16,
HAL_LP_RXFIFO_DEPTH = 128,
};定义
rxfifo是指针的数组,在函数中申请了空间。
static int ath_rxfifo_alloc(struct ath_softc *sc, HAL_RX_QUEUE qtype)
{
struct ath_rx_edma *rxedma;
int bsize, error;
rxedma = &sc->sc_rxedma[qtype];
error = ath_hal_getrxfifodepth(sc->sc_ah, qtype, &rxedma->rxfifohwsize);
if (error)
return error;
bsize = sizeof(wbuf_t) * rxedma->rxfifohwsize;
printk("%s %d rxedma->rxfifohwsize = %d, bsize = %d\r\n", __func__, __LINE__, rxedma->rxfifohwsize, bsize);
/*
上面在串口中打印结果是:
[2016:11:10:14:55:09][ 10.804000] ath_rxfifo_alloc 128 rxedma->rxfifohwsize = 16, bsize = 64
[2016:11:10:14:55:09][ 10.812000] ath_rxfifo_alloc 128 rxedma->rxfifohwsize = 128, bsize = 512
*/
rxedma->rxfifo = (wbuf_t *)OS_MALLOC(sc->sc_osdev, bsize, GFP_KERNEL); /*所以这里申请的是存放指针的数组空间,这些指针就用来执行可用的ath_buf*/
if (rxedma->rxfifo == NULL)
return -ENOMEM;
rxedma->rxfifoheadindex = 0;
rxedma->rxfifotailindex = 0;
rxedma->rxfifodepth = 0;
OS_MEMZERO(rxedma->rxfifo, bsize);
TAILQ_INIT(&rxedma->rxqueue);
ATH_RXQ_LOCK_INIT(rxedma);
return 0;
}
sc->sc_rxbuf
sc_rxbuf是整个驱动中,收包所使用的缓冲池,其中初始化了 512个ath_buf 的对象。该结构为 LMAC层提供空白的ath_buf结构。在在函数ath_rx_edma_init中初始化
int ath_rx_edma_init(ath_dev_t dev, int nbufs)
{
...
printk("%s %d: nbufs = %d, sc->sc_rxbufsize = %d\r\n", __func__, __LINE__, nbufs, sc->sc_rxbufsize);
/*串口输出: [2016:11:10:14:55:09][ 10.828000] ath_rx_edma_init 216: nbufs = 256, sc->sc_rxbufsize = 3900*/
for (i = 0; i < nbufs; i++, bf++, rxs++) {
wbuf = ath_rxbuf_alloc(sc, sc->sc_rxbufsize);
if (wbuf == NULL) {
error = -ENOMEM;
break;
}
bf->bf_mpdu = wbuf;
bf->bf_buf_addr[0] = wbuf_map_single(sc->sc_osdev, wbuf, BUS_DMA_FROMDEVICE,
OS_GET_DMA_MEM_CONTEXT(bf, bf_dmacontext));
/*bf_buf_addr[0] 是物理地址,物理地址,物理地址,重要事情说三次, 这个地址在函数ath_rx_buf_link_aponly中写入MAC的寄存器:
ath_hal_putrxbuf(ah, bf->bf_buf_addr[0], qtype); /*ar9300_set_rx_dp*/
*/
ATH_SET_RX_CONTEXT_BUF(wbuf, bf);
bf->bf_desc = (void *)rxs;
TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); /*然后将bf加入到sc_rxbuf链的后面,就是说sc_rxbuf是有256个wbuf的链,这些buf就是free buf,用来接收数据包的*/
}
...
}
DMA是一种硬件机制,允许外围设备和主存之间直接传输他们的IO数据,而不需要系统处理器的参与。一个DMA映射就是要分配的DMA缓冲区与该缓冲器生成的,设备可访问的地址组合。分为两种映射
一致性DMA映射和流式DMA映射,而无线驱动中使用的是流式DMA映射。
回到代码中,在初始化时使用了wbuf_map_single,其中的参数是BUS_DMA_FROMDEVICE
bf->bf_buf_addr[0] = wbuf_map_single(sc->sc_osdev, wbuf, BUS_DMA_FROMDEVICE,
OS_GET_DMA_MEM_CONTEXT(bf, bf_dmacontext));
wbuf_map_single调用了函数dma_map_single(devhandle->bdev, ptr, size, (direction == BUS_DMA_TODEVICE)? DMA_TO_DEVICE : DMA_FROM_DEVICE);
参考DMA-API.txt可以看到,函数dma_map_single用于映射处理的一段虚拟地址使得硬件设备可以直接访问并返回这段地址的物理地址;
Maps a piece of processor virtual memory so it can be accessed by the
device and returns the physical handle of the memory.
dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
enum dma_data_direction direction)
{
unsigned long addr = (unsigned long) ptr;
if (!plat_device_is_coherent(dev)) /*在kernel的配置文件中CONFIG_DMA_NONCOHERENT=y设置成y*/
__dma_sync(addr, size, direction);
return plat_map_dma_mem(dev, ptr, size);
}
linux/kernels/mips-linux-2.6.31/arch/mips/include/asm/mach-generic/dma-coherence.h
static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size)
{
return virt_to_phys(addr); /*这里返回的是物理地址*/
}
cache一致性
__dma_syn
a、DMA_TO_DEVICE:把cache的数据刷回内存里,用于使能dma传输到外设之前。因为dma传输只会从内存拿数据,所以必须把cache的数据全部刷回到内存中;
b、DMA_FROM_DEVICE:把cache的数据置无效,用于dma已经传输完毕产生中断之后,准备从内存读取到驱动的buffer中。如果不把cache的数据置无效,
那么cpu就会直接从cache中取出旧的数据,不会到内存中去拿新的数据;
c、DMA_BIDIRECTIONAL跟DMA_TO_DEVICE的效果一样
在函数ath_common_intr_aponly中关闭所有的中断,除了 RXEOL, RXORN, SWBA。
软中断 处理函数do_ath_handle_intr
ieee80211_input->ieee80211_iter_input_all->ieee80211_input_all->ath_net80211_rx_aponly ->ath_rx_indicate_aponly->ath_rx_process_aponly->ath_rx_handler_aponly->do_ath_handle_intr
注册tasklet
ATH_INIT_TQUEUE(&osdev->intr_tq, (adf_os_defer_fn_t)ath_tasklet, (void*)dev);
tasklet的实现函数
ath_tasklet(TQUEUE_ARG data)
{
struct net_device *dev = (struct net_device *)data;
struct ath_softc_net80211 *scn = ath_netdev_priv(dev);
do_ath_handle_intr(scn->sc_dev);
}
ath_rx_handler_aponly 是一个do ...while(true)的大循环,不断调用ath_rx_process_aponly,
#endif
2016.11.16
1)toolchain buildroot-gcc463重新编译zlib失败,原来的RPT_Platform中zlib包含了.o文件,解压后没有重新编译,所以编译没有提示出错;
2)buildroot-gcc463中/usr/bin/aclocal中脚本执行失败;
提示:
Can't locate Autom4te/ChannelDefs.pm in @INC (@INC contains: /opt/buildroot-gcc463/usr/share/autoconf /etc/perl /usr/local/lib/perl/5.14.2 /usr/local/share/perl/5.14.2 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.14 /usr/share/perl/5.14 /usr/local/lib/site_perl .) at /project/build/../toolchain/buildroot-gcc463/./usr/bin/autoreconf line 40.
代码中是:
use Autom4te::ChannelDefs;
use Autom4te::Channels;
use Autom4te::Configure_ac;
use Autom4te::FileUtils;
use Autom4te::General;
将toolchain里面的相关脚本工具删除,应该使用系统安装的脚本工具。
2016.11.18
流写入函数fwrite多次调用的时候,是在末尾续写内容,而不是重头覆盖。
2016.11.23
ieee80211_recv_asreq 处理收到的请求关联报文;
ieee80211_node_join:处理加入到基础结构型网络的sta
一个umac的ieee80211_node需要一个lmac的ath_node对应;
[ 12.056000] ath_net80211_node_alloc 1539 sizeof ath_node_net80211 is: 2992
2016.11.28
osif_vap_hardstart_aponly 发包函数
ath_tx_start_aponly调用__wbuf_map_sg_aponly尽心dma映射
2016.11.30
ath_tx_txqaddbuf:发送数据包
最后是调用hal层的发包函数ar9300_start_tx_dma,但是这个函数只是返回了true。
2016.12.2
beacon报文有ath_beacon_tasklet 发送,该函数在收包中断ath_handle_intr中执行
WME有四种流类型,分别是:
/* WME stream classes */
#define WME_AC_BE 0 /* best effort */
#define WME_AC_BK 1 /* background */
#define WME_AC_VI 2 /* video */
#define WME_AC_VO 3 /* voice */
struct ath_txq 是LMAC 层用于对应硬件层队列的数据结构,就是说这个数据结构是硬件层队列在LMAC层的抽象。因此该数据结构的实例和硬件队列是1对1对应的关系。在数据结构ath_softc中,ath_txq的维度是10,定位为sc_txq[HAL_NUM_TX_QUEUES]。这个数据结构在LMAC层的代码中引用成txq。
在struct ath_txq中axq_minfree变量是每种数据流需要保证的最小可用buffer数量,在函数ath_txq_setup中设置。
[2016:12:02:17:19:08][ 11.064000] ath_txq_setup 383 qtype = 3 subtype = 0
[2016:12:02:17:19:08][ 11.068000] ath_txq_setup 383 qtype = 1 subtype = 0
[2016:12:02:17:19:08][ 11.072000] ath_txq_setup 383 qtype = 1 subtype = 1
[2016:12:02:17:19:08][ 11.080000] ath_txq_setup 383 qtype = 1 subtype = 2
[2016:12:02:17:19:08][ 11.084000] ath_txq_setup 383 qtype = 1 subtype = 3
[2016:12:02:17:19:08][ 11.088000] ath_txq_setup 383 qtype = 4 subtype = 0
[2016:12:02:17:19:08][ 11.092000] ath_txq_setup 383 qtype = 7 subtype = 0
wlan_acs_find_best_channel查找最佳的channel,但是是通过ic->ic_acs中的ic_flags进行判断,而这个ic_flags的赋值地方好多,不知道是如何决定的这个值的。
2016.12.6
NetBIOS提供的三个基本功能:
名称服务。在 TCP/IP 网络中,计算机具有供人们使用的名称,但计算机通常使用 IP 地址和硬件地址进行通信。在 NetBEUI 中,没有使用 IP 地址,只使用名称和硬件地址。因此,NBT 负责创建 IP 地址,但这在使用 NetBIOS 和 NetBEUI 网络的 SMB/CIFS 上是不需要的。本文的上半部分专门将讨论这个主题。
数据报服务。这是一种网络通信类型,它不会创建永久连接。在 TCP/IP 中,它大致相当于 UDP,所以 NBT 对需要数据报服务的特性使用 UDP,如在本文下半部分中所描述的浏览器选举。
会话服务。NetBIOS 事务为大部分数据传输请求(例如,用户装载文件共享)提供更长时间的连接。这种服务类型逻辑映射到 TCP/IP 协议的 TCP 部分,因此,NBT 对这种连接使用 TCP。
End-nodes support NetBIOS service interfaces and contain
applications.
Three types of end-nodes are part of this standard:
- Broadcast ("B") nodes
- Point-to-point ("P") nodes
- Mixed mode ("M") nodes
10.1 Broadcast (or "B") nodes communicate using a mix of UDP datagrams
(both broadcast and directed) and TCP connections. B nodes may
freely interoperate with one another within a broadcast area. A
broadcast area is a single MAC-bridged "B-LAN". (See Appendix A for
a discussion of using Internet Group Multicasting as a means to
extend a broadcast area beyond a single B-LAN.)
10.2. POINT-TO-POINT (P) NODES
Point-to-point (or "P") nodes communicate using only directed UDP
datagrams and TCP sessions. P nodes neither generate nor listen for
broadcast UDP packets. P nodes do, however, offer NetBIOS level
broadcast and multicast services using capabilities provided by the
NBNS and NBDD.
P nodes rely on NetBIOS name and datagram distribution servers.
These servers may be local or remote; P nodes operate the same in
either case.
10.3. MIXED MODE (M) NODES
Mixed mode nodes (or "M") nodes are P nodes which have been given
certain B node characteristics. M nodes use both broadcast and
unicast. Broadcast is used to improve response time using the
assumption that most resources reside on the local broadcast medium
rather than somewhere in an internet.
M nodes rely upon NBNS and NBDD servers. However, M nodes may
continue limited operation should these servers be temporarily
unavailable.
2016.12.8
_addIpAndDevName2Data 添加Dev name和IP,该IP是通过get_client模块在br_bridge中加的钩子函数解析的。
Base64是一种基于64个可打印字符来表示二进制数据的表示方法。Base64是一种编码方式;Base64主要用于将二进制数据转换为文本数据,方便使用HTTP协议等,是可逆的。处理文本数据的场合,表示、传输、存储一些二进制数据。包括MIME的email,email via MIME,在XML中存储复杂数据
2017.1.13
暂时修改factoryLanMac的默认值;
2017.1.22
#define NM_DEBUG(fmt, args...) \
printf("[NM_Debug](%s) %05d: "fmt"\r\n", __FUNCTION__, __LINE__, ##args)
#define NM_ERROR(fmt, args...) \
printf("[NM_Error](%s) %05d: "fmt"\r\n", __FUNCTION__, __LINE__, ##args)
#define NM_INFO(fmt, args...) \
printf(fmt, ##args)
2017.2.6
NB 0x0020 NetBIOS general Name Service Resource Record
NBSTAT 0x0021 NetBIOS NODE STATUS Resource Record (See NODE
STATUS REQUEST)
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NAME_TRN_ID |1| 0x0 |1|0|0|0|0 0|0| 0x0 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0000 | 0x0001 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0000 | 0x0000 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
/ RR_NAME /
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NBSTAT (0x0021) | IN (0x0001) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x00000000 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RDLENGTH | NUM_NAMES | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
| |
+ +
/ NODE_NAME ARRAY /
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
/ STATISTICS /
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The NODE_NAME ARRAY is an array of zero or more NUM_NAMES entries
of NODE_NAME records. Each NODE_NAME entry represents an active
name in the same NetBIOS scope as the requesting name in the
local name table of the responder. RR_NAME is the requesting
name.
2017.2.15 周三
升级文件用一个错误的文件升级,发现cache不断增加,多升级几次后内存不足出错。原因是打开的文件描述符没有关闭,而单单把文件给删除,导致kernel中cached不断增大。
2017.2.20 周一
MTK 的FAE 到公司测试,测试时发现他们的公板对LAN->LAN, wlan->LAN 这种情况, WLAN到LAN可以跑起来,而LAN到LAN不可以
2017.2.21 周二
重新验证bug,确定必定出现的显现。MTK提供了demo软件,我们也提供了demo软件给他,但是关键的plc->lan这个他们那边应该测试部出来。
2017.2.22 周三
IEEE802.3X标准定义了一种新方法,在全双工环境中去实现流量控制,交换机产生一个pause帧,pause帧利用一个保留的组播地址:01-80-c2-00-00-01,它将发送给正在发送的站,站点收到该帧后,就会暂停或者停止发送帧。
pause帧利用了一个保留的组播地址,所以不会被交换机或者网桥转发,这样就不会导致额外的数据量。
2017.2.28
升级时,malloc一个升级文件大小的buffer,malloc提示成功,但是写入这内存是出现内存耗尽。就是说malloc成功实际上不是成功分配可以的物理地址。
malloc函数分配是从memfree和cached两者之和分配内存,但是cached的不能全部被释放,只能释放部分,这个能释放的值不确定,所以malloc还是以Memfree的为关键值。
/tmp # cat /proc/meminfo
MemTotal: 29952 kB
MemFree: 6728 kB
Buffers: 232 kB
Cached: 9608 kB
SwapCached: 0 kB
Active: 3708 kB
Inactive: 10756 kB
Active(anon): 2408 kB
Inactive(anon): 2256 kB
Active(file): 1300 kB
Inactive(file): 8500 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 0 kB
Writeback: 0 kB
AnonPages: 4672 kB
Mapped: 2248 kB
Shmem: 0 kB
Slab: 4920 kB
SReclaimable: 212 kB
SUnreclaim: 4708 kB
KernelStack: 416 kB
PageTables: 272 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 14976 kB
Committed_AS: 8876 kB
VmallocTotal: 1048372 kB
VmallocUsed: 3340 kB
VmallocChunk: 1041856 kB
/tmp # ./testd 20000
main 222 malloc 20000 Kbyte
main 227 malloc error
/tmp # ./testd 15000
main 222 malloc 15000 Kbyte
main 231 malloc 15000 Kbyte
main 232 memcpy begin
wirte 1 M
wirte 2 M
/tmp # ./testd 16000
main 222 malloc 16000 Kbyte
main 227 malloc error
/tmp # ./testd 15000
main 222 malloc 15000 Kbyte
main 231 malloc 15000 Kbyte
main 232 memcpy begin
wirte 1 M
临界值:
/tmp # cat /proc/meminfo
MemTotal: 29952 kB
MemFree: 6784 kB
Buffers: 192 kB
Cached: 9608 kB
SwapCached: 0 kB
Active: 5924 kB
Inactive: 8536 kB
Active(anon): 4660 kB
Inactive(anon): 0 kB
Active(file): 1264 kB
Inactive(file): 8536 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 0 kB
Writeback: 0 kB
AnonPages: 4672 kB
Mapped: 2252 kB
Shmem: 0 kB
Slab: 4900 kB
SReclaimable: 172 kB
SUnreclaim: 4728 kB
KernelStack: 416 kB
PageTables: 276 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 14976 kB
Committed_AS: 8876 kB
VmallocTotal: 1048372 kB
VmallocUsed: 3340 kB
VmallocChunk: 1041856 kB
/tmp # ./testd 15660
main 222 malloc 15660 Kbyte
main 227 malloc error
/tmp #
/tmp # ./testd 15659
main 222 malloc 15659 Kbyte
main 231 malloc 15659 Kbyte
main 232 memcpy begin
wirte 1 M
/tmp # cat /proc/sys/vm/min_free_kbytes
721
/tmp #
2017.3.2
当前文件夹中结合使用grep和xargs来处理文件名: ls | grep -v keep | xargs rm #删除keep文件之外的所有文件,删除除了syslog和msgcenter外的其他目录:ls | grep -v 'syslog\|msgcenter'
例7:删除匹配行和之后两行
$sed '/Storage/,+2d' thegeekstuff.txt
if test "$(BOARD_TYPE)" = "ralink"; then \
cd $(GPL_LINUX_KERNEL_DIR)/ralink && sed -i '/raeth/d' Kconfig && sed -i '/wireless/d' Kconfig; \
cd $(GPL_LINUX_KERNEL_DIR)/drivers/net && sed -i '/wireless/d' Kconfig; \
else \
cd $(GPL_LINUX_KERNEL_DIR)/ralink && sed -i '/wireless/d' Kconfig.source; \
fi;
\后面不能有空格
2017.3.7 周二
将生成gpl的代码独立编写成Makefile.gpl,在主Makefile中include这个Makefile,然后上传两个template文件。
2017.38 周三
国家码标准:https://www.iso.org/obp/ui/#search
MTKiwpriv命令
1.CountryRegion 2.4GHz的国家地区码,不同的地区码信道选择范围不一样,范围是0~7,31~33
iwpriv ra0 set CountryRegion=5
2.CountryRegionABand 5G的国家地区码
3.CountryCode 无线国家码
国家码简写标准:https://www.iso.org/obp/ui/#search
iwpriv ra0 set CountryCode=cn
4.ChannelGeography:信道地理类型
0:Outdoor 1:Indoor 2:Both
5.SSID 无线SSID,1~32 ASCII码
iwpriv ra0 set SSID="AAA"
6.WirelessMode 无线模式
1. legacy 11B only;2.legacy 11A only;3.legacy 11a/b/g mixed;4.legacy 11G only;5.11ABGN mixed
6.11N only in 2.4G; 7.11GN mixed;8.11AN mixed; 9.11BGN mixed; 10.11AGN mixed;11.11N only in 5G;
14.11A/AN/AC mixed 5G band only;15. 11AN/AC mixed 5G band only.
7.Channel 无线channel
Channel=0; 0表示自动扫描;
8.BasicRate 无线支持的基本速率集
1. 1Mbps;2.2Mbps;3.1Mbps,2Mbps;4.5.5Mbps;15.1Mbps,2Mbps,5.5Mbps,11Mbps;
9.Beacon Period Beacon帧的周期
iwpriv ra0 set BeaconPeriod=100
10.DtimPeriod duratin time 1~255
iwpriv ra0 set DtimPeriod=64
11.TxPower 传输功率,0~100
iwpriv ra0 set TxPower=99
12.DisableOLBC
13.BGProtection 启用/禁用 无线11B or 11G保护
0:auto;1:on;2:off
14.MaxStaNum 最大sta连接数量
0:disable 1~32
15.TxAntenna 配置Tx天线数量
iwpriv ra0 set TxAntenna=1
16.RxAntenna 配置Rx天线数量
17.TxPreamble 启用/禁用Tx 前导码
iwpriv ra0 set TxPreamble=0
18.RTSThreshold 设置RTS 阈值 1~2347
19.FragThreshold 设置分片包阈值,256~2346
iwpriv ra0 set FragThreshold=1024
20.TxBurst 启用/禁用Tx burst,0:disable;1:enable
iwpriv ra0 set TxBurst=1
21.PktAggregate 启用/禁用 Tx 帧聚合,0:disable,1:enable
22.NoForwarding 启用或禁用不同的sta的包在相同的SSID转发,0:disable;1:enable
iwpriv ra0 set NoForwarding=0
23.NoForwardingBTNBSSID,禁用或启用在每个BSSID之间不转发0:disable;1:enable
24.NoForwardingMBCast,禁用或启用不抓发组播/多播包
25.HideSSID,禁用或启用隐藏SSID,0:disable;1:enable
iwpriv ra0 set HideSSID=0
26.StationKeepAlive禁用或启用周期性自动检测活跃的sta,0:disable;1:enable
iwpriv ra0 set StationKeepAlive=1
27.ShortSlot,禁用或启用short slot time,0:disable;1:enable
iwpriv ra0 set ShortSlot=1
28.AutoChannelSelect,启用禁用信道自动选则,0,disable;1:旧算法,2:新算法;
29.Debug 设置WLAN debug等级(0~5) 0:off;1:Error;2:Warning;3:Trace;4:Info;5:Loud
iwpriv ra0 set Debug=3
30.DriverVersion 检测无线驱动版本
iwpriv ra0 set DriverVersion=0
31.AccessPolicy 配置访问控制规则,0:允许访问AP,1:禁止访问AP
iwpriv ra0 set AccessPolicy=0
32.ResetCounter,重设计算器
iwpriv ra0 set ResetCounter=1
33.SiteSurvey 请求动作做站点测量
iwpriv ra0 set SiteSurvey=
被动扫描:空串,iwpriv ra0 set SiteSurvey=
主动扫描:目的SSID,iwpriv ra0 set SiteSurvey=Target_SSID
34.CountryString 设置国家
iwpriv ra0 set CountryString=China
35.FixedTxMode设置发送调制模式,CCK OFDM HT
iwpriv ra0 set FixedTxMode=CCK
36.DisConnectSta断开一个指定的STA
iwpriv ra0 set DisConnectSta=00:11:22:33:44:55
37.DisConnectAllSta 断开所有sta
iwpriv ra0 set DisConnectAllSta=1
38.McastPhyMode 设置多播物理模式,0:Disable; 1:CCK;2:OFDM;3:HTMIX
iwpriv ra0 set McastPhyMode=0
39.McastMcs设置多播包的MCS,0~15
iwpriv ra0 set McastMcs=0
40.MaxStaNum 现在每一个BSS可以管理sta的最大值 1~32
iwpriv ra0 set MaxStaNum=0
0:禁用限制
41.AutoFallBack 启用/禁用自动降低速率功能。0:disable; 1:enable
iwpriv ra0 set AutoFallBack=1
42.MBSSWirelessMode 设置MBSS 无线物理方式
iwpriv ra0 set MBSSWirelessMode=1
0:802.11B/G mixed
1:802.11B only
2:801.11A only
4:801.11G only
6:801.11N only
7:801.11G/N mixed
8:801.11A/N mixed
9:801.11B/G/Nmixed
10:801.11A/G/N mixed
11:801.11N in 5G band only
43.HtBw HT信道带宽设置, 0:20MHz;1:20/40 MHz
iwpriv ra0 set HtBw=1
44.HtMcs 设置无线调制编码策略, 0~15,32:fix MCS rate, 33,自动适配
iwpriv ra0 set HtMcs=33
45.HtGi 设置无线guard 间隔,0:长间隔;1短间隔
iwpriv ra0 set HtGi=1
46.HtOpMode 设置HT操作模式,0:HT混合模式,1:HT greenfield模式
iwpriv ra0 set HtOpMode=0
47.HtBaWinSize 设置Block Ack 窗口大小,1~64
iwpriv ra0 set HtBaWinSize=64
48.HtTxBASize 设置一次传输burst中AMPDU聚合包的个数,1~64
iwpriv ra0 set HtBASize=64
49.HtAmsdu 启用禁用A-MSDU,0 禁用,1启用
iwpriv ra0 set HtAmsdu=0
50.HtAutoBa 启用禁用自动block ack,0 禁用,1启用
iwpriv ra0 set HtAutoBa=1
51.HtMimoPs 启用禁用HT MIMMO power save 模式,1:enable,0:disable
iwpriv ra0 set HtMimoPs=1
52.AP2040Rescan 触发HT20/40 coexistence重新扫描,1:触发
iwpriv ra0 set AP2040Rescan=1
53.HtBssCoex 启用禁用HT BSS coexistence,0 禁用,1启用
iwpriv ra0 set HtBssCoex=1
54.AssocReqRssiThres设置关联请求时接收灵敏度的阈值,使拒绝STA的关联请求在弱信号的情况下
iwpriv ra0 set AssocReqRssiThres=-88
0:关闭
0~-100RSSI的值
55.stat 显示无线统计信息
iwpriw ra0 stat
或者:
while [ 1 ]; do iwpriv ra0 set ResetCounter=1; sleep 1; iwpriv ra0 stat; done;
56.get_site_survey 获取扫描信息
iwpriv ra0 get_site_survey
执行该命令前先执行iwpriv ra0 set SiteSurvey=
57.get_mac_table 获取连接到AP的sta的mac地址信息
iwpriv ra0 get_mac_talbe
58.get_ba_table 显示BlackACK table
iwpriv ra0 get_ba_table
59.show 显示信息
iwpriv ra0 show [parameter]
[parameter list]
1. driverinfo
2.stat
3.stainfo
4.stacountinfo
5.stasecinfo
6.bainfo
7.connStatus
8.reptinfo
9.wdsinfo
10.igmpinfo
11.mbss
12.blockch
2017.3.16 周四
这两天一直在跟踪RootAP修改LAN IP后,DUT 不能检测到前端RootAP IP变动的问题。开始反馈这个问题的时候我和测试部
同事验证这个问题,发现没有复现,后来在其他项目上测试时复现了,抓包发现,当RootAP修改了LAN IP后,DHCP server地址池也修改,收到续约包后Dhcpsever返回一个NAK,而这时候正常来说DHCP client要重新发Discover,但是实际上没有发。比较两个拓扑的差异,差异在于一个内网,一个外网。分析原因是因为外网PPPoE拨号,成功后DUT的NTP时间更新了,而内网则不会更新NTP。而在busybox的udhcpc中,会根据当前的时间和上一次发送DHCP Discover报文的时间差,决定是否再次发送Discover包。由于第一次发送DHCP Discover系统时间是默认时间2017.6.1,而NTP更新后,变成2017.3.16,所以不会发送。
2017.3.17 周五
先从flash的配置文件分区config中读出文件,然后MD5校验,解密,解压,然后将解压后的字符串解析成json格式,根root = cJSON_Parse(pRawDataBuf); 然后遍历uclOpModInitArray数组,根据模块名,调用模块的jsonTodata函数指针pEntry->jsonToData(module);,将函数将模块对应的json格式的参数转成模块参数数据结构格式;如果pEntry->jsonToData 为NULL,说明这个模块没有json格式的默认配置,那么则调用pEntry->reset(); 所有模块都处理完之后,调用
函数_usrconf_save保持,_usrconf_save函数中,先构造一个root的json数据跟节点,然后遍历所有模块,调用dataTojson将各个模块的配置信息加入到root中,然后进行压缩,加密,MD5处理,最后调用函数writeConfigFlash写入到到user-config分区。
usrconf_init 函数执行各个模块的初始化,该函数中调用usrconf_load将配置参数(json结构)从用户配置区读出来,然后调用pEntry->jsonToData(module) 将json格式的参数转成模块数据结构格式保持在各个模块的全局地址变量中。 然后调用usrconf_execute_init函数执行各个模块的初始化工作。
对于页面修改某个模块参数后点击保存,则通过ucl_op_processMessage函数中调用usrconf_save进行保存。
2.4g的无线启动时间需要6s
2017.3.20 周一
查看无线的初始化,发现当中设置了br0的mac地址,然后进行down和up的操作。如果没有经这一步,则原来的无线参数在文件rcS中通过脚本进行设置。
无线需要写MAC地址后,SSID生成规则马上生效。
2017.3.24 周五
网桥可以进行MAC地址学习,通过MAC学习建立MAC-PORT的对应关系表。
1.MAC学习:学习MAC地址,起初,网桥是没有任何地址与端口的对应关系的,它发送数据,还是得想HUB一样,但是每发送一个数据,它都会关心数据包的来源MAC是从自己的哪个端口来的,由于学习,建立地址-端口的对照表(CAM表)。
2. 报文转发:每发送一个数据包,网桥都会提取其目的MAC地址,从自己的地址-端口对照表(CAM表)中查找由哪个端口把数据包发送出去。
通过命令brctl showmacs可以查看
~ # brctl showmacs br0
port no mac addr is local? ageing timer
1 00:0a:eb:13:7b:00 no 1.22
1 00:42:20:30:10:38 yes 0.00
1 00:42:20:30:10:39 no 5.78
3 02:42:20:30:10:38 yes 0.00
2 14:cc:20:16:fb:da no 0.56
1 40:61:86:cf:1d:3c no 0.70
1 6c:62:6d:f5:aa:c4 no 128.76
1 ec:17:2f:bb:49:70 no 2.88
40:61:86:cf:1d:3c和ec:17:2f:bb:49:70分别是连接到DUT switch的连个PC有线网卡。 14:cc:20:16:fb:da是连接到DUT的无线网卡。
进入桥的数据报文分为几个类型,桥对应的处理方法也不同:
1. 报文是本机发送给自己的,桥不处理,交给上层协议栈;
2. 接收报文的物理接口不是网桥接口,桥不处理,交给上层协议栈;
3. 进入网桥后,如果网桥的状态为Disable,则将包丢弃不处理;
4. 报文源地址无效(广播,多播,以及00:00:00:00:00:00),丢包;
5. 如果是STP的BPDU包,进入STP处理,处理后不再转发,也不再交给上层协议栈;
6. 如果是发给本机的报文,桥直接返回,交给上层协议栈,不转发;
7. 需要转发的报文分三种情况:
1) 广播或多播,则除接收端口外的所有端口都需要转发一份;
2) 单播并且在CAM表中能找到端口映射的,只需要网映射端口转发一份即可;
3) 单播但找不到端口映射的,则除了接收端口外其余端口都需要转发;
msgcenter通过两个套接字进行信息的转发,一个套接字是udp,绑定的IP是环回ip127.0.0.1,一个是域套接字,绑定文件/tmp/msgcenter
static os_s32 create_udp(void)
{
os_s32 s = 0;
os_s32 send_buf = 0;
os_s32 recv_buf = 0;
//struct timeval tv;
socklen_t buf_len = 0;
struct sockaddr_in server;
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
log_show("failed to create udp socket: %s", strerror(errno));
return os_err;
}
if (mc_setnonblocking(s) < 0)
{
goto bad;
}
bzero(&server, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(MC_PORT_SERVER);
if (inet_pton(AF_INET, MC_BIND_UDP_ADDR, &server.sin_addr) <= 0)
{
log_show("failed to inet_pton: %s", strerror(errno));
goto bad;
}
/*
tv.tv_sec = 1;
tv.tv_usec = 0;
if (setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0)
{
log_show("failed setsockop SO_SNDTIMEO: %s", strerror(errno));
goto bad;
}
*/
buf_len = sizeof(os_s32);
if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, &send_buf, &buf_len) < 0)
{
log_show("failed getsockop SO_SNDBUF: %s", strerror(errno));
goto bad;
}
log_info("udp send_buf: %d", send_buf);
send_buf <<= 2;
if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &send_buf, sizeof(os_s32)) < 0)
{
log_show("failed setsockop SO_SNDBUF: %s", strerror(errno));
goto bad;
}
buf_len = sizeof(os_s32);
if (getsockopt(s, SOL_SOCKET, SO_RCVBUF, &recv_buf, &buf_len) < 0)
{
log_show("failed getsockop SO_RCVBUF: %s", strerror(errno));
goto bad;
}
log_info("udp recv_buf: %d", recv_buf);
recv_buf <<= 2;
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &recv_buf, sizeof(os_s32)) < 0)
{
log_show("failed setsockop SO_RCVBUF: %s", strerror(errno));
goto bad;
}
if (bind(s, (struct sockaddr*)&server, sizeof(server)) < 0)
{
log_show("failed to bind: %s", strerror(errno));
goto bad;
}
return s;
bad:
close(s);
return os_err;
}
static os_s32 create_unix(void)
{
os_s32 s = 0;
struct sockaddr_un server;
if ((s = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0)
{
log_show("failed to create unix socket: %s", strerror(errno));
return os_err;
}
if (mc_setnonblocking(s) < 0)
{
goto bad;
}
unlink(MC_BIND_UNIX_ADDR);
bzero(&server, sizeof(server));
server.sun_family = AF_LOCAL;
strcpy(server.sun_path, MC_BIND_UNIX_ADDR);
if (bind(s, (struct sockaddr*)&server, sizeof(server)) < 0)
{
log_show("failed to bind: %s", strerror(errno));
goto bad;
}
return s;
bad:
close(s);
return os_err;
}
域套接字收到的包类型包括注册,注销和数据包,如果是数据包,则用udp发送到udp server。mc_deliver_data函数将数据包发送到每一个attach的client上。
2017.3.29 周三
周二和周三在整理autoip的问题分析文档,用户使用时发现了这个问题,要求给出问题存在的原因。于是老大要求写份文档分析整个模块的结构问题存在的原因解决方法经验教训等。
为了写这份文档,将DHCP的RFC 2131看了一下,重点是数据包类型和状态机,然后是busybox中的udhcpc的实现,发现和RFC中的描述是有出入的,比如T1/T2的描述,代码中直接的T/2的方式。最后是经验教训,个人写的格局不够高,这个以后要注意一下。
2016.4.7 周五
今天尝试安装和使用pc-lint,安装好工具后,第一步先测试头文件搜索路径
root@vickytong:/toolchain/usr/bin# ./mipsel-linux-gcc-4.6.3 -c -v empty.c
Using built-in specs.
COLLECT_GCC=./mipsel-linux-gcc-4.6.3
COLLECT_LTO_WRAPPER=/toolchain/usr/bin/../libexec/gcc/mipsel-buildroot-linux-uclibc/4.6.3/lto-wrapper
Target: mipsel-buildroot-linux-uclibc
Configured with: /home/ralink/buildroot-2012.11.1/output/toolchain/gcc-4.6.3/configure --prefix=/opt/buildroot-gcc463/usr --build=i686-pc-linux-gnu --host=i686-pc-linux-gnu --target=mipsel-buildroot-linux-uclibc --enable-languages=c,c++ --with-sysroot=/opt/buildroot-gcc463/usr/mipsel-buildroot-linux-uclibc/sysroot --with-build-time-tools=/opt/buildroot-gcc463/usr/mipsel-buildroot-linux-uclibc/bin --disable-__cxa_atexit --enable-target-optspace --disable-libgomp --with-gnu-ld --disable-libssp --disable-multilib --disable-tls --disable-shared --with-gmp=/opt/buildroot-gcc463/usr --with-mpfr=/opt/buildroot-gcc463/usr --with-mpc=/opt/buildroot-gcc463/usr --disable-nls --enable-threads --disable-decimal-float --with-float=soft --with-abi=32 --with-tune=mips32r2 --with-pkgversion='Buildroot 2012.11.1' --with-bugurl=http://bugs.buildroot.net/
Thread model: posix
gcc version 4.6.3 (Buildroot 2012.11.1)
COLLECT_GCC_OPTIONS='-c' '-v' '-mtune=mips32r2' '-mabi=32' '-msoft-float' '-mllsc' '-mno-synci' '-mno-shared'
/toolchain/usr/bin/../libexec/gcc/mipsel-buildroot-linux-uclibc/4.6.3/cc1 -quiet -v -iprefix /toolchain/usr/bin/../lib/gcc/mipsel-buildroot-linux-uclibc/4.6.3/ -isysroot /toolchain/usr/bin/../mipsel-buildroot-linux-uclibc/sysroot empty.c -quiet -dumpbase empty.c -mtune=mips32r2 -mabi=32 -msoft-float -mllsc -mno-synci -mno-shared -auxbase empty -version -o /tmp/ccT99qPW.s
GNU C (Buildroot 2012.11.1) version 4.6.3 (mipsel-buildroot-linux-uclibc)
compiled by GNU C version 4.4.3, GMP version 5.0.5, MPFR version 3.1.1, MPC version 1.0.1
warning: GMP header version 5.0.5 differs from library version 5.0.2.
warning: MPFR header version 3.1.1 differs from library version 3.1.0-p3.
warning: MPC header version 1.0.1 differs from library version 0.9.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring duplicate directory "/toolchain/usr/bin/../lib/gcc/../../lib/gcc/mipsel-buildroot-linux-uclibc/4.6.3/include"
ignoring nonexistent directory "/toolchain/usr/bin/../mipsel-buildroot-linux-uclibc/sysroot/usr/local/include"
ignoring duplicate directory "/toolchain/usr/bin/../lib/gcc/../../lib/gcc/mipsel-buildroot-linux-uclibc/4.6.3/include-fixed"
ignoring duplicate directory "/toolchain/usr/bin/../lib/gcc/../../lib/gcc/mipsel-buildroot-linux-uclibc/4.6.3/../../../../mipsel-buildroot-linux-uclibc/include"
#include "..." search starts here:
#include <...> search starts here:
/toolchain/usr/bin/../lib/gcc/mipsel-buildroot-linux-uclibc/4.6.3/include
/toolchain/usr/bin/../lib/gcc/mipsel-buildroot-linux-uclibc/4.6.3/include-fixed
/toolchain/usr/bin/../lib/gcc/mipsel-buildroot-linux-uclibc/4.6.3/../../../../mipsel-buildroot-linux-uclibc/include
/toolchain/usr/bin/../mipsel-buildroot-linux-uclibc/sysroot/usr/include
End of search list.
GNU C (Buildroot 2012.11.1) version 4.6.3 (mipsel-buildroot-linux-uclibc)
compiled by GNU C version 4.4.3, GMP version 5.0.5, MPFR version 3.1.1, MPC version 1.0.1
warning: GMP header version 5.0.5 differs from library version 5.0.2.
warning: MPFR header version 3.1.1 differs from library version 3.1.0-p3.
warning: MPC header version 1.0.1 differs from library version 0.9.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 803a9f797010d160a1bef2d33c25729e
COLLECT_GCC_OPTIONS='-c' '-v' '-mtune=mips32r2' '-mabi=32' '-msoft-float' '-mllsc' '-mno-synci' '-mno-shared'
/toolchain/usr/bin/../lib/gcc/mipsel-buildroot-linux-uclibc/4.6.3/../../../../mipsel-buildroot-linux-uclibc/bin/as -EL -no-mdebug -mabi=32 -mno-shared -mtune=mips32r2 -KPIC -o empty.o /tmp/ccT99qPW.s
COMPILER_PATH=/toolchain/usr/bin/../libexec/gcc/mipsel-buildroot-linux-uclibc/4.6.3/:/toolchain/usr/bin/../libexec/gcc/:/toolchain/usr/bin/../lib/gcc/mipsel-buildroot-linux-uclibc/4.6.3/../../../../mipsel-buildroot-linux-uclibc/bin/
LIBRARY_PATH=/toolchain/usr/bin/../lib/gcc/mipsel-buildroot-linux-uclibc/4.6.3/:/toolchain/usr/bin/../lib/gcc/:/toolchain/usr/bin/../lib/gcc/mipsel-buildroot-linux-uclibc/4.6.3/../../../../mipsel-buildroot-linux-uclibc/lib/:/toolchain/usr/bin/../mipsel-buildroot-linux-uclibc/sysroot/lib/:/toolchain/usr/bin/../mipsel-buildroot-linux-uclibc/sysroot/usr/lib/
COLLECT_GCC_OPTIONS='-c' '-v' '-mtune=mips32r2' '-mabi=32' '-msoft-float' '-mllsc' '-mno-synci' '-mno-shared'
root@vickytong:/toolchain/usr/bin#
#include <...> search starts here:显示的就是编译器搜索系统文件的路径,将这些路径在文件options.lnt中记录下来:
-i"Z:\mtk\toolchain\buildroot-gcc463\usr\bin\..\lib\gcc\mipsel-buildroot-linux-uclibc\4.6.3\include"
-i"Z:\mtk\toolchain\buildroot-gcc463\usr\bin\..\lib\gcc\mipsel-buildroot-linux-uclibc\4.6.3\include-fixed" -i"Z:\mtk\toolchain\buildroot-gcc463\usr\bin\..\lib\gcc\mipsel-buildroot-linux-uclibc\4.6.3\..\..\..\..\mipsel-buildroot-linux-uclibc\include"
-i"Z:\mtk\toolchain\buildroot-gcc463\usr\mipsel-buildroot-linux-uclibc\sysroot\usr\include"
-i"Z:\mtk\toolchain\buildroot-gcc463\usr\mipsel-buildroot-linux-uclibc\sysroot\usr\include\linux"
此外,非系统头文件的查找路径也需要在该文件中定义
-i"Z:\apps\develop\private\apps\wifid\include"
-i"Z:\apps\develop\private\apps\wifid\include\mtk"
第二步: gcc -E -dM empty.c >co-gcc.h 查看编译器中定义了哪些宏
# ./mipsel-linux-gcc-4.6.3 -E -dM empty.c > /home/project/co-gcc.h
将文件co-gcc.h放在lint目录下。
第三步:
修改lnt目录下面的文件
首先是std.lnt
// Gnu C/C++ (version 2.95.3 or later), -si4 -sp4, lib-w32.lnt
// Standard lint options
D:\tools\pclint\lnt\co-gcc.lnt
D:\tools\pclint\lnt\lib-w32.lnt
D:\tools\pclint\lnt\options.lnt -si4 -sp4
然后是co-gcc.lnt,在该文件中主要要把库文件的报错屏蔽,-wlib(0)并且显示warming以下的信息-w2
第四步:执行命令测试
D:\tools\pclint>lint-nt -i"D:\tools\pclint\lnt" -u std.lnt Z:\apps\develop\private\apps\wifid\src\mt k\wifi_cmd_mtk.c
在执行是发现一个奇怪的现象,就是检查出头文件问题就停止了,并没有检查后面的代码,后来发现将头文件屏蔽掉,就可以了
#include
2017.4.11 周二
使用pc-lint检查wifi中mtk的代码,发现如果头文件中包含了,则检查不能执行,解决方法是将:
Z:\/mtk\toolchain\buildroot-gcc463\usr\mipsel-buildroot-linux-uclibc\sysroot\usr\include\中的string.h重新命令为其他名字,则可以顺利检查。
2017.4.12 周三
使用pc-link检查wifi_platform_mtk.c和wifi_cmd_mtk.c两个文件并且上传svn。过程中对错误信息更加了解,对宏的代码检查经常报错,也许是因为该工具是静态检查代码,而宏的替换在预编译执行的。
2017.4.13 周四
pc-lint检查文件,发现对已一些宏,如CJSON_GETINTOBJITEM(tmp, pnode, "filterRule", (int)pAcl->filterRule),报错误:
Error 63: Expected an lvalue
将这个宏展开后,则没有错误。
2017.4.18 周二
sed 's/.$//' 该命令去除DOS 格式文件中行尾CR/LF 为 UNIX的LF.
2017.4.19 周三
2017.4.20 周四
~ # brctl show
bridge name bridge id STP enabled interfaces
br0 8000.50c7bfa05abc no eth1
eth0
ath0
分析这个问题,需要查看switch的状态
2017.4.21 周五
查看datasheet,发现switch寄存器和主芯片寄存器是不一样的,对于主芯片,寄存器是统一的编程地址,GMAC是主芯片的一部分,所以对GMAC的配置的寄存器也是通过统一编程地址实现,而对于switch,可以视作独立的硬件,对它的配置和访问,还有PHY,通常则是通过媒体无关接口RGMII/SGMII传址和传值。
从代码上看,在头文件athrs27_phy.h中进行定义,如:
这部分是交换机的寄存器,对应datasheet中的8.18章
#define S27_MASK_CTL_REG 0x0000
#define S27_OPMODE_REG0 0x0004
#define S27_OPMODE_REG1 0x0008
#define S27_OPMODE_REG2 0x000C
#define S27_PWRSTRAP_REG 0x0010
#define S27_GLOBAL_INTR_REG 0x0014
#define S27_GLOBAL_INTR_MASK_REG 0x0018
#define S27_FLD_MASK_REG 0x002c
#define S27_FLCTL_REG0 0x0034
#define S27_FLCTL_REG1 0x0038
#define S27_ARL_TBL_FUNC_REG0 0x0050
#define S27_ARL_TBL_FUNC_REG1 0x0054
#define S27_ARL_TBL_FUNC_REG2 0x0058
#define S27_ARL_TBL_CTRL_REG 0x005c
#define S27_TAGPRI_REG 0x0070
#define S27_CPU_PORT_REGISTER 0x0078
#define S27_MDIO_CTRL_REGISTER 0x0098
而读的函数接口
unsigned int athrs27_reg_read(unsigned int s27_addr) 和void athrs27_reg_write(unsigned int s27_addr, unsigned int s27_write_data)中,使用的是物理地址和寄存器地址。
而对于读写phy,则通过写固定的phy信息数组athrPhyInfo进行访问。
unsigned int s27_rd_phy(int ethUnit,unsigned int phy_addr, unsigned int reg_addr) 这里的reg_addr就是datasheet中说明的地址。
/*****************/
/* PHY Registers */
/*****************/
#define S27_PHY_CONTROL 0
#define S27_PHY_STATUS 1
#define S27_PHY_ID1 2
#define S27_PHY_ID2 3
#define S27_AUTONEG_ADVERT 4
#define S27_LINK_PARTNER_ABILITY 5
#define S27_AUTONEG_EXPANSION 6
#define S27_NEXT_PAGE_TRANSMIT 7
#define S27_LINK_PARTNER_NEXT_PAGE 8
#define S27_1000BASET_CONTROL 9
#define S27_1000BASET_STATUS 10
#define S27_MMD_CTRL_REG 13
#define S27_MMD_DATA_REG 14
#define S27_PHY_FUNC_CONTROL 16
#define S27_PHY_SPEC_STATUS 17
#define S27_PHY_INTR_ENABLE 18
#define S27_PHY_INTR_STATUS 19
#define S27_PHY_EXTEND_PHY_SPEC 20
#define S27_DEBUG_PORT_ADDRESS 29
#define S27_DEBUG_PORT_DATA 30
这部分是PHY的寄存器,对应datasheet中的8.20
2017.4.24 周一
MTK中,判断是否存在雷达信号的函数是SWRadarCheck,检查函数有tasklet进行调度,函数实现共600多行。
预先设定了雷达的参数,不同的认证标准参数值不同,然后这些参数和PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect中检测到的参数进行比较,得出是否存在雷达信号。
2017.4.25 周二
MTK的无线设备是PCI总线的设备,设备的数据结构是rt_pci_driver,通过函数pci_register_driver(&rt_pci_driver)进行调用。在设备的成员函数中有成员函数probe: rt_pci_probe,,该函数是一个探针函数,在挂载设备的驱动时,调用rt_pci_probe探针函数进行设备的初始化。
探针函数rt_pci_probe调用函数RtmpPhyNetDevInit,RtmpPhyNetDevInit中注册了发包函数:
pNetDevHook->xmit = rt28xx_send_packets;
2017.4.26 周三
函数首部代码占用另外一个寄存器的值s8(通常的别名是fp),把它设置为sp刚开始的值。
fp 帧指针寄存器(frame pointer):CPU通用寄存器($30),有是用来表示一个栈帧的基址。
栈帧:一个具有函数所有的栈空间的片段;在一些函数中,栈空间的大小是位置的,比如用定义可变长度的数组,这时候通过栈帧指针记录变化后的栈空间,这时栈帧指针可能会比栈指针大。如果发生栈溢出,那么可能出现栈帧指针被改写。
2017.4.27 周四
MTK无线MAC/BBP寄存器使用的映射地址是从1030.0000到103F.FFFF开始,映射到MIP上的位置是从0XB030.0000到0xB03F.0000,这个地址umapped
,uncached的地址,在代码中,函数rt2880_module_init的初始化时就给赋值基地址。
#define RTMP_MAC_CSR_ADDR 0xB0300000
#define RTMP_MAC_IRQ_NUM 4
csr_addr = (unsigned long)RTMP_MAC_CSR_ADDR;
dev_irq = RTMP_MAC_IRQ_NUM;
网络设备通过RTMP_DRIVER_MAIN_INF_CREATE(pAd, &net_dev);(该宏其实是封装了的函数RtmpPhyNetDevMainCreate)创建一个以太网类型的网络设备,通过设备的私有数据区关联一个无线设备。
pDevNew = RtmpOSNetDevCreate((INT32)MC_RowID, (UINT32 *)&IoctlIF,
INT_MAIN, 0, sizeof(struct mt_dev_priv), dev_name);
以太网设备的私有数据结构:
struct mt_dev_priv{
void *sys_handle;
void *wifi_dev;
unsigned long priv_flags;
UCHAR sniffer_mode;
}; 当中的wifi_dev就是无线设备的指针。
RtmpOSFileOpen 在内核态中打开无线的配置文件,其实现函数是filp_open,该函数返回 strcut file*结构指针,供后续操作使用。如读取文件内容:
int RtmpOSFileRead(RTMP_OS_FD osfd, char *pDataPtr, int readLen)
{
/* The object must have a read method */
if (osfd->f_op && osfd->f_op->read) {
return osfd->f_op->read(osfd, pDataPtr, readLen, &osfd->f_pos);
} else {
MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("no file read method\n"));
return -1;
}
}
然后初始化pNetDevHook,该pNetDevHook 通过函数RtmpOSNetDevAttach赋值给网络设备。
pNetDevHook->open = MainVirtualIF_open;
pNetDevHook->stop = MainVirtualIF_close;
pNetDevHook->xmit = rt28xx_send_packets;
2017.5.2 周二
Lex Lex 是一种生成扫描器的工具。扫描器是一种识别文本中的词汇模式的程序
Yacc 代表 Yet Another Compiler Compiler。 Yacc 的 GNU 版叫做 Bison。它是一种工具,将任何一种编程语言的所有语法翻译成针对此种语言的 Yacc 语 法解析器。它用巴科斯范式(BNF, Backus Naur Form)来书写。按照惯例,Yacc 文件有 .y 后缀
2017.5.4 周四
函数sock_open(const char *ifname, unsigned short etherType)
ifname 是设备的名称,这里是br0; etherType是包类型,这里是0x8f83。就是说这个函数直接打开了监听br0设备并且包类型是0x8f83的数据包。
关键是bind的实现
static int wc_bind(int sockfd, int ifindex, unsigned short protocol, char *errbuf)
{
struct sockaddr_ll sll;
memset(&sll, 0, sizeof(sll));
sll.sll_family = AF_PACKET;
sll.sll_ifindex = ifindex;
sll.sll_protocol = htons(protocol);
if (-1 == bind(sockfd, (struct sockaddr *)&sll, sizeof(sll)))
{
return -1;
}
return 0;
}
因为是直接发送二层包,所以需要判断要发送的数据包长度是否超过MTU,如果超过,需要多次发送,见函数_sendBigPkt。
一个简单实用的条件判断宏:
#define JUDGE_ERROR(string, condition, operation) \
do { \
if (condition) \
{ \
printf("%s\n", string); \
operation; \
} \
}while(0)
2017.5.10 周三
跟踪uboot升级软件出现的问题,发现原来是刷用户配置区的函数中使用了malloc 64KByte字节长度,但是malloc失败,导致升级错误。但是奇怪的是重新烧一次flash后,问题消失了。
2017.5.11 周四
关于关于fe_reset导致DUT重启卡死的问题,反馈是要先关闭DMA,然后再注销收包的tasklet:
int ei_close(struct net_device *dev)
{
…
fe_reset(); ç 搬到 tasklet kill 前做,將 FE 先停住
//tasklet_kill(&ei_local->tx_tasklet); ç remove it
tasklet_kill(&ei_local->rx_tasklet);
…
}
2017.5.12 周五
raeather.c中配置MAC地址,MAC地址共6字节,其中高2字节写入一个寄存器中,低4字节写入另外一个寄存器中,通过2个寄存器进行MAC地址的配置;
收包模式三种,一个是NAPI,一个是tasklet,一个是workqueue。现在驱动中使用的是tasklet,以太网驱动版本是v3.1。
在ei_open函数中注册中断处理函数:
err = request_irq( dev->irq, ei_interrupt, IRQF_DISABLED, dev->name, dev); // try to fix irq in open
中断函数主要读取中断状态寄存器的值,然后通过函数tasklet_hi_schedule(&ei_local->rx_tasklet);调度tasklet,
tasklet执行的函数通过tasklet_init(&ei_local->rx_tasklet, ei_receive, 0);进行注册。
2017.5.26 周五
和测试部讨论小米6导致DUT死机的问题,使用最新的MIUI版本8.2.23重新测试,没出现问题,查看出问题的小米miui版本是8.2.22,就是说更新了一版解决了这个问题。
2017.5.27 周六
看DMA使用的函数接口,特别是dma_map_single,pci_alloc_consistent的使用方法。
下午查阅到一个如何调试死机,连串口都唔反应的bug调试方法。通过JTAG工具,查看死机是cpu运行的位置和调用栈信息;然后通过反汇编得到这个位置所属的代码片段;最后查阅代码是wportal.ko中对TCP选项解析出现问题,TCP选项中EOL和NOP只有TYPE,没有长度,所以当收到这种包时,解析的while循环中当前指针位置按长度向前解析下一个option,但是EOL和NOP长度为0,所以指针不会移动,那么就出现死循环。
myModule: version magic '2.6.36+ mod_unload MIPS32_R2 32BIT ' should be '2.6.36 mod_unload MIPS32_R2 32BIT '
2017.5.31 周三
先解释一下task_pt_regs,在前面的描述中,内核栈高地址部分压入了通用寄存器及用户栈指针信息,这些寄存器作为一个整体pt_regs存放在栈高地址部分(内核struct pt_regs结构)。task_pt_regs返回的就是pt_regs的起始地址。