Adds to the network namespace a device list view. This view is emptied when the unshare is done. The view is filled/emptied by a set of function which can be called by an external module.
Replace-Subject: [Network namespace] Network device sharing by view Signed-off-by: Daniel Lezcano <[EMAIL PROTECTED]> -- include/linux/net_ns.h | 2 include/linux/net_ns_dev.h | 32 +++++++ init/version.c | 4 net/core/Makefile | 2 net/core/net_ns_dev.c | 205 +++++++++++++++++++++++++++++++++++++++++++++ net/net_ns.c | 6 + 6 files changed, 250 insertions(+), 1 deletion(-) Index: 2.6-mm/include/linux/net_ns_dev.h =================================================================== --- /dev/null +++ 2.6-mm/include/linux/net_ns_dev.h @@ -0,0 +1,32 @@ +#ifndef _LINUX_NET_NS_DEV_H +#define _LINUX_NET_NS_DEV_H + +struct net_device; + +struct net_ns_dev { + struct list_head list; + struct net_device *dev; +}; + +struct net_ns_dev_list { + struct list_head list; + rwlock_t lock; +}; + +extern int net_ns_dev_unregister(struct net_device *dev, + struct net_ns_dev_list *devlist); + +extern int net_ns_dev_register(struct net_device *dev, + struct net_ns_dev_list *devlist); + +extern struct net_device *net_ns_dev_find_by_name(const char *devname, + struct net_ns_dev_list *devlist); +extern int net_ns_dev_remove(const char *devname, + struct net_ns_dev_list *devlist); + +extern int net_ns_dev_add(const char *devname, + struct net_ns_dev_list *devlist); + +extern int free_net_ns_dev(struct net_ns_dev_list *devlist); + +#endif Index: 2.6-mm/include/linux/net_ns.h =================================================================== --- 2.6-mm.orig/include/linux/net_ns.h +++ 2.6-mm/include/linux/net_ns.h @@ -4,9 +4,11 @@ #include <linux/kref.h> #include <linux/sched.h> #include <linux/nsproxy.h> +#include <linux/net_ns_dev.h> struct net_namespace { struct kref kref; + struct net_ns_dev_list dev_list; }; extern struct net_namespace init_net_ns; Index: 2.6-mm/net/core/net_ns_dev.c =================================================================== --- /dev/null +++ 2.6-mm/net/core/net_ns_dev.c @@ -0,0 +1,205 @@ +/* + * net_ns_dev.c - adds namespace netwok device view + * + * Copyright (C) 2006 IBM + * + * Author: Daniel Lezcano <[EMAIL PROTECTED]> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + */ +#include <linux/list.h> +#include <linux/spinlock.h> +#include <linux/netdevice.h> +#include <linux/net_ns_dev.h> + +int free_net_ns_dev(struct net_ns_dev_list *devlist) +{ + struct list_head *l, *next; + struct net_ns_dev *db; + struct net_device *dev; + + write_lock(&devlist->lock); + list_for_each_safe(l, next, &devlist->list) { + db = list_entry(l, struct net_ns_dev, list); + dev = db->dev; + list_del(&db->list); + dev_put(dev); + kfree(db); + } + write_unlock(&devlist->lock); + + return 0; +} + +/* + * Remove a device to the namespace network devices list + * when registered from a namespace + * @dev : network device + * @dev_list: network namespace devices + * Return ENODEV if the device does not exist, + */ +int net_ns_dev_unregister(struct net_device *dev, + struct net_ns_dev_list *devlist) +{ + struct net_ns_dev *db; + struct list_head *l; + int ret = -ENODEV; + + write_lock(&devlist->lock); + list_for_each(l, &devlist->list) { + db = list_entry(l, struct net_ns_dev, list); + if (dev != db->dev) + continue; + + list_del(&db->list); + dev_put(dev); + kfree(db); + ret = 0; + break; + } + write_unlock(&devlist->lock); + return ret; +} + +EXPORT_SYMBOL_GPL(net_ns_dev_unregister); + +/* + * Add a device to the namespace network devices list + * when registered from a namespace + * @dev : network device + * @dev_list: network namespace devices + * Return ENOMEM if allocation fails, 0 on success + */ +int net_ns_dev_register(struct net_device *dev, + struct net_ns_dev_list *devlist) +{ + struct net_ns_dev *db; + + db = kmalloc(sizeof(*db), GFP_KERNEL); + if (!db) + return -ENOMEM; + + write_lock(&devlist->lock); + dev_hold(dev); + db->dev = dev; + list_add_tail(&db->list, &devlist->list); + write_unlock(&devlist->lock); + + return 0; +} + +EXPORT_SYMBOL_GPL(net_ns_dev_register); + +/* + * Add a device to the namespace network devices list + * @devname : network device name + * @dev_list: network namespace devices + * Return ENODEV if the device does not exist, + * ENOMEM if allocation fails, 0 on success + */ +int net_ns_dev_add(const char *devname, + struct net_ns_dev_list *devlist) +{ + struct net_ns_dev *db; + struct net_device *dev; + int ret = 0; + + read_lock(&dev_base_lock); + + for (dev = dev_base; dev; dev = dev->next) + if (!strncmp(dev->name, devname, IFNAMSIZ)) + break; + + if (!dev) { + ret = -ENODEV; + goto out; + } + + db = kmalloc(sizeof(*db), GFP_KERNEL); + if (!db) { + ret = -ENOMEM; + goto out; + } + + write_lock(&devlist->lock); + db->dev = dev; + dev_hold(dev); + list_add_tail(&db->list, &devlist->list); + write_unlock(&devlist->lock); + +out: + read_unlock(&dev_base_lock); + + return ret; +} + +EXPORT_SYMBOL_GPL(net_ns_dev_add); + +/* + * Remove a device from the namespace network devices list + * @devname : network device name + * @dev_list: network namespace devices + * Return ENODEV if the device does not exist, 0 on success + */ +int net_ns_dev_remove(const char *devname, + struct net_ns_dev_list *devlist) +{ + struct net_ns_dev *db; + struct net_device *dev; + struct list_head *l; + int ret = 0; + + write_lock(&devlist->lock); + list_for_each(l, &devlist->list) { + db = list_entry(l, struct net_ns_dev, list); + dev = db->dev; + + if (!strncmp(dev->name, devname, IFNAMSIZ)) { + list_del(&db->list); + dev_put(dev); + kfree(db); + goto out; + } + } + ret = -ENODEV; +out: + write_unlock(&devlist->lock); + return ret; +} + +EXPORT_SYMBOL_GPL(net_ns_dev_remove); + +/* + * Find a namespace network device + * @devname : network device name + * @dev_list: network namespace devices + * Return ENODEV if the device does not exist, 0 on success + */ +struct net_device *net_ns_dev_find_by_name(const char *devname, + struct net_ns_dev_list *devlist) +{ + struct net_ns_dev *db; + struct net_device *dev; + struct list_head *l; + + read_lock(&devlist->lock); + + list_for_each(l, &devlist->list) { + db = list_entry(l, struct net_ns_dev, list); + dev = db->dev; + + if (!strncmp(dev->name, devname, IFNAMSIZ)) { + dev_hold(dev); + goto out; + } + } + dev = NULL; +out: + read_unlock(&devlist->lock); + return dev; +} + +EXPORT_SYMBOL_GPL(net_ns_dev_find_by_name); Index: 2.6-mm/net/net_ns.c =================================================================== --- 2.6-mm.orig/net/net_ns.c +++ 2.6-mm/net/net_ns.c @@ -23,11 +23,16 @@ struct net_namespace *clone_net_ns(struct net_namespace *old_ns) { struct net_namespace *new_ns; + struct net_ns_dev_list *new_dev_list; new_ns = kmalloc(sizeof(*new_ns), GFP_KERNEL); if (!new_ns) return NULL; + kref_init(&new_ns->kref); + new_dev_list = &new_ns->dev_list; + INIT_LIST_HEAD(&new_dev_list->list); + new_dev_list->lock = RW_LOCK_UNLOCKED; return new_ns; } @@ -92,5 +97,6 @@ void free_net_ns(struct kref *kref) struct net_namespace *ns; ns = container_of(kref, struct net_namespace, kref); + free_net_ns_dev(&ns->dev_list); kfree(ns); } Index: 2.6-mm/net/core/Makefile =================================================================== --- 2.6-mm.orig/net/core/Makefile +++ 2.6-mm/net/core/Makefile @@ -7,7 +7,7 @@ obj-y := sock.o request_sock.o skbuff.o obj-$(CONFIG_SYSCTL) += sysctl_net_core.o -obj-y += dev.o ethtool.o dev_mcast.o dst.o \ +obj-y += dev.o net_ns_dev.o ethtool.o dev_mcast.o dst.o \ neighbour.o rtnetlink.o utils.o link_watch.o filter.o obj-$(CONFIG_XFRM) += flow.o Index: 2.6-mm/init/version.c =================================================================== --- 2.6-mm.orig/init/version.c +++ 2.6-mm/init/version.c @@ -38,6 +38,10 @@ struct net_namespace init_net_ns = { .kref = { .refcount = ATOMIC_INIT(2), }, + .dev_list = { + .lock = RW_LOCK_UNLOCKED, + .list = LIST_HEAD_INIT(init_net_ns.dev_list.list), + }, }; EXPORT_SYMBOL_GPL(init_net_ns); -- - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html