Message ID | m1oci4zv7h.fsf@fess.ebiederm.org |
---|---|
State | Not Applicable, archived |
Delegated to: | David Miller |
Headers | show |
Hello, Eric. On 03/31/2010 06:39 PM, Eric W. Biederman wrote: > Let me try a happy median between overwhelming and too little > information by giving you some experts, and a bit of overview. > > (Ugh after have writing this I certainly will agree that we > have some many layers in the device model that they become > obfuscating abstractions). Yeah, exactly, and this patchset is pushing it further with no documentation and indirections to high heavens. As someone who doesn't have much experience with namespaces, I can't make much sense of this patchset and it obfuscates the whole kobject thing more and that's a bad direction to be heading toward. > Looking through my code there are 3 types of callbacks. > - Callbacks to the namespace type of a children. > .child_ns_type Can you please also explain the relationships among kobjects, ns_types and NSes? > - Callbacks to find the namespace of a kobject. > .namespace > - Callbacks on the a namespace type to find the namespace > of a particular context. > .current_ns > .initial_ns (not used in my patchset) > .netlink_ns (not used in my patchset) > > In a world of weird explicitness I expect .child_ns_type and > .namespace could be made to go away by pushing through explicit > ns_type, and namespace parameters everywhere. But that seems > like an awful lot of unnecessary code churn and bloat with > the only real advantage being that we have an abstraction > stored explicit at each layer. * How much churn would it be? I would be willing to trade quite a bit if the following can go away. The sheer amount of indirection there scares me a lot. struct kobj_type { ... const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj); ... }; * Is it necessary to teach kobject layer the concept of namespaces? Wouldn't it be possible to let kobject and sysfs deal with tags and make namespaces use them? > static int kobj_bcast_filter(struct sock *dest_sk, struct sk_buff *skb, void *data) > { > struct kobject *kobj = data; > const struct kobj_ns_type_operations *ops; > > ops = kobj_ns_ops(kobj); > if (ops) { > const void *sock_ns, *ns; > ns = kobj->ktype->namespace(kobj); > sock_ns = ops->netlink_ns(dsk); > return sock_ns != ns; > } > > return 0; > } > > initial_ns is used to figure out what the initial/default > namespace is for a class of namespaces. We only report > with /sbin/hotplug events in the initial network namespace. > At least for now. > > static int kobj_usermode_filter(struct kobject *kobj) > { > const struct kobj_ns_type_operations *ops; > > ops = kobj_ns_ops(kobj); > if (ops) { > const void *init_ns, *ns; > ns = kobj->ktype->namespace(kobj); > init_ns = ops->initial_ns(); > return ns != init_ns; > } > > return 0; > } I can understand you would need two different ways of establishing the accessor depending on the mode of access (file IO or netlink) but can initial_ns ever be dynamic? Can't it just be void *inital_ns instead of a callback? Thanks.
diff --git a/include/linux/kobject.h b/include/linux/kobject.h index d9456f6..9452e39 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -138,6 +138,7 @@ extern const struct sysfs_ops kobj_sysfs_ops; enum kobj_ns_type { KOBJ_NS_TYPE_NONE = 0, + KOBJ_NS_TYPE_NET, KOBJ_NS_TYPES }; diff --git a/net/Kconfig b/net/Kconfig index 041c35e..265e33b 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -45,6 +45,14 @@ config COMPAT_NETLINK_MESSAGES menu "Networking options" +config NET_NS + bool "Network namespace support" + default n + depends on EXPERIMENTAL && NAMESPACES + help + Allow user space to create what appear to be multiple instances + of the network stack. + source "net/packet/Kconfig" source "net/unix/Kconfig" source "net/xfrm/Kconfig" diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 099c753..1b98e36 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -13,7 +13,9 @@ #include <linux/kernel.h> #include <linux/netdevice.h> #include <linux/if_arp.h> +#include <linux/nsproxy.h> #include <net/sock.h> +#include <net/net_namespace.h> #include <linux/rtnetlink.h> #include <linux/wireless.h> #include <net/wext.h> @@ -466,6 +468,37 @@ static struct attribute_group wireless_group = { }; #endif +static const void *net_current_ns(void) +{ + return current->nsproxy->net_ns; +} + +static const void *net_initial_ns(void) +{ + return &init_net; +} + +static const void *net_netlink_ns(struct sock *sk) +{ + return sock_net(sk); +} + +static struct kobj_ns_type_operations net_ns_type_operations = { + .type = KOBJ_NS_TYPE_NET, + .current_ns = net_current_ns, + .netlink_ns = net_netlink_ns, + .initial_ns = net_initial_ns, +}; + +static void net_kobj_ns_exit(struct net *net) +{ + kobj_ns_exit(KOBJ_NS_TYPE_NET, net); +} + +static struct pernet_operations sysfs_net_ops = { + .exit = net_kobj_ns_exit, +}; + #endif /* CONFIG_SYSFS */ #ifdef CONFIG_HOTPLUG @@ -506,6 +539,13 @@ static void netdev_release(struct device *d) kfree((char *)dev - dev->padded); } +static const void *net_namespace(struct device *d) +{ + struct net_device *dev; + dev = container_of(d, struct net_device, dev); + return dev_net(dev); +} + static struct class net_class = { .name = "net", .dev_release = netdev_release, @@ -515,6 +555,8 @@ static struct class net_class = { #ifdef CONFIG_HOTPLUG .dev_uevent = netdev_uevent, #endif + .ns_type = &net_ns_type_operations, + .namespace = net_namespace, }; /* Delete sysfs entries but hold kobject reference until after all @@ -587,5 +629,9 @@ void netdev_initialize_kobject(struct net_device *net) int netdev_kobject_init(void) { + kobj_ns_type_register(&net_ns_type_operations); +#ifdef CONFIG_SYSFS + register_pernet_subsys(&sysfs_net_ops); +#endif return class_register(&net_class); }