给RTL8111网卡固定MAC地址的一种方法

        一些嵌入式主板集成了RTL8111网卡,出于成本原因没有加EEPROM,这样其MAC地址就无法固定,可能是随机数或全0,不利于使用。当然也可以利用脚本给它设置个MAC地址,但有时不记得修改,就有可能存在相同MAC地址。这里给出一种固定MAC地址方法。

        最近在使用NaoPi R4SE时遇到开机后 8111网卡的MAC为 00:00:00:00:00:00,导致无法使用。如果使用脚本命令:ifconfig enp1s0 hw ether 00:0C:29:6A:F7:72 ,也能分配MAC地址,这是临时的。要想永久固定MAC地址,我想到了一种办法,修改r8169驱动程序,让r8169驱动程序从文件中读取MAC地址,文件的MAC地址是系统第一次加载r8169驱动时随机生成,生成文件后,以后每次启动时就读此MAC文件,这样基本上不存在MAC地址相同现象。这种方法也等同于为RTL8111加了EEPROM芯片。
        我使用linux内核是 4.19.206的,从 r8169.c 里找到 函数:rtl_init_one,在此函数前增加:

#include <linux/fs.h>
#include <linux/random.h>

static int get_mac_addr(int bus,int devfn)
{
    struct file *fp;
    loff_t pos = 0;

    char filename[100]={0};
    int mac ;

    get_random_bytes(&mac,sizeof(int));

    sprintf(filename,"/etc/.rtl8111-%02x-%02x.mac",bus,devfn);
    fp = filp_open(filename, O_RDONLY, 0644);
    if (unlikely(IS_ERR(fp))) {
        fp = filp_open(filename, O_RDWR | O_CREAT, 0644);
        if (unlikely(IS_ERR(fp))) {
            return mac;
        }
        kernel_write(fp, &mac, sizeof(int), &pos);
        filp_close(fp,NULL);
        return mac;
    }

    kernel_read(fp, &mac, sizeof(int), &(pos));
    filp_close(fp, NULL);
    return mac;
}

        MAC地址文件保存在/etc目录下,如果有多张RTL8111网卡,会根据bus、devfn来区分网卡,分别使用不同的MAC地址文件。函数 get_mac_addr 的使用:

static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
	struct rtl8169_private *tp;
	struct net_device *dev;
	int chipset, region, i;
	int jumbo_max, rc;

        int mac=get_mac_addr(pdev->bus->number,pdev->devfn);

	dev = devm_alloc_etherdev(&pdev->dev, sizeof (*tp));
	if (!dev)
		return -ENOMEM;

        在函数rtl_init_one 后面这样修改:

	/* Get MAC address */
	switch (tp->mac_version) {
		u8 mac_addr[ETH_ALEN] __aligned(4);
	case RTL_GIGA_MAC_VER_35 ... RTL_GIGA_MAC_VER_38:
	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51:
		*(u32 *)&mac_addr[0] = rtl_eri_read(tp, 0xe0, ERIAR_EXGMAC);
		*(u16 *)&mac_addr[4] = rtl_eri_read(tp, 0xe4, ERIAR_EXGMAC);

		if (is_valid_ether_addr(mac_addr))
			rtl_rar_set(tp, mac_addr);
                else
                {
                    mac_addr[0]=0x00;
                    mac_addr[1]=0x2D;
                    mac_addr[2]=mac&0xFF;
                    mac_addr[3]=(mac>>8)&0xFF;
                    mac_addr[4]=(mac>>16)&0xFF;
                    mac_addr[5]=(mac>>24)&0xFF;
                    rtl_rar_set(tp, mac_addr);
                }
		break;
	default:
		break;
	}
	for (i = 0; i < ETH_ALEN; i++)
		dev->dev_addr[i] = RTL_R8(tp, MAC0 + i);

        我这里固定了MAC前两个字节为:00:2D,可以根据自己修改,后面4个字节随机生成。系统启动过程:

         可以看出已经成功为8111分配了MAC地址。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值