1、feature arc及feature注册
vnet\ipIp4_forward.c feature arc及feature的main函数启动前的注册宏
- feature arc注册
VNET_FEATURE_ARC_INIT将注册feature arc,主要初始化feature类的名称、起始及结束node名字及arc_index的指针。会
以链表形式挂接到全局变量extern vnet_feature_main_t feature_main 的next_arc上。
VNET_FEATURE_ARC_INIT (ip4_unicast, static) =
{
.arc_name = "ip4-unicast",
.start_nodes = VNET_FEATURES ("ip4-input", "ip4-input-no-checksum"),
.last_in_arc = "ip4-lookup",
.arc_index_ptr = &ip4_main.lookup_main.ucast_feature_arc_index,
};
- 2、feature注册
VNET_FEATURE_INIT完成feature的注册,主要初始化arc名称,node节点名称,及运行当前feature node的前面或后面的feature node。
VNET_FEATURE_INIT (ip4_flow_classify, static) =
{
.arc_name = "ip4-unicast",
.node_name = "ip4-flow-classify",
.runs_before = VNET_FEATURES ("ip4-inacl"),
};
2、feature初始化及添加删除
- 1、feature初始化
是在node节点注册的后面,是由VLIB_INIT_FUNCTION (vnet_feature_init)宏注册到初始化函数中,在mian loop前被调用。 - 2、以ip4-unicast为例,vnet_feature_arc_init函数实现流程。
typedef struct
{
/** feature arc configuration list
*main函数启动前VNET_FEATURE_ARC_INIT宏中注册的feature arc 链表形式保存下来*/
vnet_feature_arc_registration_t *next_arc;
/*创建<key:arc_name, vlaue:feature_arc指针及在next_arc链表中的节点地址>的hash表*/
uword **arc_index_by_name;
/** feature path configuration lists
*main函数启动前 VNET_FEATURE_INIT宏将feature注册到这个链表中*/
vnet_feature_registration_t *next_feature;
/*next_feature_by_arc[arc_index] 将同一类的feature以链表形式串到一起*/
vnet_feature_registration_t **next_feature_by_arc;
/*vector结构:二维,一维是feature arc的索引,二维是hash头
next_feature_by_name[arc_index] : <key:feature结构中node 名称;
value: vnet_feature_registration_t 的指针。 */
uword **next_feature_by_name;
/** feature arc类对应一个 vnet_feature_config_main_t。
*feature_config_mains[arc_index]:保存feature类的配置属性*/
vnet_feature_config_main_t *feature_config_mains;
/** Save partial order results for show command
*feature_nodes[x], X:feature arc 的索引
保存feature 节点,保存节点node的名称,顺序存储*/
char ***feature_nodes;
/** bitmap of interfaces which have driver rx features configured */
uword **sw_if_index_has_features;
/** feature reference counts by interface
*feature_count_by_sw_if_index[arc_index][sw_if_index]:下面feature的计数*/
i16 **feature_count_by_sw_if_index;
/** Feature arc index for device-input */
u8 device_input_feature_arc_index;
/** convenience */
vlib_main_t *vlib_main;
vnet_main_t *vnet_main;
} vnet_feature_main_t;
3、feature 添加及删除流程
- 1、相关结构体及相关字段介绍
- 2、相关函数介绍
4、node节点处理如果获取下一个slot号
b0->feature_arc_index存储的cm->config_string_heap的偏移量,里面存储的就是当前节点的下一个nodeslot号。
在通过下面函数偏移了confi_index的数值。
always_inline void *
vnet_get_config_data (vnet_config_main_t * cm,
u32 * config_index, u32 * next_index, u32 n_data_bytes)
{
u32 i, n, *d;
i = *config_index;
d = heap_elt_at_index (cm->config_string_heap, i);
n = round_pow2 (n_data_bytes, sizeof (d[0])) / sizeof (d[0]);
/* Last 32 bits are next index. 本feature吓一跳的slot号*/
*next_index = d[n];
/* Advance config index to next config.获取下一个slot位置。b0->feature_arc_index; */
*config_index = (i + n + 1);
/* Return config data to user for this feature. */
return (void *) d;
}
static_always_inline void *
vnet_feature_next_with_data (u32 sw_if_index, u32 * next0,
vlib_buffer_t * b0, u32 n_data_bytes)
{
vnet_feature_main_t *fm = &feature_main;
u8 arc = b0->feature_arc_index;
vnet_feature_config_main_t *cm = &fm->feature_config_mains[arc];
return vnet_get_config_data (&cm->config_main,
&b0->current_config_index, next0,
n_data_bytes);
}