[openib-general] [PATCH RFC 2/31] net: Implement a place holder network namespace
Stephen Hemminger
shemminger at linux-foundation.org
Thu Jan 25 11:29:32 PST 2007
On Thu, 25 Jan 2007 12:00:04 -0700
"Eric W. Biederman" <ebiederm at xmission.com> wrote:
> From: Eric W. Biederman <ebiederm at xmission.com> - unquoted
>
> Many of the changes to the network stack will simply be adding a
> network namespace parameter to function calls or moving variables
> from globals to being per network namespace. When those variables
> have initializers that cannot statically compute the proper value,
> a function that runs at the creation and destruction of network
> namespaces will need to be registered, and the logic will need to
> be changed to accomidate that.
>
> Adding unconditional support for these functions ensures that even when
> everything else is compiled out the modified network stack logic will
> continue to run correctly.
>
> This patch adds struct pernet_operations that has an init (constructor)
> and an exit (destructor) method. When registered the init method
> is called for every existing namespace, and when unregistered the
> exit method is called for every existing namespace. When a new
> network namespace is created all of the init methods are called
> in the order in which they were registered, and when a network namespace
> is destroyed the exit methods are called in the reverse order in
> which they were registered.
>
> There are two distinct types of pernet_operations recognized: subsys and
> device. At creation all subsys init functions are called before device
> init functions, and at destruction all device exit functions are called
> before subsys exit function. For other ordering the preservation
> of the order of registration combined with the various kinds of
> kernel initcalls should be sufficient.
>
> Signed-off-by: Eric W. Biederman <ebiederm at xmission.com>
> +
> +static inline net_t get_net(net_t net) { return net; }
> +static inline void put_net(net_t net) {}
> +static inline net_t hold_net(net_t net) { return net; }
> +static inline void release_net(net_t net) {}
> +
> +#define __per_net_start ((char *)0)
> +#define __per_net_end ((char *)0
Don't use these use NULL
> +
> +static inline int copy_net(int flags, struct task_struct *tsk) { return 0; }
> +
> +/* Don't let the list of network namespaces change */
> +static inline void net_lock(void) {}
> +static inline void net_unlock(void) {}
Don't make all one line, or use #define instead.
> +
> +#define for_each_net(VAR) if (1)
> +
> +extern net_t net_template;
> +
> +#define NET_CREATE 0x0001 /* A network namespace has been created */
> +#define NET_DESTROY 0x0002 /* A network namespace is being destroyed */
> +
> +struct pernet_operations {
> + struct list_head list;
> + int (*init)(net_t net);
> + void (*exit)(net_t net);
> +};
> +
> +extern int register_pernet_subsys(struct pernet_operations *);
> +extern void unregister_pernet_subsys(struct pernet_operations *);
> +extern int register_pernet_device(struct pernet_operations *);
> +extern void unregister_pernet_device(struct pernet_operations *);
> +
> +#endif /* __NET_NET_NAMESPACE_H */
> diff --git a/net/core/Makefile b/net/core/Makefile
> index 73272d5..554dbdc 100644
> --- a/net/core/Makefile
> +++ b/net/core/Makefile
> @@ -3,7 +3,7 @@
> #
>
> obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \
> - gen_stats.o gen_estimator.o
> + gen_stats.o gen_estimator.o net_namespace.o
>
> obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
>
> diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
> new file mode 100644
> index 0000000..4ae266d
> --- /dev/null
> +++ b/net/core/net_namespace.c
> @@ -0,0 +1,149 @@
> +#include <linux/rtnetlink.h>
> +#include <net/net_namespace.h>
> +
> +/*
> + * Our network namespace constructor/destructor lists
> + */
> +
> +static LIST_HEAD(pernet_list);
> +static struct list_head *first_device = &pernet_list;
> +static DEFINE_MUTEX(net_mutex);
> +net_t net_template;
> +
> +static int register_pernet_operations(struct list_head *list,
> + struct pernet_operations *ops)
> +{
> + net_t net, undo_net;
> + int error;
> +
> + error = 0;
> + list_add_tail(&ops->list, list);
> + for_each_net(net) {
> + if (ops->init) {
> + error = ops->init(net);
> + if (error)
> + goto out_undo;
> + }
> + }
> +out:
> + return error;
> +
> +out_undo:
> + /* If I have an error cleanup all namespaces I initialized */
> + list_del(&ops->list);
> + for_each_net(undo_net) {
> + if (net_eq(undo_net, net))
> + goto undone;
> + if (ops->exit)
> + ops->exit(undo_net);
> + }
> +undone:
> + goto out;
> +}
> +
> +static void unregister_pernet_operations(struct pernet_operations *ops)
> +{
> + net_t net;
> +
> + list_del(&ops->list);
> + for_each_net(net)
> + if (ops->exit)
> + ops->exit(net);
> +}
> +
>
You should use RCU for this because registering/unregistering network
namespaces is obviously a much rarer occurrence than referencing them.
--
Stephen Hemminger <shemminger at linux-foundation.org>
More information about the general
mailing list