Chinaunix首页 | 论坛 | 博客
  • 博客访问: 716712
  • 博文数量: 79
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 1338
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-12 08:51
个人简介

XMU->九天揽月->五湖抓鳖->DSP->driver->kernel/OpenWRT->ISP/RTOS

文章分类

全部博文(79)

文章存档

2020年(2)

2018年(3)

2016年(7)

2015年(42)

2014年(25)

分类: LINUX

2015-03-10 20:06:11

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

  1. tl_wvr841_setup()
  2. ...
  3. u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00);
  4.     ath79_init_mac(ath79_eth0_data.mac_addr, mac, -1);
  5. ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0);
  6. 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有效性的
  1. 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地址,
  1. ath79_register_wmac() -> ath79_init_wmac_pdata()
  2. if (mac_addr) {
  3. memcpy(ath79_wmac_mac, mac_addr, sizeof(ath79_wmac_mac));
  4. 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时被内核拒绝。

  1. if (mac_addr)
  2. {
  3.     if (!is_valid_ether_addr(mac_addr))
  4.     {
  5.         random_ether_addr(mac_addr);
  6.         printk(KERN_ERR"ar71xx: using random MAC address for wmac%s\n",
  7.                 ath79_wmac_data.eeprom_name);
  8.     }
  9.     memcpy(ath79_wmac_mac, mac_addr, sizeof(ath79_wmac_mac));
  10.     ath79_wmac_data.macaddr = ath79_wmac_mac;
  11. }
实际上,机子出厂时,一定是用烧写器为在0x1fc00偏移写死了一个独特的合法mac,也就不会有这个问题。所以此问题也就纯粹是openwrt刷机者的烦恼了。

阅读(5368) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

polejo2016-07-12 13:51:52

这个地址是因开发板而异的,有的是在flash的最后一个block上。比如高通的自己的qsdk的处理就是  0x1fff0000。
由于arch/mips/ath79/mach-*.c中通过 MIPS_MACHINE来注册开发板,注册 spi、mtd分区表、netdev等platform_device,这时候driver的初始化只有在总线上找到对应的device时才会进行,所以此时是不能通过 mtd 分区来进行读取的。这里只能使用绝对地址来取mac。