1

在 Linux 内核模块中使用struct pernet_operationsregister_pernet_subsys(..)正确的方法来拥有每个网络命名空间的状态?

或者有没有办法只标记一个内核模块,它在每个网络命名空间中都有一个独立的状态?

4

1 回答 1

1

Linux 内核模块只有一种状态。网络命名空间需要在内核模块中显式处理。

使用的关键方法register_pernet_subsysunregister_pernet_subsysnet_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");
于 2020-06-24T15:37:10.413 回答