博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Openvswitch原理与代码分析(3): openvswitch内核模块的加载
阅读量:5254 次
发布时间:2019-06-14

本文共 6135 字,大约阅读时间需要 20 分钟。

在datapath/datapath.c中会调用module_init(dp_init);来初始化内核模块。

 

static int __init dp_init(void)

{
   int err;
 
   BUILD_BUG_ON(sizeof(struct ovs_skb_cb) > FIELD_SIZEOF(struct sk_buff, cb));
 
   pr_info("Open vSwitch switching datapath %s\n", VERSION);
 
   err = compat_init();
   if (err)
      goto error;
 
   err = action_fifos_init();
   if (err)
      goto error_compat_exit;
 
   err = ovs_internal_dev_rtnl_link_register();
   if (err)
      goto error_action_fifos_exit;
 
   err = ovs_flow_init();
   if (err)
      goto error_unreg_rtnl_link;
 
   err = ovs_vport_init();
   if (err)
      goto error_flow_exit;
 
   err = register_pernet_device(&ovs_net_ops);
   if (err)
      goto error_vport_exit;
 
   err = register_netdevice_notifier(&ovs_dp_device_notifier);
   if (err)
      goto error_netns_exit;
 
   err = ovs_netdev_init();
   if (err)
      goto error_unreg_notifier;
 
   err = dp_register_genl();
   if (err < 0)
      goto error_unreg_netdev;
 
   return 0;
 
error_unreg_netdev:
   ovs_netdev_exit();
error_unreg_notifier:
   unregister_netdevice_notifier(&ovs_dp_device_notifier);
error_netns_exit:
   unregister_pernet_device(&ovs_net_ops);
error_vport_exit:
   ovs_vport_exit();
error_flow_exit:
   ovs_flow_exit();
error_unreg_rtnl_link:
   ovs_internal_dev_rtnl_link_unregister();
error_action_fifos_exit:
   action_fifos_exit();
error_compat_exit:
   compat_exit();
error:
   return err;
}
 

其中比较重要的是调用了dp_register_genl(),这个就是注册netlink函数,从而ovs-vswitchd可以通过netlink调用内核。

 

static int dp_register_genl(void)

{
   int err;
   int i;
 
   for (i = 0; i < ARRAY_SIZE(dp_genl_families); i++) {
 
      err = genl_register_family(dp_genl_families[i]);
      if (err)
         goto error;
   }
 
   return 0;
 
error:
   dp_unregister_genl(i);
   return err;
}
 

这里dp_genl_families由四个netlink的family组成

 

static struct genl_family *dp_genl_families[] = {

   &dp_datapath_genl_family,
   &dp_vport_genl_family,
   &dp_flow_genl_family,
   &dp_packet_genl_family,
};
 

其中分别定义了以下的操作:

 

Family名称

.name

.ops

dp_datapath_genl_family

static struct genl_family dp_datapath_genl_family = {

   .id = GENL_ID_GENERATE,
   .hdrsize = sizeof(struct ovs_header),
   .name = OVS_DATAPATH_FAMILY,
   .version = OVS_DATAPATH_VERSION,
   .maxattr = OVS_DP_ATTR_MAX,
   .netnsok = true,
   .parallel_ops = true,
   .ops = dp_datapath_genl_ops,
   .n_ops = ARRAY_SIZE(dp_datapath_genl_ops),
   .mcgrps = &ovs_dp_datapath_multicast_group,
   .n_mcgrps = 1,
};
static struct genl_ops dp_datapath_genl_ops[] = {
   { .cmd = OVS_DP_CMD_NEW,
     .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
     .policy = datapath_policy,
     .doit = ovs_dp_cmd_new
   },
   { .cmd = OVS_DP_CMD_DEL,
     .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
     .policy = datapath_policy,
     .doit = ovs_dp_cmd_del
   },
   { .cmd = OVS_DP_CMD_GET,
     .flags = 0, /* OK for unprivileged users. */
     .policy = datapath_policy,
     .doit = ovs_dp_cmd_get,
     .dumpit = ovs_dp_cmd_dump
   },
   { .cmd = OVS_DP_CMD_SET,
     .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
     .policy = datapath_policy,
     .doit = ovs_dp_cmd_set,
   },
};
dp_vport_genl_family

struct genl_family dp_vport_genl_family = {

   .id = GENL_ID_GENERATE,
   .hdrsize = sizeof(struct ovs_header),
   .name = OVS_VPORT_FAMILY,
   .version = OVS_VPORT_VERSION,
   .maxattr = OVS_VPORT_ATTR_MAX,
   .netnsok = true,
   .parallel_ops = true,
   .ops = dp_vport_genl_ops,
   .n_ops = ARRAY_SIZE(dp_vport_genl_ops),
   .mcgrps = &ovs_dp_vport_multicast_group,
   .n_mcgrps = 1,
};
static struct genl_ops dp_vport_genl_ops[] = {
   { .cmd = OVS_VPORT_CMD_NEW,
     .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
     .policy = vport_policy,
     .doit = ovs_vport_cmd_new
   },
   { .cmd = OVS_VPORT_CMD_DEL,
     .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
     .policy = vport_policy,
     .doit = ovs_vport_cmd_del
   },
   { .cmd = OVS_VPORT_CMD_GET,
     .flags = 0, /* OK for unprivileged users. */
     .policy = vport_policy,
     .doit = ovs_vport_cmd_get,
     .dumpit = ovs_vport_cmd_dump
   },
   { .cmd = OVS_VPORT_CMD_SET,
     .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
     .policy = vport_policy,
     .doit = ovs_vport_cmd_set,
   },
};
dp_flow_genl_family

