初始化

初始化有两步,先使用宏初始化内存然后再使用函数添加

1.使用宏

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,/*notbeforeanyotherfeatures*/};

把这些node都挂在对应的构造函数上,在初始化的时候就会调用。然后初始化相应的配置,也就是vnet_feature_arc_init 这个函数,会根据之前的配置,将各feature的先后关系排列好。此时只是排列好顺序,并未插入feature_arc中,也就是不会被调用到。

2.使用函数add/del

调用vnet_feature_enable_disable即可,此时才是将要用到的feature真正的插入feature_arc中。

具体的实现是 vnet_config_add_feature() vnet_config_del_feature() 这两个个函数跟之前版本的feature没有什么区别了。

使用

按照老版本的思想,feature至少分为两种,接口的feature和其他的feature

节点feature的使用

在node的处理函数里调用vnet_feature_arc_start就好了。
通过命令show features可以看到成功加载的feature。

接口feature的使用

接口的feature与之前的版本不一样,是移至ip4-rewrite中进行接口feature的跳转。
通过命令show interface features xxx,可以看到接口的feature。

初始化会有一点变化,说一下区别

1.初始化

代码里并没有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,};2.使用

在函数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);}......}