重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
初始化有两步,先使用宏初始化内存然后再使用函数添加
为忻府等地区用户提供了全套网页设计制作服务,及忻府网站建设行业解决方案。主营业务为网站制作、网站设计、忻府网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!
1.1 先初始化arc
arc就是一串有序的feature的集合
VNET_FEATURE_ARC_INIT (device_input, static) = { .arc_name = "device-input", .start_nodes = VNET_FEATURES ("device-input"), .arc_index_ptr = &feature_main.device_input_feature_arc_index, };
1.2 再初始化这个arc下的feature,通过.runs_before来控制feature的先后关系,当然也有runs_after
VNET_FEATURE_INIT (worker_handoff, static) = { .arc_name = "device-input", .node_name = "worker-handoff", .runs_before = VNET_FEATURES ("ethernet-input"), }; VNET_FEATURE_INIT (span_input, static) = { .arc_name = "device-input", .node_name = "span-input", .runs_before = VNET_FEATURES ("ethernet-input"), }; VNET_FEATURE_INIT (ethernet_input, static) = { .arc_name = "device-input", .node_name = "ethernet-input", .runs_before = 0, /* not before any other features */};
把这些node都挂在对应的构造函数上,在初始化的时候就会调用。然后初始化相应的配置,也就是vnet_feature_arc_init 这个函数,会根据之前的配置,将各feature的先后关系排列好。此时只是排列好顺序,并未插入feature_arc中,也就是不会被调用到。
调用vnet_feature_enable_disable即可,此时才是将要用到的feature真正的插入feature_arc中。
具体的实现是 vnet_config_add_feature() vnet_config_del_feature() 这两个个函数跟之前版本的feature没有什么区别了。
按照老版本的思想,feature至少分为两种,接口的feature和其他的feature
在node的处理函数里调用vnet_feature_arc_start就好了。
通过命令show features可以看到成功加载的feature。
接口的feature与之前的版本不一样,是移至ip4-rewrite中进行接口feature的跳转。
通过命令show interface features xxx,可以看到接口的feature。
初始化会有一点变化,说一下区别
代码里并没有ip4-output这个节点,它只是一个arc_name。它的起始结点是使用.start_nodes挂上的两个。也就是ip4-rewrite与ip4-midchain。 在ip4-rewrite里跳转的feature
此处多说一句,"ip4-rewrite", "ip4-midchain"两个节点(最终调用的一个函数ip4_rewrite_inline),都有name为ip4-output的feature arc。具体在vnet_feature_init中实现的。
VNET_FEATURE_ARC_INIT (ip4_output, static) = { .arc_name = "ip4-output", .start_nodes = VNET_FEATURES ("ip4-rewrite", "ip4-midchain"), .arc_index_ptr = &ip4_main.lookup_main.output_feature_arc_index, };
在函数ip4_rewrite_inline中
ip4_rewrite_inline() { ...... if (PREDICT_TRUE (error0 == IP4_ERROR_NONE)) { p0->current_data -= rw_len0; p0->current_length += rw_len0; "从adj的rewrite取得sw_if_index" tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index; vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0; next0 = adj0[0].rewrite_header.next_index; if (is_midchain) { adj0->sub_type.midchain.fixup_func (vm, adj0, p0); } "若adj的VNET_REWRITE_HAS_FEATURES被置位,则跳转到feature节点" if (PREDICT_FALSE (adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES)) vnet_feature_arc_start (lm->output_feature_arc_index, tx_sw_if_index0, &next0, p0); } ...... }