Linux教程

[ Linux RK ] 更改网卡名字|CSDN创作打卡

本文主要是介绍[ Linux RK ] 更改网卡名字|CSDN创作打卡,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文章目录

    • 背景
    • 解析设置网卡设备默认名字eth0/eth1的过程
    • 更改网卡名字
    • 整体打印log解析
    • 实现效果图

背景

ifconfig查看网口信息时,都有网口eth0、eth1。这个两个网口的名字驱动是如何分配的?要怎么将标准的eth1、eth0更改为LAN、WAN(或者用户可以自己定义名字)。再次ifconfig的时候显示LAN和WAN两个网卡。

解析设置网卡设备默认名字eth0/eth1的过程

以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解析

添加打印之后的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 则区开两个网口--------------------------------

实现效果图

在这里插入图片描述

这篇关于[ Linux RK ] 更改网卡名字|CSDN创作打卡的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!