is using struct pernet_operations
and register_pernet_subsys(..)
the correct way to have a state per network namespace in a Linux kernel module?
Or is there a way just mark a kernel module and it will have an independent state in each network namespace?
Linux Kernel modules have only one state. Network namespaces need to be explicitly handled in the kernel module.
The key methods to use are register_pernet_subsys
, unregister_pernet_subsys
and net_generic
.
Here is an example kernel module:
#include <net/sock.h>
#include <net/netns/generic.h>
#include <net/net_namespace.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/pid_namespace.h>
/*
* Per network namespace data
*/
struct ns_data {
struct sock *sk;
};
/*
* Index to store custom data for each network namespace.
*/
static unsigned int net_id;
/*
* Called for every existing and added network namespaces
*/
static int __net_init ns_test_init(struct net *net)
{
// create (if not present) and access data item in network namespace (net) using the id (net_id)
struct ns_data *data = net_generic(net, net_id);
data->sk = -1; // initialize or example socket
// ...
return 0;
}
static void __net_exit ns_test_exit(struct net *net)
{
// called when the network namespace is removed
struct ns_data *data = net_generic(net, net_id);
// close socket
netlink_kernel_release(data->sk);
}
// callback to make the module network namespace aware
static struct pernet_operations net_ops __net_initdata = {
.init = ns_test_init,
.exit = ns_test_exit,
.id = &net_id,
.size = sizeof(struct ns_data),
};
static int __init netlink_test_init(void)
{
printk(KERN_INFO "netlink_test: Init module\n");
register_pernet_subsys(&net_ops);
return 0;
}
static void __exit netlink_test_exit(void)
{
printk(KERN_INFO "netlink_test: Exit module\n");
unregister_pernet_subsys(&net_ops);
}
module_init(netlink_test_init);
module_exit(netlink_test_exit);
MODULE_LICENSE("GPL");