Getting list of network devices inside the Linux kernel

前端 未结 2 403
耶瑟儿~
耶瑟儿~ 2021-02-01 23:10

I\'ve been looking through net/core/dev.c and other files to try to find out how to get the list of network devices that are currently configured and it\'s proving to be a littl

相关标签:
2条回答
  • 2021-02-01 23:54

    This ought to do the trick:

    #include <linux/netdevice.h>
    
    struct net_device *dev;
    
    read_lock(&dev_base_lock);
    
    dev = first_net_device(&init_net);
    while (dev) {
        printk(KERN_INFO "found [%s]\n", dev->name);
        dev = next_net_device(dev);
    }
    
    read_unlock(&dev_base_lock);
    
    0 讨论(0)
  • 2021-02-01 23:54

    Given a struct net *net identifying the net namespace that you are interested in, you should grab the dev_base_lock and use for_each_netdev():

    read_lock(&dev_base_lock);
    for_each_netdev(net, dev) {
       /* Inspect dev */
    }
    read_unlock(&dev_base_lock);
    

    (In newer kernels, you can use RCU instead, but that is probably an overcomplication in this case).


    To obtain the net namespace to use, you should be registering your proc file with register_pernet_subsys():

    static const struct file_operations foostats_seq_fops = {
        .owner   = THIS_MODULE,
        .open    = foostats_seq_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
        .release = foostats_seq_release,
    };
    
    static int foo_proc_init_net(struct net *net)
    {
        if (!proc_net_fops_create(net, "foostats", S_IRUGO,
                &foostats_seq_fops))
            return -ENOMEM;
        return 0;
    }
    
    static void foo_proc_exit_net(struct net *net)
    {
        proc_net_remove(net, "foostats");
    }
    
    
    static struct pernet_operations foo_proc_ops = {
        .init = foo_proc_init_net,
        .exit = foo_proc_exit_net,
    };
    
    register_pernet_subsys(&foo_proc_ops)
    

    In your foostats_seq_open() function, you take a reference on the net namespace, and drop it in the release function:

    static int foostats_seq_open(struct inode *inode, struct file *file)
    {
        int err;
        struct net *net;
    
        err = -ENXIO;
        net = get_proc_net(inode);
        if (net == NULL)
            goto err_net;
    
        err = single_open(file, foostats_seq_show, net);
        if (err < 0)
            goto err_open;
    
        return 0;
    
    err_open:
        put_net(net);
    err_net:
        return err;
    }
    
    static int foostats_seq_release(struct inode *inode, struct file *file)
    {
        struct net *net = ((struct seq_file *)file->private_data)->private;
    
        put_net(net);
        return single_release(inode, file);
    }
    

    The foostats_seq_show() function can then obtain the net, walk the devices, gather the statistics and produce the output:

    static int sockstat6_seq_show(struct seq_file *seq, void *v)
    {
        struct net *net = seq->private;
        struct net_device *dev;
    
        int foostat, barstat;
    
        read_lock(&dev_base_lock);
        for_each_netdev(net, dev) {
           /* Inspect dev */
        }
        read_unlock(&dev_base_lock);
    
        seq_printf(seq, "Foo: %d\n", foostat);
        seq_printf(seq, "Bar: %d\n", barstat);
    
        return 0;
    }
    
    0 讨论(0)
提交回复
热议问题