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