如何在每个网络名称空间中编写作为新实例的 Linux 内核模块?
How to write Linux kernel module that is a new instance in each network namespace?
使用 struct pernet_operations
和 register_pernet_subsys(..)
是在 Linux 内核模块中为每个网络命名空间设置状态的正确方法吗?
或者有没有办法只标记一个内核模块,它在每个网络命名空间中都有一个独立的状态?
Linux 内核模块只有一种状态。网络名称空间需要在内核模块中明确处理。
要使用的关键方法是 register_pernet_subsys
、unregister_pernet_subsys
和 net_generic
。
这是一个示例内核模块:
#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");
使用 struct pernet_operations
和 register_pernet_subsys(..)
是在 Linux 内核模块中为每个网络命名空间设置状态的正确方法吗?
或者有没有办法只标记一个内核模块,它在每个网络命名空间中都有一个独立的状态?
Linux 内核模块只有一种状态。网络名称空间需要在内核模块中明确处理。
要使用的关键方法是 register_pernet_subsys
、unregister_pernet_subsys
和 net_generic
。
这是一个示例内核模块:
#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");