static struct genl_family dp_flow_genl_family = {

   .id = GENL_ID_GENERATE,
   .hdrsize = sizeof(struct ovs_header),
   .name = OVS_FLOW_FAMILY,
   .version = OVS_FLOW_VERSION,
   .maxattr = OVS_FLOW_ATTR_MAX,
   .netnsok = true,
   .parallel_ops = true,
   .ops = dp_flow_genl_ops,
   .n_ops = ARRAY_SIZE(dp_flow_genl_ops),
   .mcgrps = &ovs_dp_flow_multicast_group,
   .n_mcgrps = 1,
};
static struct genl_ops dp_flow_genl_ops[] = {
   { .cmd = OVS_FLOW_CMD_NEW,
     .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
     .policy = flow_policy,
     .doit = ovs_flow_cmd_new
   },
   { .cmd = OVS_FLOW_CMD_DEL,
     .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
     .policy = flow_policy,
     .doit = ovs_flow_cmd_del
   },
   { .cmd = OVS_FLOW_CMD_GET,
     .flags = 0, /* OK for unprivileged users. */
     .policy = flow_policy,
     .doit = ovs_flow_cmd_get,
     .dumpit = ovs_flow_cmd_dump
   },
   { .cmd = OVS_FLOW_CMD_SET,
     .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
     .policy = flow_policy,
     .doit = ovs_flow_cmd_set,
   },
};
dp_packet_genl_family

static struct genl_family dp_packet_genl_family = {

   .id = GENL_ID_GENERATE,
   .hdrsize = sizeof(struct ovs_header),
   .name = OVS_PACKET_FAMILY,
   .version = OVS_PACKET_VERSION,
   .maxattr = OVS_PACKET_ATTR_MAX,
   .netnsok = true,
   .parallel_ops = true,
   .ops = dp_packet_genl_ops,
   .n_ops = ARRAY_SIZE(dp_packet_genl_ops),
};
static struct genl_ops dp_packet_genl_ops[] = {
   { .cmd = OVS_PACKET_CMD_EXECUTE,
     .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
     .policy = packet_policy,
     .doit = ovs_packet_cmd_execute
   }
};
 

如上一节中,ovs-vswitchd启动的时候,将虚拟网卡添加到虚拟交换机上的时候,会调用netlink的OVS_VPORT_CMD_NEW命令,因而会调用函数ovs_vport_cmd_new。

会调用static struct vport *new_vport(const struct vport_parms *parms)

会调用struct vport *ovs_vport_add(const struct vport_parms *parms)里面会调用vport = ops->create(parms);

ops是什么呢?在dp_init函数中会调用ovs_netdev_init,它会调用ovs_vport_ops_register(&ovs_netdev_vport_ops);

static struct vport_ops ovs_netdev_vport_ops = {

   .type = OVS_VPORT_TYPE_NETDEV,
   .create = netdev_create,
   .destroy = netdev_destroy,
   .send = dev_queue_xmit,
};
 

所以ops->create会调用netdev_create,它会调用ovs_netdev_link,其中有下面的代码:

err = netdev_rx_handler_register(vport->dev, netdev_frame_hook,

                vport);
 

注册一个方法叫做netdev_frame_hook,每当网卡收到包的时候,就调用这个方法。

转载于:https://www.cnblogs.com/liuhongru/p/11416561.html

你可能感兴趣的文章
UOJ Round #15 [构造 | 计数 | 异或哈希 kmp]
查看>>
Countdown项目UML用例图
查看>>
struts2文件上传大小限制问题小结
查看>>
actor运行报错:java.lang.ClassNotFoundException
查看>>
Eclipse PHPEclipse 配置
查看>>
关于BigDecimal的四舍五入和截断 (转)
查看>>
VB刷网页程序(VB+DOS)
查看>>
LeetCode 153. Find Minimum in Rotated Sorted Array
查看>>
Xdebug在PHP中的安装配置
查看>>
JS实现select去除option的使用注意事项
查看>>
00085_异常
查看>>
ruby 方法(2)
查看>>
Python遍历列表删除多个元素或者重复元素
查看>>
jQuery内部原理和实现方式浅析
查看>>
windows共享虚拟机ubuntu目录
查看>>
常用SQL查询语句
查看>>
Python包管理工具setuptools详解及entry point
查看>>
ADB WiFi连接手机
查看>>
Centos7源码安装MySQL5.7
查看>>
no matter相关
查看>>