网关第二路网口(eth1)mac地址烧录问题

背景

网卡使用的是sigmastar的SSD202D芯片,该芯片有两个网口,其中一个网口需要外部的phy,方案图如下:
ssd201双网口方案
那么两个网口的mac地址是怎么存储的呢?如果是存储在mac模块内的flash是最理想的,烧录一次后就跟硬件走,芯片出厂前厂家烧录到芯片内更好。然而并不是。查看资料和代码后知道芯片并不会存储,每次上电后需要写入到mac寄存器。厂家的文档可以印证:
mac地址烧录官方方案
意思是厂家提供一个脚本,开机进入系统后自动读取eth0的mac地址,+1后写到eth1去。

问题

本来我也是用厂家这个脚本的,直到测试提几个问题单才发现有缺陷:

  • 通过dhcp获取ip地址,每次重启后ip地址都会变;
  • 在路由上看设备会占用好几个ip;
  • 用非ifconfig列表的ip地址也能访问网关;

这些问题现象看起来很诡异的,每次都怀疑是不是测试搞错了。专门花时间分析了一下网络相关,原因也慢慢知道了。通过厂家的脚本写mac地址的方案在我们项目这里有个问题,这个脚本在dhcp之后才被执行! 就是说开机启动后eth1拿的一个不可预知的mac地址(跟eth0同一个默认mac地址)通过dhcp获取到了ip地址,然后再通过脚本配置了一个新的mac地址,然后再dhcp一个新的ip地址,所以导致了上面这些问题。

解决

这个问题可以通过把设置mac地址的脚本提前来解决,脚本目录如下:

# ls /etc/init.d/
S01syslogd  S02klogd    S02sysctl   S10mdev     S20urandom  S21haveged  S40network  S41dhcpcd   S50sshd     rcK         rcS

S40network S41dhcpcd 这两个脚本负责配置网络,我在 rcS 脚本设备eth1的mac地址,rcS 在后面执行的,想解决的话可以把脚本放在 S40network 脚本之前。
想了一下,这种方式还是不靠谱,因为设置mac地址的脚本依赖 ifconfig 命令,如果网络都没配置的话,命令执行的是什么结果呢?我没有去验证这个事情,因为我找到了更好的办法 - 修改uboot源码。看源码时得知,在uboot启动时会从 env 区(flash)读取eth0的mac地址,并写到mac寄存器,内核启动后加载mac驱动,驱动会尝试从mac寄存器读mac地址,验证是合法的就继续使用,不合法就用默认的mac地址。所以官方文档推荐在uboot通过” setenv -f ethaddr xx:xx:xx:xx:xx:xx “命令来烧录eth0的mac地址,但是eth1却晾下不管了(估计同系列有的芯片只有eth0)。
uboot启动时,会从 env 区读取eth0的mac地址,然后写到mac寄存器去,我添加了一段代码,把mac地址+1,同时写到eth1的mac寄存器去,以上问题得以解决。当然,只有一个网口的芯片不能用同一套uboot的代码。修改代码如下:
/boot/drivers/mstar/emac/infinity2m/mhal_emac.c

/*
    根据 emac0 计算 emac1, emac1 的mac 地址默认比 emac0 大1
*/
void MHal_calc_emac1_mac(u32 *w0, u32 *w1, u8 m0,u8 m1,u8 m2,u8 m3,u8 m4,u8 m5)
{
    m5 += 1;
    if (m5 == 0) 
    {
        m4 += 1;
        if (m4 == 0) 
        {
            m3 += 1;
            if (m3 == 0) 
            {
                m2 += 1;
                if (m2 == 0) 
                {
                    m1 += 1;
                    if (m1 == 0) 
                    {
                        m0 += 1;
                    }
                }
            }
        }
    }

    *w0 = (u32)m3 << 24 | m2 << 16 | m1 << 8 | m0;
    *w1 = (u32)m5 <<  8 | m4;
}

void MHal_EMAC_Write_SA1_MAC_Address(u8 m0,u8 m1,u8 m2,u8 m3,u8 m4,u8 m5)
{
    u32 w0 = (u32)m3 << 24 | m2 << 16 | m1 << 8 | m0;
    u32 w1 = (u32)m5 <<  8 | m4;
    TITANIA_EMAC regs = (TITANIA_EMAC) REG_ADDR_BASE;

    // 设置emac0的mac地址
    regs->REG_EMAC_SA1L_L= w0&0x0000FFFF;
    regs->REG_EMAC_SA1L_H= w0>>16;
    regs->REG_EMAC_SA1H_L= w1&0x0000FFFF;
    regs->REG_EMAC_SA1H_H= w1>>16;

    // 添加对emac1 mac地址设置
    MHal_calc_emac1_mac(&w0, &w1, m0, m1, m2, m3, m4, m5);
    regs = (TITANIA_EMAC) REG_ADDR_BASE_EMAC1;
    regs->REG_EMAC_SA1L_L= w0&0x0000FFFF;
    regs->REG_EMAC_SA1L_H= w0>>16;
    regs->REG_EMAC_SA1H_L= w1&0x0000FFFF;
    regs->REG_EMAC_SA1H_H= w1>>16;
}

上面代码的 MHal_calc_emac1_mac 函数是自己实现的,然后需要找到emac1的基址,学着emac0一样写进去即可。

总结

  • BUG要认真对待,了解内部实现并深入分析,不然表面现象会百思不得其解。
  • 厂商可能是同一个uboot同时适配单个或多个网口的型号,所以用脚本的方案,可能改变脚本的启动顺序也能解决。无论用哪种方案,要写清楚文档或者代码提交记录,否则后面的人很难理解。

end

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值