网站域名注册价格,电子工程网校,怎样创建个人销售网站,济宁做网站公司找融合遍历feature_main主结构的next_arc单向链表#xff0c;按照顺序为每个ARC注册结构分配索引#xff08;feature_arc_index#xff09;#xff0c;如果注册ARC的时候为成员arc_index_ptr附了值#xff0c;将ARC索引写入此值。
将arc_name作为key#xff0c;areg注册结构为…遍历feature_main主结构的next_arc单向链表按照顺序为每个ARC注册结构分配索引feature_arc_index如果注册ARC的时候为成员arc_index_ptr附了值将ARC索引写入此值。
将arc_name作为keyareg注册结构为value写入arc_index_by_name的哈希中方便之后查找。计算ARC中开始节点的数量递增ARC索引遍历下一个ARC注册结构。
vnet_feature_init (vlib_main_t * vm)
{vnet_feature_main_t *fm feature_main;vnet_feature_registration_t *freg;vnet_feature_arc_registration_t *areg;vnet_feature_constraint_registration_t *creg;u32 arc_index 0;fm-arc_index_by_name hash_create_string (0, sizeof (uword));areg fm-next_arc;while (areg) {char *s;int i 0;areg-feature_arc_index arc_index;if (areg-arc_index_ptr)*areg-arc_index_ptr arc_index;hash_set_mem (fm-arc_index_by_name, areg-arc_name, pointer_to_uword (areg));while ((s areg-start_nodes[i]))i;areg-n_start_nodes i;areg areg-next;arc_index;}按照最大的ARC索引值分配以下的向量。 vec_validate (fm-next_feature_by_arc, arc_index - 1);vec_validate (fm-feature_nodes, arc_index - 1);vec_validate (fm-feature_config_mains, arc_index - 1);vec_validate (fm-next_feature_by_name, arc_index - 1);vec_validate (fm-sw_if_index_has_features, arc_index - 1);vec_validate (fm-feature_count_by_sw_if_index, arc_index - 1);vec_validate (fm-next_constraint_by_arc, arc_index - 1);遍历全局features单向链表next_feature根据feature中的ARC名称在哈希arc_index_by_name中找到ARC注册结构进而找到ARC的feature链表头next_feature_by_arc[arc_index]为索引arc_index的ARC创建feature链表。
遍历结束之后为每个ARC创建了feature链表next_feature_by_arc[arc_index]。 freg fm-next_feature;while (freg) {vnet_feature_registration_t *next;uword *p hash_get_mem (fm-arc_index_by_name, freg-arc_name);if (p 0) {clib_warning (Unknown feature arc %s, freg-arc_name);os_exit (1);}areg uword_to_pointer (p[0], vnet_feature_arc_registration_t *);arc_index areg-feature_arc_index;next freg-next;freg-next_in_arc fm-next_feature_by_arc[arc_index];fm-next_feature_by_arc[arc_index] freg;freg next;}遍历全局的next_constraint链表最终为每个ARC创建单独的constraint链表链表头部为next_constraint_by_arc[arc_index]最后添加的位于链表的头部。 /* Move bulk constraints to the constraint by arc lists */creg fm-next_constraint;while (creg) {vnet_feature_constraint_registration_t *next;uword *p hash_get_mem (fm-arc_index_by_name, creg-arc_name);if (p 0) {clib_warning (Unknown feature arc %s, creg-arc_name);os_exit (1);}areg uword_to_pointer (p[0], vnet_feature_arc_registration_t *);arc_index areg-feature_arc_index;next creg-next;creg-next_in_arc fm-next_constraint_by_arc[arc_index];fm-next_constraint_by_arc[arc_index] creg;creg next;}最后再次遍历next_arc链表对于每个ARC集合检测其中的features是否满足定义的次序如果last_in_arc不等于排序之后的最后一个feature表明发生错误。 areg fm-next_arc;while (areg){vnet_feature_config_main_t *cm;vnet_config_main_t *vcm;char **features_in_order, *last_feature;arc_index areg-feature_arc_index;cm fm-feature_config_mains[arc_index];vcm cm-config_main;if ((error vnet_feature_arc_init (vm, vcm, areg-start_nodes, areg-n_start_nodes,areg-last_in_arc, fm-next_feature_by_arc[arc_index],fm-next_constraint_by_arc[arc_index], fm-feature_nodes[arc_index]))) {os_exit (1);}features_in_order fm-feature_nodes[arc_index];/* If specified, verify that the last node in the arc is actually last */if (areg-last_in_arc vec_len (features_in_order) 0){last_feature features_in_order[vec_len (features_in_order) - 1];if (strncmp (areg-last_in_arc, last_feature, strlen (areg-last_in_arc)))clib_warning(WARNING: %s arc: last node is %s, but expected %s!,areg-arc_name, last_feature, areg-last_in_arc);}为每个ARC的所有feature初始化next_feature_by_name[arc_index]哈希结构之后可通过feature名称找到feature注册结构。 fm-next_feature_by_name[arc_index] hash_create_string (0, sizeof (uword));freg fm-next_feature_by_arc[arc_index];while (freg) {hash_set_mem (fm-next_feature_by_name[arc_index], freg-node_name, pointer_to_uword (freg));freg freg-next_in_arc;}areg areg-next;}显示ARC
命令show features [verbose] 用于显示VPP系统中的注册的ARCs以及每个ARC包含的features集合。所有的信息都保存在全局结构feature_main中其成员next_arc为保存了ARC注册信息的单向链表以下函数遍历此链表。
static clib_error_t *
show_features_command_fn (vlib_main_t * vm,unformat_input_t * input, vlib_cli_command_t * cmd)
{vnet_feature_main_t *fm feature_main;vnet_feature_arc_registration_t *areg;vnet_feature_registration_t *freg;vnet_feature_registration_t *feature_regs 0;areg fm-next_arc;while (areg) {if (verbose)vlib_cli_output (vm, [%2d] %s:, areg-feature_arc_index, areg-arc_name);elsevlib_cli_output (vm, %s:, areg-arc_name);ARC中的features链表保存在feature_main的成员next_feature_by_arc中单向链表next_in_arc指向下一个feature注册结构。遍历过程中将所有的feature注册结构保存到feature_regs向量中按照feature索引值由小到大进行排序之后输出feature索引和名称信息。 freg fm-next_feature_by_arc[areg-feature_arc_index];while (freg) {vec_add1 (feature_regs, freg[0]);freg freg-next_in_arc;}vec_sort_with_function (feature_regs, feature_cmp);vec_foreach (freg, feature_regs) {if (verbose)vlib_cli_output (vm, [%2d]: %s\n, freg-feature_index, freg-node_name);elsevlib_cli_output (vm, %s\n, freg-node_name);}vec_reset_length (feature_regs);areg areg-next;}如下显示
vpp# show features verbose
Available feature paths
[ 0] nsh-eth-output:[ 0]: interface-output[ 1]: error-drop
[ 1] arp:[ 0]: vrrp4-arp-input[ 1]: linux-cp-arp-phy[ 2]: linux-cp-arp-host[ 3]: arping-input[ 4]: arp-reply[ 5]: arp-proxy[ 6]: arp-disabled[ 7]: error-drop
[ 2] nsh-output:[ 0]: error-drop
[ 3] mpls-input:[ 0]: vlan-mpls-qos-record[ 1]: mpls-qos-record[ 2]: mpls-not-enabled[ 3]: mpls-lookup接口feature配置
函数vnet_interface_features_show显示在指定接口上激活的feature集合这里也是由遍历feature_main结构的成员next_arc开头的单链表开始。
void
vnet_interface_features_show (vlib_main_t * vm, u32 sw_if_index, int verbose)
{vnet_feature_main_t *fm feature_main;vnet_feature_config_main_t *cm fm-feature_config_mains;vnet_feature_arc_registration_t *areg;vnet_config_main_t *vcm;vnet_config_t *cfg;vnet_config_feature_t *feat;vlib_node_t *n;vlib_cli_output (vm, Feature paths configured on %U...,format_vnet_sw_if_index_name, vnet_get_main (), sw_if_index);areg fm-next_arc;根据ARC索引找到对应的配置结构vcm如果接口sw_if_index完全没有激活此ARC显示none configured。否则检查此接口在此ARC上激活了哪些features。 while (areg) {feature_arc areg-feature_arc_index;vcm (cm[feature_arc].config_main);vlib_cli_output (vm, \n%s:, areg-arc_name);areg areg-next;if (!vnet_have_features (feature_arc, sw_if_index)) {vlib_cli_output (vm, none configured);continue;}先根据sw_if_index接口索引在向量config_index_by_sw_if_index中找到ARC配置索引(current_config_index)再根据配置索引在向量config_pool_index_by_user_index中找到pool索引最终在config_pool中取得相应配置cfg。
遍历cfg结构向量成员features根据其中的节点索引node_index找到feature的节点结构。打印输出feature索引和节点名称。 current_config_index vec_elt (cm[feature_arc].config_index_by_sw_if_index, sw_if_index);cfg_index vec_elt (vcm-config_pool_index_by_user_index, current_config_index);cfg pool_elt_at_index (vcm-config_pool, cfg_index);for (i 0; i vec_len (cfg-features); i) {feat cfg-features i;node_index feat-node_index;n vlib_get_node (vm, node_index);if (verbose)vlib_cli_output (vm, [%2d] %v, feat-feature_index, n-name);elsevlib_cli_output (vm, %v, n-name);}ARC的最后一个节点索引保存在end_node_indices_by_user_index的current_config_index索引位置vlib_get_node根据最后节点索引找到节点结构打印其名称。 if (verbose) {n vlib_get_node (vm, vcm-end_node_indices_by_user_index[current_config_index]);vlib_cli_output (vm, [end] %v, n-name);}如下显示接口features配置
vpp# show interface features eth0
Feature paths configured on eth0...nsh-eth-output:none configuredarp:linux-cp-arp-phyfeature开启关闭
feature开启关闭操作需要指定ARC和Feature的名称以及要开启的接口索引。如下函数根据ARC和Feature名称找到ARC索引和feature索引。
int
vnet_feature_enable_disable (const char *arc_name, const char *node_name,u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
{ u32 feature_index;u8 arc_index;arc_index vnet_get_feature_arc_index (arc_name); if (arc_index (u8) ~ 0)return VNET_API_ERROR_INVALID_VALUE;feature_index vnet_get_feature_index (arc_index, node_name);return vnet_feature_enable_disable_with_index (arc_index, feature_index,sw_if_index, enable_disable, feature_config, n_feature_config_bytes); 在feature_main结构中根据ARC名称在哈希arc_index_by_name找到ARC的注册结构其中保存着ARC的索引feature_arc_index。
vnet_get_feature_arc_index (const char *s)
{vnet_feature_main_t *fm feature_main;vnet_feature_arc_registration_t *reg;uword *p;p hash_get_mem (fm-arc_index_by_name, s);if (p 0)return ~0;reg uword_to_pointer (p[0], vnet_feature_arc_registration_t *);return reg-feature_arc_index;在feature_main主结构中根据ARC索引和feature名称在哈希next_feature_by_name[arc]中找到feature的注册结构其中保存着feature的索引feature_index。
vnet_get_feature_index (u8 arc, const char *s)
{vnet_feature_main_t *fm feature_main;vnet_feature_registration_t *reg;uword *p;if (s 0) return ~0;p hash_get_mem (fm-next_feature_by_name[arc], s);if (p 0)return ~0;reg uword_to_pointer (p[0], vnet_feature_registration_t *);return reg-feature_index;根据ARC索引找到对应配置结构cm再根据接口索引sw_if_index在config_index_by_sw_if_index找到配置池索引ci检查一下接口当前开启的feature数量如果为零并且当前为disable操作直接返回不需要disable了。
vnet_feature_enable_disable_with_index (u8 arc_index, u32 feature_index,u32 sw_if_index, int enable_disable,void *feature_config, u32 n_feature_config_bytes)
{vnet_feature_main_t *fm feature_main;vnet_feature_config_main_t *cm;cm fm-feature_config_mains[arc_index];vec_validate_init_empty (cm-config_index_by_sw_if_index, sw_if_index, ~0);ci cm-config_index_by_sw_if_index[sw_if_index];vec_validate (fm-feature_count_by_sw_if_index[arc_index], sw_if_index);feature_count fm-feature_count_by_sw_if_index[arc_index][sw_if_index];if (!enable_disable feature_count 1)return 0;调用函数vnet_config_add_feature/vnet_config_del_feature添加或者删除feature。将返回的配置池索引ci保存到接口对应的config_index_by_sw_if_index中。递增接口的feature数量。
ARC对应的向量sw_if_index_has_features[arc_index]中保存接口是否开启有feature。 ci (enable_disable? vnet_config_add_feature: vnet_config_del_feature)(vlib_get_main (), cm-config_main, ci, feature_index, feature_config, n_feature_config_bytes);if (ci ~0)return 0;cm-config_index_by_sw_if_index[sw_if_index] ci;/* update feature count */enable_disable (enable_disable 0);feature_count enable_disable ? 1 : -1;ASSERT (feature_count 0);fm-sw_if_index_has_features[arc_index] clib_bitmap_set (fm-sw_if_index_has_features[arc_index], sw_if_index, (feature_count 0));fm-feature_count_by_sw_if_index[arc_index][sw_if_index] feature_count;vnet_feature_reg_invoke (sw_if_index, arc_index, (feature_count 0));如下增加feature函数如果config_string_heap_index为有效值据此获得之前添加的vnet_config_t结构old这里将p进行了减一操作之后会再次看着这个值进行了加一保存将其中的features复制一份。
vnet_config_add_feature (vlib_main_t * vm,vnet_config_main_t * cm, u32 config_string_heap_index,u32 feature_index, void *feature_config, u32 n_feature_config_bytes)
{vnet_config_t *old, *new;vnet_config_feature_t *new_features, *f;u32 n_feature_config_u32s, end_node_index;u32 node_index vec_elt (cm-node_index_by_feature_index, feature_index);if (config_string_heap_index ~0) {old 0;new_features 0;end_node_index cm-default_end_node_index;} else {u32 *p vnet_get_config_heap (cm, config_string_heap_index);old pool_elt_at_index (cm-config_pool, p[-1]);new_features old-features;end_node_index cm-end_node_indices_by_user_index[config_string_heap_index];if (new_features)new_features duplicate_feature_vector (new_features);}分配一个新的feature结构vnet_config_feature_t将要添加的feature索引和节点索引赋值到新feature结构中。如果指定了配置字节保存到新feature结构中。 vec_add2 (new_features, f, 1);f-feature_index feature_index;f-node_index node_index;if (n_feature_config_bytes) {n_feature_config_u32s round_pow2 (n_feature_config_bytes, sizeof (f-feature_config[0])) / sizeof (f-feature_config[0]);vec_validate (f-feature_config, n_feature_config_u32s - 1);clib_memcpy_fast (f-feature_config, feature_config, n_feature_config_bytes);}如果new_features向量元素大于1进行排序。释放旧的vnet_config结构。函数find_config_with_features分配一个新的vnet_config结构new。 /* Sort (prioritize) features. */if (vec_len (new_features) 1)vec_sort_with_function (new_features, feature_cmp);if (old)remove_reference (cm, old);new find_config_with_features (vm, cm, new_features, end_node_index);new-reference_count 1;分配config_pool_index_by_user_index索引将配置池索引进行保存。返回配置池索引值进行了加一操作。 /* User gets pointer to config string first element* (which defines the pool index this config string comes from).*/vec_validate (cm-config_pool_index_by_user_index,new-config_string_heap_index 1);cm-config_pool_index_by_user_index[new-config_string_heap_index 1] new - cm-config_pool;return new-config_string_heap_index 1;