ifconfig查看网口信息时,都有网口eth0、eth1。这个两个网口的名字驱动是如何分配的?要怎么将标准的eth1、eth0更改为LAN、WAN(或者用户可以自己定义名字)。再次ifconfig的时候显示LAN和WAN两个网卡。
以RK3568为例,设备树gmac0和gmac1两个节点会调用驱动里的rk_gmac_probe。在注册网络设备的时候会分配网络名字,这之前的网络设备名字都是eth%d。下面解析下整个分配名字的过程。
// drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c rk_gmac_probe -> stmmac_dvr_probe // drivers/net/ethernet/stmicro/stmmac/stmmac_main.c // printk("dwb -1- stmmac_dvr_probe --- priv->dev=%s\n\r", priv->dev->name); 可添加查看后面有打印log -> register_netdev // 在注册网络设备时改为eth0\eth1,这之前priv->dev->name="eth%d" -> register_netdevice // net/core/dev.c -> dev_get_valid_name(net, dev, dev->name); -> if (!dev_valid_name(name)) return -EINVAL; if (strchr(name, '%')) // 搜索名字中第一个%的位置 return dev_alloc_name_ns(net, dev, name); -> ret = __dev_alloc_name(net, name, buf); // net/core/dev.c if (ret >= 0) // 若大于0则将buf赋值给dev->name strlcpy(dev->name, buf, IFNAMSIZ); // printk("dwb -2- stmmac_dvr_probe --- priv->dev=%s\n\r", priv->dev->name); 可添加查看后面有打印log // arch/arm64/include/asm/page-def.h #define for_each_netdev(net, d) \ list_for_each_entry(d, &(net)->dev_base_head, dev_list) #define PAGE_SHIFT CONFIG_ARM64_PAGE_SHIFT 12 #define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) // net/core/dev.c static int __dev_alloc_name(struct net *net, const char *name, char *buf) { int i = 0; const char *p; const int max_netdevices = 8*PAGE_SIZE; unsigned long *inuse; struct net_device *d; if (!dev_valid_name(name)) return -EINVAL; p = strchr(name, '%'); // 获取"%"的位置 if (p) { if (p[1] != 'd' || strchr(p + 2, '%')) // 检查是否为"%"或"d",不是返回 return -EINVAL; /* Use one page as a bit array of possible slots */ inuse = (unsigned long *) get_zeroed_page(GFP_ATOMIC); // 分配一个物理页面作为位图,来对系统中该类型设备已用序列号进行标记 if (!inuse) return -ENOMEM; for_each_netdev(net, d) { // 循环网络设备 变量网络命名空间中的所有设备,即net_device结构 // printk("dwb -0- d->name=%s, name=%s, i=%d\n\r", d->name, name, i); 可添加查看后面有打印log if (!sscanf(d->name, name, &i)) // 获取同类型网络设备的其序列号 continue; // printk("dwb --- 11111111----continue\n\r"); 可添加查看后面有打印log if (i < 0 || i >= max_netdevices) // 判断序列号的范围 continue; // printk("dwb -1- i=%d\n\r", i); 可添加查看后面有打印log /* avoid cases where sscanf is not exact inverse of printf */ snprintf(buf, IFNAMSIZ, name, i); if (!strncmp(buf, d->name, IFNAMSIZ)) // 验证解析的序列号是否正确 set_bit(i, inuse); // 在位图中将该位标记 } // printk("dwb -2- i=%d\n\r", i); i = find_first_zero_bit(inuse, max_netdevices); // 找到第一个为0的序列号 free_page((unsigned long) inuse); } snprintf(buf, IFNAMSIZ, name, i); // 根据找到的序列号,输出完整的设备名 if (!__dev_get_by_name(net, buf)) // 在name_list链表中查找是否有同名的设备 return i; /* It is possible to run out of possible slots * when the name is long and there isn't enough space left * for the digits, or if all bits are used. */ return -ENFILE; }
dev_alloc_name(dev, dev->name)函数会在系统中找到这种类型的网络设备中第一个没有使用的序列号来替换设备名称中的%d,生成如eth5的设备名称。
在这里就为设备完成了完整设备名的组合,以后可以在处理位图时,可以直接使用内核实现的set_bit和find_first_zero_bit、clear_bit等函数。
介绍完网络名字的来源之后,现在实现将eth0改为LAN显示,将eth1改为WLAN显示
diff --git a/net/core/dev.c b/net/core/dev.c index 768b1dd5..38e187e8 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -8645,6 +8651,7 @@ int register_netdevice(struct net_device *dev) { int ret; struct net *net = dev_net(dev); + static int flag=1; BUILD_BUG_ON(sizeof(netdev_features_t) * BITS_PER_BYTE < NETDEV_FEATURE_COUNT); @@ -8663,7 +8670,20 @@ int register_netdevice(struct net_device *dev) ret = dev_get_valid_name(net, dev, dev->name); if (ret < 0) goto out; - + + if((!strcmp(dev->name , "eth0")) && flag) + { + snprintf(dev->name , IFNAMSIZ, "LAN"); + flag--; // printk("dwb --------55 ------eth0\n\r"); 可添加查看后面有打印log + } + else if(!strcmp(dev->name , "eth0")) + { + snprintf(dev->name , IFNAMSIZ, "WAN"); + flag++; // printk("dwb --------55 ------eth1\n\r");可添加查看后面有打印log + } + /* Init, if this function is available */ if (dev->netdev_ops->ndo_init) { ret = dev->netdev_ops->ndo_init(dev);
解析:在通过dev_get_valid_name分配好名字之后,将名字改为自己想要的名字。但是注意的是要定义个flag标志位,区分两个网口,正如上面分析的在分配名字的时候会扫描net_device *结构体下的所有设备中name函数与传进来的name=eth%d(这个是网口初始赋值)进行对比,没有发现有同类名字,则还是输出eth0。
所以若没有定义flag标志位,无论有多少个网口设备注册,经过register_netdevice函数分配出来的名字都是eth0
注:两个名字交换只要将标志位改为static int flag=0;
添加打印之后的log信息
[ 0.581826] dwb -0- d->name=lo, name=can%d, i=0 [ 0.581829] dwb --- 11111111----continue [ 0.581849] dwb -2- i=0 [ 0.582597] dwb -0- d->name=lo, name=can%d, i=0 [ 0.582617] dwb --- 11111111----continue [ 0.582632] dwb -0- d->name=can0, name=can%d, i=0 [ 0.582649] dwb -1- i=0 [ 0.582663] dwb -2- i=0 ---------------------- 以上是其他的网络设备注册 ----------------------------- [ 0.802759] dwb -1- stmmac_dvr_probe --- priv->dev=eth%d [ 0.802767] dwb -0- d->name=lo, name=eth%d, i=0 [ 0.802785] dwb --- 11111111----continue [ 0.802801] dwb -0- d->name=can0, name=eth%d, i=0 [ 0.802813] dwb --- 11111111----continue [ 0.802827] dwb -0- d->name=can1, name=eth%d, i=0 [ 0.802838] dwb --- 11111111----continue [ 0.802850] dwb -2- i=0 [ 0.802867] dwb --------55 ------eth0 [ 0.803203] dwb -2- stmmac_dvr_probe --- priv->dev=LAN --------------------- 以上是第一个网口扫描分配名字,遍历net_device *结构体下的所有设备名字,没有匹配的输出eth0 (dwb -2- i=0)--------------------------- [ 1.022609] dwb -1- stmmac_dvr_probe --- priv->dev=eth%d [ 1.022618] dwb -0- d->name=lo, name=eth%d, i=0 [ 1.022636] dwb --- 11111111----continue [ 1.022650] dwb -0- d->name=can0, name=eth%d, i=0 [ 1.022663] dwb --- 11111111----continue [ 1.022672] dwb -0- d->name=can1, name=eth%d, i=0 [ 1.022684] dwb --- 11111111----continue [ 1.022697] dwb -0- d->name=LAN, name=eth%d, i=0 [ 1.022709] dwb --- 11111111----continue [ 1.022721] dwb -2- i=0 [ 1.022737] dwb --------55 ------eth1 [ 1.023078] dwb -2- stmmac_dvr_probe --- priv->dev=WAN ----------------------以上是第二个网口扫描分配名字,遍历net_device *结构体下的所有设备名字,没有匹配的输出eth0 (dwb -2- i=0)由于有标志位flag 则区开两个网口--------------------------------