[TUN]: Introduce the tun_net structure and init/exit net ops.
This is the first step in making tuntap devices work in net namespaces. The structure mentioned is pointed by generic net pointer with tun_net_id id, and tun driver fills one on its load. It will contain only the tun devices list. So declare this structure and introduce net init and exit hooks. Signed-off-by: Pavel Emelyanov <xemul@openvz.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
17515408a1
commit
79d1760491
@@ -63,6 +63,7 @@
|
|||||||
#include <linux/if_tun.h>
|
#include <linux/if_tun.h>
|
||||||
#include <linux/crc32.h>
|
#include <linux/crc32.h>
|
||||||
#include <net/net_namespace.h>
|
#include <net/net_namespace.h>
|
||||||
|
#include <net/netns/generic.h>
|
||||||
|
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
@@ -106,6 +107,11 @@ struct tun_struct {
|
|||||||
|
|
||||||
/* Network device part of the driver */
|
/* Network device part of the driver */
|
||||||
|
|
||||||
|
static unsigned int tun_net_id;
|
||||||
|
struct tun_net {
|
||||||
|
struct list_head dev_list;
|
||||||
|
};
|
||||||
|
|
||||||
static LIST_HEAD(tun_dev_list);
|
static LIST_HEAD(tun_dev_list);
|
||||||
static const struct ethtool_ops tun_ethtool_ops;
|
static const struct ethtool_ops tun_ethtool_ops;
|
||||||
|
|
||||||
@@ -909,6 +915,37 @@ static const struct ethtool_ops tun_ethtool_ops = {
|
|||||||
.set_rx_csum = tun_set_rx_csum
|
.set_rx_csum = tun_set_rx_csum
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int tun_init_net(struct net *net)
|
||||||
|
{
|
||||||
|
struct tun_net *tn;
|
||||||
|
|
||||||
|
tn = kmalloc(sizeof(*tn), GFP_KERNEL);
|
||||||
|
if (tn == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&tn->dev_list);
|
||||||
|
|
||||||
|
if (net_assign_generic(net, tun_net_id, tn)) {
|
||||||
|
kfree(tn);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tun_exit_net(struct net *net)
|
||||||
|
{
|
||||||
|
struct tun_net *tn;
|
||||||
|
|
||||||
|
tn = net_generic(net, tun_net_id);
|
||||||
|
kfree(tn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pernet_operations tun_net_ops = {
|
||||||
|
.init = tun_init_net,
|
||||||
|
.exit = tun_exit_net,
|
||||||
|
};
|
||||||
|
|
||||||
static int __init tun_init(void)
|
static int __init tun_init(void)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@@ -916,9 +953,22 @@ static int __init tun_init(void)
|
|||||||
printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
|
printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
|
||||||
printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT);
|
printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT);
|
||||||
|
|
||||||
|
ret = register_pernet_gen_device(&tun_net_id, &tun_net_ops);
|
||||||
|
if (ret) {
|
||||||
|
printk(KERN_ERR "tun: Can't register pernet ops\n");
|
||||||
|
goto err_pernet;
|
||||||
|
}
|
||||||
|
|
||||||
ret = misc_register(&tun_miscdev);
|
ret = misc_register(&tun_miscdev);
|
||||||
if (ret)
|
if (ret) {
|
||||||
printk(KERN_ERR "tun: Can't register misc device %d\n", TUN_MINOR);
|
printk(KERN_ERR "tun: Can't register misc device %d\n", TUN_MINOR);
|
||||||
|
goto err_misc;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_misc:
|
||||||
|
unregister_pernet_gen_device(tun_net_id, &tun_net_ops);
|
||||||
|
err_pernet:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -935,6 +985,7 @@ static void tun_cleanup(void)
|
|||||||
}
|
}
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
|
|
||||||
|
unregister_pernet_gen_device(tun_net_id, &tun_net_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(tun_init);
|
module_init(tun_init);
|
||||||
|
Reference in New Issue
Block a user