openwrt的无线开启可用 wifi up 命令,效果同luci network wifi控制界面的enable按钮。
[ 7956.390000] br-lan: port 1(eth1) entered forwarding state
Configuration file: /var/run/hostapd-phy0.conf
Could not set interface wlan0 flags (UP): Cannot assign requested address
nl80211: Could not set interface 'wlan0' UP
nl80211 driver initialization failed.
Failed to initialize interface
Failed to start hostapd for phy0
运行wifi up后,看到infconfig -a 会创建wlan0的netdev,找了一个无线ok的机子,发现wlan0 mac地址与lan相同。
而我的板子上wlan0的mac地址却与之不同!看来 Cannot assign requested address 指的是mac地址不对?
1.通过 vi /etc/config/wireless 添加一个正确的mac到option macaddr
重启wifi,还是失败,并且wlan0的mac又被还原成错误的那个!
2.找这个错误的mac是如何获取的?
cat /var/run/hostapd-phy0.conf
......
bssid=c6:6b:08:65:d9:36
ignore_broadcast_ssid=0
对于wlan这个,bssid就是mac。
3.再看/var/run/hostapd-phy0.conf如何生成的?
这个文件是启动后生成的,
grep 查找到 /lib/mac80211.sh 找到bssid的由来,
即为 bssid = /sys/class/ieee80211/phy0/macaddress
故每次运行wifi up,它都会从ieee80211/phy0重新获取macaddr到
hostapd-phy0.conf
所以必须在wifi设备创建时来修改mac才行。
研究了下,终于找到了根本原因和解决办法。
ar71xx方案的路由器都是从flash偏移0x1fc00出来获取mac地址的,并以这个为基础来配置eth0、eth1和wifi的mac,具体代码见arch/mips/ath79/mach-tl-wr841.c
-
tl_wvr841_setup()
-
...
-
u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00);
-
ath79_init_mac(ath79_eth0_data.mac_addr, mac, -1);
-
ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0);
-
ath79_register_wmac(ee, mac);
其中的
KSEG1ADDR(0x1f01fc00)就是使用mips的空间映射来访问flash的0x1fc00偏移获取mac。
而0x1fc00的偏移,我以前并不知道,也就没有特意去写这么一个mac地址,所以这个mac地址的值是如何来的呢。
原来uboot更新时一般都是直接用
的命令,cp.b 0x80000000 0x9f000000 0x20000; 写flash的uboot分区即第一个block,
即使实际下载的uboot长度并没有到1个block的长度,我的uboot_len只有0x1f680。这样就必然把尾巴上0x20000 - uboot_len 长度也写到flash上。
故而flash的0x1fc00偏移实际上就是从tftpboot的内存缓冲0x1fc00偏移写进去的随机值。
这是导致这个问题的根本原因,
内核从这个地址获取到mac后,给eth0 1 wifi,ath79的arch驱动中,eth设备注册时是有检测mac有效性的
-
ath79_register_eth() -> ath79_init_eth_pdata() -> is_valid_ether_addr(pdata->mac_addr)
is_valid_ether_addr() 检测mac有效只检测组播和全0,
组播就是首字节为奇数(0x01&macaddr[0] == 1即为非法,这个概率还是很大的),若地址非法,则随机生成一个mac给eth设备。
而wifi设备注册时却没有这个检测机制,直接拷贝了flash中的mac地址,
-
ath79_register_wmac() -> ath79_init_wmac_pdata()
-
if (mac_addr) {
-
memcpy(ath79_wmac_mac, mac_addr, sizeof(ath79_wmac_mac));
-
ath79_wmac_data.macaddr = ath79_wmac_mac;}
导致若被创建到/sys/class/ieee80211/phy0/macaddress就是一个错误地址,在wifi使能时就因为mac非法而无法生效。
到此,要想解决此问题,一个是修改flash 偏移0x1fc00处的mac地址为合法地址。
再一个是健壮性好一些。在wifi设备注册时添加mac有效性检测,非法则随机生成一个新的mac,保证sysfs中的wifi设备macaddress总是可用的。如此不至于在up wifi时被内核拒绝。
-
if (mac_addr)
-
{
-
if (!is_valid_ether_addr(mac_addr))
-
{
-
random_ether_addr(mac_addr);
-
printk(KERN_ERR"ar71xx: using random MAC address for wmac%s\n",
-
ath79_wmac_data.eeprom_name);
-
}
-
memcpy(ath79_wmac_mac, mac_addr, sizeof(ath79_wmac_mac));
-
ath79_wmac_data.macaddr = ath79_wmac_mac;
-
}
实际上,机子出厂时,一定是用烧写器为在0x1fc00偏移写死了一个独特的合法mac,也就不会有这个问题。所以此问题也就纯粹是openwrt刷机者的烦恼了。
阅读(5304) | 评论(1) | 转发(0) |