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

在网卡设备的驱动中首先会调用

    ndev = alloc_etherdev_mq(sizeof(struct hns_nic_priv), NIC_MAX_Q_PER_VF);
    if (!ndev)
        return -ENOMEM;
来申请一个struct net_device *ndev;
#define alloc_etherdev_mq(sizeof_priv, count) alloc_etherdev_mqs(sizeof_priv, count, count)
struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs,
                      unsigned int rxqs)
{
    return alloc_netdev_mqs(sizeof_priv, "eth%d", NET_NAME_UNKNOWN,
                ether_setup, txqs, rxqs);
}
注意这里的网卡驱动赋值的name是eth%d。在alloc_etherdev_mqs 完成后这个网卡设备驱动的name就是eth%d。在最后调用register_netdevice的时候才会改名为eth0/eth1等

register_netdevice->dev_get_valid_name
static int dev_get_valid_name(struct net *net,
                  struct net_device *dev,
                  const char *name)
{
    BUG_ON(!net);

    if (!dev_valid_name(name))
        return -EINVAL;

    if (strchr(name, '%'))
        return dev_alloc_name_ns(net, dev, name);
    else if (__dev_get_by_name(net, name))
        return -EEXIST;
    else if (dev->name != name)
        strlcpy(dev->name, name, IFNAMSIZ);

    return 0;
}

因为申请的名字是eth%d,因此strchr(name, '%')成立调用dev_alloc_name_ns->__dev_alloc_name
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;

    p = strnchr(name, IFNAMSIZ-1, '%');
    if (p) {
        /*
         * Verify the string as this thing may have come from
         * the user.  There must be either one "%d" and no other "%"
         * characters.
         */
        if (p[1] != 'd' || strchr(p + 2, '%'))
            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) {
//为网卡设备改名这样就可以通过ifconfig 看到eth0/eth1等等
            if (!sscanf(d->name, name, &i))
                continue;
            if (i < 0 || i >= max_netdevices)
                continue;

            /*  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);
        }

        i = find_first_zero_bit(inuse, max_netdevices);
        free_page((unsigned long) inuse);
    }

}

你可能感兴趣的:(Linux,源码分析)