diff options
40 files changed, 481 insertions, 1613 deletions
diff --git a/plugins/flowperpkt-plugin/flowperpkt/flowperpkt.c b/plugins/flowperpkt-plugin/flowperpkt/flowperpkt.c index ac508582669..dbdb189865d 100644 --- a/plugins/flowperpkt-plugin/flowperpkt/flowperpkt.c +++ b/plugins/flowperpkt-plugin/flowperpkt/flowperpkt.c @@ -59,10 +59,10 @@ flowperpkt_main_t flowperpkt_main; /* Define the per-interface configurable feature */ /* *INDENT-OFF* */ -VNET_IP4_TX_FEATURE_INIT (flow_perpacket, static) = { +VNET_FEATURE_INIT (flow_perpacket, static) = { + .arc_name = "ip4-output", .node_name = "flowperpkt", - .runs_before = (char *[]){"interface-output", 0}, - .feature_index = &flowperpkt_main.ip4_tx_feature_index, + .runs_before = VNET_FEATURES ("interface-output"), }; /* *INDENT-ON* */ @@ -249,11 +249,6 @@ flowperpkt_data_callback (flow_report_main_t * frm, static int flowperpkt_tx_interface_add_del_feature (flowperpkt_main_t * fm, u32 sw_if_index, int is_add) { - u32 ci; - ip4_main_t *im = &ip4_main; - ip_lookup_main_t *lm = &im->lookup_main; - vnet_feature_config_main_t *cm = &lm->feature_config_mains[VNET_IP_TX_FEAT]; - u32 feature_index; flow_report_main_t *frm = &flow_report_main; vnet_flow_report_add_del_args_t _a, *a = &_a; int rv; @@ -276,18 +271,9 @@ static int flowperpkt_tx_interface_add_del_feature } } - feature_index = fm->ip4_tx_feature_index; + vnet_feature_enable_disable ("ip4-output", "flowperpkt", sw_if_index, + is_add, 0, 0); - ci = cm->config_index_by_sw_if_index[sw_if_index]; - ci = (is_add - ? vnet_config_add_feature - : vnet_config_del_feature) - (fm->vlib_main, &cm->config_main, - ci, feature_index, 0 /* config struct */ , - 0 /* sizeof config struct */ ); - cm->config_index_by_sw_if_index[sw_if_index] = ci; - - vnet_config_update_tx_feature_count (lm, cm, sw_if_index, is_add); return 0; } diff --git a/plugins/flowperpkt-plugin/flowperpkt/flowperpkt.h b/plugins/flowperpkt-plugin/flowperpkt/flowperpkt.h index 5ddba9ce1da..31e685eb68d 100644 --- a/plugins/flowperpkt-plugin/flowperpkt/flowperpkt.h +++ b/plugins/flowperpkt-plugin/flowperpkt/flowperpkt.h @@ -35,9 +35,6 @@ typedef struct /** API message ID base */ u16 msg_id_base; - /** ip4 feature index */ - u32 ip4_tx_feature_index; - /** Has the report been created? */ int report_created; diff --git a/plugins/flowperpkt-plugin/flowperpkt/node.c b/plugins/flowperpkt-plugin/flowperpkt/node.c index b01f2be3a05..86da3a1cf59 100644 --- a/plugins/flowperpkt-plugin/flowperpkt/node.c +++ b/plugins/flowperpkt-plugin/flowperpkt/node.c @@ -284,9 +284,6 @@ flowperpkt_node_fn (vlib_main_t * vm, { u32 n_left_from, *from, *to_next; flowperpkt_next_t next_index; - ip4_main_t *im = &ip4_main; - ip_lookup_main_t *lm = &im->lookup_main; - vnet_feature_config_main_t *cm = &lm->feature_config_mains[VNET_IP_TX_FEAT]; flowperpkt_main_t *fm = &flowperpkt_main; u64 now; @@ -337,14 +334,10 @@ flowperpkt_node_fn (vlib_main_t * vm, b0 = vlib_get_buffer (vm, bi0); b1 = vlib_get_buffer (vm, bi1); - - vnet_get_config_data (&cm->config_main, - &b0->current_config_index, - &next0, 0 /* sizeof config data */ ); - - vnet_get_config_data (&cm->config_main, - &b1->current_config_index, - &next1, 0 /* sizeof config data */ ); + vnet_feature_next (vnet_buffer (b0)->sw_if_index[VLIB_TX], + &next0, b0); + vnet_feature_next (vnet_buffer (b1)->sw_if_index[VLIB_TX], + &next1, b1); ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) + vnet_buffer (b0)->ip.save_rewrite_length); @@ -413,9 +406,8 @@ flowperpkt_node_fn (vlib_main_t * vm, b0 = vlib_get_buffer (vm, bi0); - vnet_get_config_data (&cm->config_main, - &b0->current_config_index, - &next0, 0 /* sizeof config data */ ); + vnet_feature_next (vnet_buffer (b0)->sw_if_index[VLIB_TX], + &next0, b0); ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) + vnet_buffer (b0)->ip.save_rewrite_length); diff --git a/plugins/ila-plugin/ila/ila.c b/plugins/ila-plugin/ila/ila.c index 61ce0f7bacd..336f4cf560c 100644 --- a/plugins/ila-plugin/ila/ila.c +++ b/plugins/ila-plugin/ila/ila.c @@ -425,9 +425,6 @@ static uword ila_sir2ila (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - ip6_main_t *im = &ip6_main; - ip_lookup_main_t *lm = &im->lookup_main; - vnet_feature_config_main_t *cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; u32 n_left_from, *from, next_index, *to_next, n_left_to_next; ila_main_t *ilm = &ila_main; @@ -519,11 +516,8 @@ ila_sir2ila (vlib_main_t * vm, ip61->dst_address.as_u64[0] = ila_address1->as_u64[0]; ip61->dst_address.as_u64[1] = ila_address1->as_u64[1]; - vnet_get_config_data (&cm->config_main, - &p0->current_config_index, &next0, 0); - - vnet_get_config_data (&cm->config_main, - &p1->current_config_index, &next1, 0); + vnet_feature_next (vnet_buffer (p0)->sw_if_index[VLIB_RX], &next0, p0); + vnet_feature_next (vnet_buffer (p1)->sw_if_index[VLIB_RX], &next1, p1); vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next, n_left_to_next, pi0, pi1, next0, @@ -574,8 +568,7 @@ ila_sir2ila (vlib_main_t * vm, ip60->dst_address.as_u64[0] = ila_address0->as_u64[0]; ip60->dst_address.as_u64[1] = ila_address0->as_u64[1]; - vnet_get_config_data (&cm->config_main, - &p0->current_config_index, &next0, 0); + vnet_feature_next (vnet_buffer (p0)->sw_if_index[VLIB_RX], &next0, p0); vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, pi0, next0); @@ -603,11 +596,11 @@ VLIB_REGISTER_NODE (ila_sir2ila_node, static) = /** *INDENT-ON* */ /** *INDENT-OFF* */ -VNET_IP6_UNICAST_FEATURE_INIT (ila_sir2ila, static) = +VNET_FEATURE_INIT (ila_sir2ila, static) = { + .arc_name = "ip6-unicast", .node_name = "sir-to-ila", - .runs_before = ORDER_CONSTRAINTS{"ip6-lookup", 0}, - .feature_index = &ila_main.ila_sir2ila_feature_index, + .runs_before = VNET_FEATURES ("ip6-lookup"), }; /** *INDENT-ON* */ @@ -823,24 +816,8 @@ ila_add_del_entry (ila_add_del_entry_args_t * args) int ila_interface (u32 sw_if_index, u8 disable) { - vlib_main_t *vm = vlib_get_main (); - ila_main_t *ilm = &ila_main; - ip6_main_t *im = &ip6_main; - ip_lookup_main_t *lm = &im->lookup_main; - vnet_feature_config_main_t *cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; - vnet_config_main_t *vcm = &cm->config_main; - u32 ci, feature_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]; - feature_index = ilm->ila_sir2ila_feature_index; - - ci = ((disable) ? vnet_config_del_feature : vnet_config_add_feature) - (vm, vcm, ci, feature_index, - /* config data */ 0, - /* # bytes of config data */ 0); - - cm->config_index_by_sw_if_index[sw_if_index] = ci; + vnet_feature_enable_disable ("ip4-unicast", "sir-to-ila", sw_if_index, + !disable, 0, 0); return 0; } diff --git a/plugins/ila-plugin/ila/ila.h b/plugins/ila-plugin/ila/ila.h index 657511f00f2..26620983823 100644 --- a/plugins/ila-plugin/ila/ila.h +++ b/plugins/ila-plugin/ila/ila.h @@ -94,8 +94,6 @@ typedef struct { u64 lookup_table_size; clib_bihash_24_8_t id_to_entry_table; - u32 ila_sir2ila_feature_index; - u32 ip6_lookup_next_index; } ila_main_t; diff --git a/plugins/snat-plugin/snat/out2in.c b/plugins/snat-plugin/snat/out2in.c index 190350ada2b..35edcc5f7b3 100644 --- a/plugins/snat-plugin/snat/out2in.c +++ b/plugins/snat-plugin/snat/out2in.c @@ -284,8 +284,6 @@ snat_out2in_node_fn (vlib_main_t * vm, snat_out2in_next_t next_index; u32 pkts_processed = 0; snat_main_t * sm = &snat_main; - ip_lookup_main_t * lm = sm->ip4_lookup_main; - vnet_feature_config_main_t * cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; f64 now = vlib_time_now (vm); from = vlib_frame_vector_args (frame); @@ -355,10 +353,7 @@ snat_out2in_node_fn (vlib_main_t * vm, rx_fib_index0 = vec_elt (sm->ip4_main->fib_index_by_sw_if_index, sw_if_index0); - vnet_get_config_data (&cm->config_main, - &b0->current_config_index, - &next0, - 0 /* sizeof config data */); + vnet_feature_next (sw_if_index0, &next0, b0); proto0 = ~0; proto0 = (ip0->protocol == IP_PROTOCOL_UDP) ? SNAT_PROTOCOL_UDP : proto0; @@ -474,10 +469,8 @@ snat_out2in_node_fn (vlib_main_t * vm, rx_fib_index1 = vec_elt (sm->ip4_main->fib_index_by_sw_if_index, sw_if_index1); - vnet_get_config_data (&cm->config_main, - &b1->current_config_index, - &next1, - 0 /* sizeof config data */); + vnet_feature_next (sw_if_index1, &next1, b1); + proto1 = ~0; proto1 = (ip1->protocol == IP_PROTOCOL_UDP) ? SNAT_PROTOCOL_UDP : proto1; @@ -628,10 +621,8 @@ snat_out2in_node_fn (vlib_main_t * vm, rx_fib_index0 = vec_elt (sm->ip4_main->fib_index_by_sw_if_index, sw_if_index0); - vnet_get_config_data (&cm->config_main, - &b0->current_config_index, - &next0, - 0 /* sizeof config data */); + vnet_feature_next (sw_if_index0, &next0, b0); + proto0 = ~0; proto0 = (ip0->protocol == IP_PROTOCOL_UDP) ? SNAT_PROTOCOL_UDP : proto0; @@ -853,8 +844,6 @@ snat_out2in_fast_node_fn (vlib_main_t * vm, snat_out2in_next_t next_index; u32 pkts_processed = 0; snat_main_t * sm = &snat_main; - ip_lookup_main_t * lm = sm->ip4_lookup_main; - vnet_feature_config_main_t * cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; @@ -902,10 +891,8 @@ snat_out2in_fast_node_fn (vlib_main_t * vm, sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX]; rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index(sw_if_index0); - vnet_get_config_data (&cm->config_main, - &b0->current_config_index, - &next0, - 0 /* sizeof config data */); + vnet_feature_next (sw_if_index0, &next0, b0); + proto0 = ~0; proto0 = (ip0->protocol == IP_PROTOCOL_UDP) ? SNAT_PROTOCOL_UDP : proto0; diff --git a/plugins/snat-plugin/snat/snat.c b/plugins/snat-plugin/snat/snat.c index 0b972110f19..66c03817ca0 100644 --- a/plugins/snat-plugin/snat/snat.c +++ b/plugins/snat-plugin/snat/snat.c @@ -93,25 +93,25 @@ do { \ /* Hook up input features */ -VNET_IP4_UNICAST_FEATURE_INIT (ip4_snat_in2out, static) = { +VNET_FEATURE_INIT (ip4_snat_in2out, static) = { + .arc_name = "ip4-unicast", .node_name = "snat-in2out", - .runs_before = (char *[]){"snat-out2in", 0}, - .feature_index = &snat_main.rx_feature_in2out, + .runs_before = VNET_FEATURES ("snat-out2in"), }; -VNET_IP4_UNICAST_FEATURE_INIT (ip4_snat_out2in, static) = { +VNET_FEATURE_INIT (ip4_snat_out2in, static) = { + .arc_name = "ip4-unicast", .node_name = "snat-out2in", - .runs_before = (char *[]){"ip4-lookup", 0}, - .feature_index = &snat_main.rx_feature_out2in, + .runs_before = VNET_FEATURES ("ip4-lookup"), }; -VNET_IP4_UNICAST_FEATURE_INIT (ip4_snat_in2out_fast, static) = { +VNET_FEATURE_INIT (ip4_snat_in2out_fast, static) = { + .arc_name = "ip4-unicast", .node_name = "snat-in2out-fast", - .runs_before = (char *[]){"snat-out2in-fast", 0}, - .feature_index = &snat_main.rx_feature_in2out_fast, + .runs_before = VNET_FEATURES ("snat-out2in-fast"), }; -VNET_IP4_UNICAST_FEATURE_INIT (ip4_snat_out2in_fast, static) = { +VNET_FEATURE_INIT (ip4_snat_out2in_fast, static) = { + .arc_name = "ip4-unicast", .node_name = "snat-out2in-fast", - .runs_before = (char *[]){"ip4-lookup", 0}, - .feature_index = &snat_main.rx_feature_out2in_fast, + .runs_before = VNET_FEATURES ("ip4-lookup"), }; @@ -540,29 +540,15 @@ static int snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del) { snat_main_t *sm = &snat_main; snat_interface_t *i; - u32 ci; - ip4_main_t * im = &ip4_main; - ip_lookup_main_t * lm = &im->lookup_main; - vnet_feature_config_main_t * rx_cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; - u32 feature_index; + const char * feature_name; if (sm->static_mapping_only && !(sm->static_mapping_connection_tracking)) - feature_index = is_inside ? sm->rx_feature_in2out_fast - : sm->rx_feature_out2in_fast; + feature_name = is_inside ? "snat-in2out-fast" : "snat-out2in-fast"; else - feature_index = is_inside ? sm->rx_feature_in2out - : sm->rx_feature_out2in; - - ci = rx_cm->config_index_by_sw_if_index[sw_if_index]; - ci = (is_del - ? vnet_config_del_feature - : vnet_config_add_feature) - (sm->vlib_main, &rx_cm->config_main, - ci, - feature_index, - 0 /* config struct */, - 0 /* sizeof config struct*/); - rx_cm->config_index_by_sw_if_index[sw_if_index] = ci; + feature_name = is_inside ? "snat-in2out" : "snat-out2in"; + + vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, + !is_del, 0, 0); pool_foreach (i, sm->interfaces, ({ diff --git a/plugins/snat-plugin/snat/snat.h b/plugins/snat-plugin/snat/snat.h index 1469f60e59d..ca10b76adce 100644 --- a/plugins/snat-plugin/snat/snat.h +++ b/plugins/snat-plugin/snat/snat.h @@ -166,12 +166,6 @@ typedef struct { /* Randomize port allocation order */ u32 random_seed; - /* ip4 feature path indices */ - u32 rx_feature_in2out; - u32 rx_feature_out2in; - u32 rx_feature_in2out_fast; - u32 rx_feature_out2in_fast; - /* Config parameters */ u8 static_mapping_only; u8 static_mapping_connection_tracking; diff --git a/vnet/vnet/adj/adj_l2.c b/vnet/vnet/adj/adj_l2.c index c49ec77ec78..4d2dd7082f1 100644 --- a/vnet/vnet/adj/adj_l2.c +++ b/vnet/vnet/adj/adj_l2.c @@ -53,7 +53,7 @@ adj_l2_rewrite_inline (vlib_main_t * vm, u32 * from = vlib_frame_vector_args (frame); u32 n_left_from, n_left_to_next, * to_next, next_index; u32 cpu_index = os_get_cpu_number(); - vnet_feature_config_main_t * cm = ðernet_main.feature_config_mains[VNET_IP_TX_FEAT]; + ethernet_main_t * em = ðernet_main; n_left_from = frame->n_vectors; next_index = node->cached_next_index; @@ -67,7 +67,7 @@ adj_l2_rewrite_inline (vlib_main_t * vm, ip_adjacency_t * adj0; vlib_buffer_t * p0; char *h0; - u32 pi0, rw_len0, adj_index0, next0; + u32 pi0, rw_len0, adj_index0, next0 = 0; u32 tx_sw_if_index0; pi0 = to_next[0] = from[0]; @@ -121,12 +121,7 @@ adj_l2_rewrite_inline (vlib_main_t * vm, * Follow the feature ARC. this will result eventually in * the midchain-tx node */ - p0->current_config_index = vec_elt(cm->config_index_by_sw_if_index, - tx_sw_if_index0); - vnet_get_config_data (&cm->config_main, - &p0->current_config_index, - &next0, - /* # bytes of config data */ 0); + vnet_feature_arc_start(em->output_feature_arc_index, tx_sw_if_index0, &next0, p0); } else { diff --git a/vnet/vnet/adj/adj_midchain.c b/vnet/vnet/adj/adj_midchain.c index d40ea792152..92ea1ea9510 100644 --- a/vnet/vnet/adj/adj_midchain.c +++ b/vnet/vnet/adj/adj_midchain.c @@ -260,45 +260,53 @@ VLIB_REGISTER_NODE (adj_midchain_tx_no_count_node, static) = { }, }; -VNET_IP4_TX_FEATURE_INIT (adj_midchain_tx_ip4, static) = { +VNET_FEATURE_INIT (adj_midchain_tx_ip4, static) = { + .arc_name = "ip4-output", .node_name = "adj-midchain-tx", - .runs_before = ORDER_CONSTRAINTS {"interface-output", 0}, - .feature_index = &adj_midchain_tx_feature_node[VNET_LINK_IP4], + .runs_before = VNET_FEATURES ("interface-output"), + .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_IP4], }; -VNET_IP4_TX_FEATURE_INIT (adj_midchain_tx_no_count_ip4, static) = { +VNET_FEATURE_INIT (adj_midchain_tx_no_count_ip4, static) = { + .arc_name = "ip4-output", .node_name = "adj-midchain-tx-no-count", - .runs_before = ORDER_CONSTRAINTS {"interface-output", 0}, - .feature_index = &adj_midchain_tx_no_count_feature_node[VNET_LINK_IP4], + .runs_before = VNET_FEATURES ("interface-output"), + .feature_index_ptr = &adj_midchain_tx_no_count_feature_node[VNET_LINK_IP4], }; -VNET_IP6_TX_FEATURE_INIT (adj_midchain_tx_ip6, static) = { +VNET_FEATURE_INIT (adj_midchain_tx_ip6, static) = { + .arc_name = "ip6-output", .node_name = "adj-midchain-tx", - .runs_before = ORDER_CONSTRAINTS {"interface-output", 0}, - .feature_index = &adj_midchain_tx_feature_node[VNET_LINK_IP6], + .runs_before = VNET_FEATURES ("interface-output"), + .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_IP6], }; -VNET_IP6_TX_FEATURE_INIT (adj_midchain_tx_no_count_ip6, static) = { +VNET_FEATURE_INIT (adj_midchain_tx_no_count_ip6, static) = { + .arc_name = "ip6-output", .node_name = "adj-midchain-tx-no-count", - .runs_before = ORDER_CONSTRAINTS {"interface-output", 0}, - .feature_index = &adj_midchain_tx_no_count_feature_node[VNET_LINK_IP6], + .runs_before = VNET_FEATURES ("interface-output"), + .feature_index_ptr = &adj_midchain_tx_no_count_feature_node[VNET_LINK_IP6], }; -VNET_MPLS_TX_FEATURE_INIT (adj_midchain_tx_mpls, static) = { +VNET_FEATURE_INIT (adj_midchain_tx_mpls, static) = { + .arc_name = "mpls-output", .node_name = "adj-midchain-tx", - .runs_before = ORDER_CONSTRAINTS {"interface-output", 0}, - .feature_index = &adj_midchain_tx_feature_node[VNET_LINK_MPLS], + .runs_before = VNET_FEATURES ("interface-output"), + .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_MPLS], }; -VNET_MPLS_TX_FEATURE_INIT (adj_midchain_tx_no_count_mpls, static) = { +VNET_FEATURE_INIT (adj_midchain_tx_no_count_mpls, static) = { + .arc_name = "mpls-output", .node_name = "adj-midchain-tx-no-count", - .runs_before = ORDER_CONSTRAINTS {"interface-output", 0}, - .feature_index = &adj_midchain_tx_no_count_feature_node[VNET_LINK_MPLS], + .runs_before = VNET_FEATURES ("interface-output"), + .feature_index_ptr = &adj_midchain_tx_no_count_feature_node[VNET_LINK_MPLS], }; -VNET_ETHERNET_TX_FEATURE_INIT (adj_midchain_tx_ethernet, static) = { +VNET_FEATURE_INIT (adj_midchain_tx_ethernet, static) = { + .arc_name = "ethernet-output", .node_name = "adj-midchain-tx", - .runs_before = ORDER_CONSTRAINTS {"error-drop", 0}, - .feature_index = &adj_midchain_tx_feature_node[VNET_LINK_ETHERNET], + .runs_before = VNET_FEATURES ("error-drop"), + .feature_index_ptr = &adj_midchain_tx_feature_node[VNET_LINK_ETHERNET], }; -VNET_ETHERNET_TX_FEATURE_INIT (adj_midchain_tx_no_count_ethernet, static) = { +VNET_FEATURE_INIT (adj_midchain_tx_no_count_ethernet, static) = { + .arc_name = "ethernet-output", .node_name = "adj-midchain-tx-no-count", - .runs_before = ORDER_CONSTRAINTS {"error-drop", 0}, - .feature_index = &adj_midchain_tx_no_count_feature_node[VNET_LINK_ETHERNET], + .runs_before = VNET_FEATURES ("error-drop"), + .feature_index_ptr = &adj_midchain_tx_no_count_feature_node[VNET_LINK_ETHERNET], }; static inline u32 @@ -320,36 +328,30 @@ adj_get_midchain_node (vnet_link_t link) return (0); } -static vnet_feature_config_main_t * -adj_midchain_get_config_for_link_type (const ip_adjacency_t *adj) +static u8 +adj_midchain_get_feature_arc_index_for_link_type (const ip_adjacency_t *adj) { - vnet_feature_config_main_t *cm = NULL; - + u8 arc = (u8) ~0; switch (adj->ia_link) { case VNET_LINK_IP4: { - ip4_main_t * im = &ip4_main; - ip_lookup_main_t * lm = &im->lookup_main; - cm = &lm->feature_config_mains[VNET_IP_TX_FEAT]; + arc = ip4_main.lookup_main.output_feature_arc_index; break; } case VNET_LINK_IP6: { - ip6_main_t * im = &ip6_main; - ip_lookup_main_t * lm = &im->lookup_main; - cm = &lm->feature_config_mains[VNET_IP_TX_FEAT]; + arc = ip6_main.lookup_main.output_feature_arc_index; break; } case VNET_LINK_MPLS: { - mpls_main_t * mm = &mpls_main; - cm = &mm->feature_config_mains[VNET_IP_TX_FEAT]; + arc = mpls_main.output_feature_arc_index; break; } case VNET_LINK_ETHERNET: { - cm = ðernet_main.feature_config_mains[VNET_IP_TX_FEAT]; + arc = ethernet_main.output_feature_arc_index; break; } case VNET_LINK_ARP: @@ -357,7 +359,9 @@ adj_midchain_get_config_for_link_type (const ip_adjacency_t *adj) break; } - return (cm); + ASSERT (arc != (u8) ~0); + + return (arc); } /** @@ -373,10 +377,9 @@ adj_nbr_midchain_update_rewrite (adj_index_t adj_index, adj_midchain_flag_t flags, u8 *rewrite) { - vnet_config_main_t * vcm; - vnet_feature_config_main_t *cm; ip_adjacency_t *adj; - u32 ci; + u8 arc_index; + u32 feature_index; ASSERT(ADJ_INDEX_INVALID != adj_index); @@ -394,43 +397,18 @@ adj_nbr_midchain_update_rewrite (adj_index_t adj_index, adj->sub_type.midchain.fixup_func = fixup; - cm = adj_midchain_get_config_for_link_type(adj); - vcm = &(cm->config_main); - vec_validate_init_empty(cm->config_index_by_sw_if_index, - adj->rewrite_header.sw_if_index, ~0); - ci = cm->config_index_by_sw_if_index[adj->rewrite_header.sw_if_index]; - - /* - * Choose the adj tx function based on whether the client wants - * to count against the interface or not and insert the appropriate - * TX feature. - */ - if (flags & ADJ_MIDCHAIN_FLAG_NO_COUNT) - { - adj->sub_type.midchain.tx_function_node = - adj_midchain_tx_no_count_node.index; - - ci = vnet_config_add_feature( - vlib_get_main(), - vcm, ci, - adj_midchain_tx_no_count_feature_node[adj->ia_link], - /* config data */ 0, - /* # bytes of config data */ 0); - } - else - { - adj->sub_type.midchain.tx_function_node = - adj_midchain_tx_node.index; - ci = vnet_config_add_feature( - vlib_get_main(), - vcm, ci, - adj_midchain_tx_feature_node[adj->ia_link], - /* config data */ 0, - /* # bytes of config data */ 0); - } + arc_index = adj_midchain_get_feature_arc_index_for_link_type (adj); + feature_index = (flags & ADJ_MIDCHAIN_FLAG_NO_COUNT) ? + adj_midchain_tx_no_count_feature_node[adj->ia_link] : + adj_midchain_tx_feature_node[adj->ia_link]; - cm->config_index_by_sw_if_index[adj->rewrite_header.sw_if_index] = ci; + adj->sub_type.midchain.tx_function_node = (flags & ADJ_MIDCHAIN_FLAG_NO_COUNT) ? + adj_midchain_tx_no_count_node.index : + adj_midchain_tx_node.index; + vnet_feature_enable_disable_with_index (arc_index, feature_index, + adj->rewrite_header.sw_if_index, + 1 /* enable */, 0, 0); /* * stack the midchain on the drop so it's ready to forward in the adj-midchain-tx. diff --git a/vnet/vnet/classify/flow_classify.c b/vnet/vnet/classify/flow_classify.c index 527b13cb887..0a624204e34 100644 --- a/vnet/vnet/classify/flow_classify.c +++ b/vnet/vnet/classify/flow_classify.c @@ -21,30 +21,24 @@ vnet_flow_classify_feature_enable (vlib_main_t * vnm, flow_classify_table_id_t tid, int feature_enable) { - ip_lookup_main_t * lm; - vnet_feature_config_main_t * ifcm; - u32 ftype; - u32 ci; + vnet_feature_config_main_t *vfcm; + u8 arc; if (tid == FLOW_CLASSIFY_TABLE_IP4) - { - lm = &ip4_main.lookup_main; - ftype = ip4_main.ip4_unicast_rx_feature_flow_classify; - } + { + vnet_feature_enable_disable ("ip4-unicast", "ip4-flow-classify", + sw_if_index, feature_enable, 0, 0); + arc = vnet_get_feature_arc_index ("ip4-unicast"); + } else - { - lm = &ip6_main.lookup_main; - ftype = ip6_main.ip6_unicast_rx_feature_flow_classify; - } - - ifcm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; - - ci = ifcm->config_index_by_sw_if_index[sw_if_index]; - ci = (feature_enable ? vnet_config_add_feature : vnet_config_del_feature) - (vnm, &ifcm->config_main, ci, ftype, 0, 0); + { + vnet_feature_enable_disable ("ip6-unicast", "ip6-flow-classify", + sw_if_index, feature_enable, 0, 0); + arc = vnet_get_feature_arc_index ("ip6-unicast"); + } - ifcm->config_index_by_sw_if_index[sw_if_index] = ci; - fcm->vnet_config_main[tid] = &ifcm->config_main; + vfcm = vnet_get_feature_arc_config_main (arc); + fcm->vnet_config_main[tid] = &vfcm->config_main; } int vnet_set_flow_classify_intfc (vlib_main_t * vm, u32 sw_if_index, diff --git a/vnet/vnet/classify/input_acl.c b/vnet/vnet/classify/input_acl.c index ddb4332767a..c446f2d687c 100644 --- a/vnet/vnet/classify/input_acl.c +++ b/vnet/vnet/classify/input_acl.c @@ -33,34 +33,24 @@ vnet_inacl_ip_feature_enable (vlib_main_t * vnm, } else { /* IP[46] */ - ip_lookup_main_t * lm; - vnet_feature_config_main_t * ipcm; - u32 ftype; - u32 ci; + vnet_feature_config_main_t *fcm; + u8 arc; if (tid == INPUT_ACL_TABLE_IP4) - { - lm = &ip4_main.lookup_main; - ftype = ip4_main.ip4_unicast_rx_feature_check_access; - } + { + vnet_feature_enable_disable ("ip4-unicast", "ip4-inacl", + sw_if_index, feature_enable, 0, 0); + arc = vnet_get_feature_arc_index ("ip4-unicast"); + } else - { - lm = &ip6_main.lookup_main; - ftype = ip6_main.ip6_unicast_rx_feature_check_access; - } - - ipcm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; - - ci = ipcm->config_index_by_sw_if_index[sw_if_index]; - ci = ((feature_enable) - ? vnet_config_add_feature - : vnet_config_del_feature) - (vnm, &ipcm->config_main, ci, ftype, - /* config data */ 0, - /* # bytes of config data */ 0); - - ipcm->config_index_by_sw_if_index[sw_if_index] = ci; - am->vnet_config_main[tid] = &ipcm->config_main; + { + vnet_feature_enable_disable ("ip6-unicast", "ip6-inacl", + sw_if_index, feature_enable, 0, 0); + arc = vnet_get_feature_arc_index ("ip6-unicast"); + } + + fcm = vnet_get_feature_arc_config_main (arc); + am->vnet_config_main[tid] = &fcm->config_main; } return 0; diff --git a/vnet/vnet/classify/policer_classify.c b/vnet/vnet/classify/policer_classify.c index ada0dae34d0..569234fba3b 100644 --- a/vnet/vnet/classify/policer_classify.c +++ b/vnet/vnet/classify/policer_classify.c @@ -28,30 +28,25 @@ vnet_policer_classify_feature_enable (vlib_main_t * vnm, } else { - ip_lookup_main_t * lm; - vnet_feature_config_main_t * ipcm; - u32 ftype; - u32 ci; + vnet_feature_config_main_t * fcm; + u8 arc; if (tid == POLICER_CLASSIFY_TABLE_IP4) - { - lm = &ip4_main.lookup_main; - ftype = ip4_main.ip4_unicast_rx_feature_policer_classify; - } + { + vnet_feature_enable_disable ("ip4-unicast", "ip4-policer-classify", + sw_if_index, feature_enable, 0, 0); + arc = vnet_get_feature_arc_index ("ip4-unicast"); + } + else - { - lm = &ip6_main.lookup_main; - ftype = ip6_main.ip6_unicast_rx_feature_policer_classify; - } - - ipcm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; - - ci = ipcm->config_index_by_sw_if_index[sw_if_index]; - ci = (feature_enable ? vnet_config_add_feature : vnet_config_del_feature) - (vnm, &ipcm->config_main, ci, ftype, 0, 0); - - ipcm->config_index_by_sw_if_index[sw_if_index] = ci; - pcm->vnet_config_main[tid] = &ipcm->config_main; + { + vnet_feature_enable_disable ("ip6-unicast", "ip6-policer-classify", + sw_if_index, feature_enable, 0, 0); + arc = vnet_get_feature_arc_index ("ip6-unicast"); + } + + fcm = vnet_get_feature_arc_config_main (arc); + pcm->vnet_config_main[tid] = &fcm->config_main; } } diff --git a/vnet/vnet/devices/devices.c b/vnet/vnet/devices/devices.c index 26753305db2..928b0b4757a 100644 --- a/vnet/vnet/devices/devices.c +++ b/vnet/vnet/devices/devices.c @@ -37,6 +37,7 @@ 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, }; VNET_FEATURE_INIT (l2_patch, static) = { diff --git a/vnet/vnet/ethernet/ethernet.h b/vnet/vnet/ethernet/ethernet.h index c31025b7840..e557a2c23cc 100644 --- a/vnet/vnet/ethernet/ethernet.h +++ b/vnet/vnet/ethernet/ethernet.h @@ -263,34 +263,12 @@ typedef struct /* debug: make sure we don't wipe out an ethernet registration by mistake */ u8 next_by_ethertype_register_called; - /** per-interface features */ - vnet_feature_config_main_t feature_config_mains[VNET_N_IP_FEAT]; - - /** Feature path configuration lists */ - vnet_feature_registration_t *next_feature[VNET_N_IP_FEAT]; - - /** Save results for show command */ - char **feature_nodes[VNET_N_IP_FEAT]; - - /** feature node indicies */ - u32 ethernet_tx_feature_drop; + /* Feature arc index */ + u8 output_feature_arc_index; } ethernet_main_t; ethernet_main_t ethernet_main; -#define VNET_ETHERNET_TX_FEATURE_INIT(x,...) \ - __VA_ARGS__ vnet_feature_registration_t tx_##x; \ -static void __vnet_add_feature_registration_tx_##x (void) \ - __attribute__((__constructor__)) ; \ -static void __vnet_add_feature_registration_tx_##x (void) \ -{ \ - ethernet_main_t * im = ðernet_main; \ - tx_##x.next = im->next_feature[VNET_IP_TX_FEAT]; \ - im->next_feature[VNET_IP_TX_FEAT] = &tx_##x; \ -} \ -__VA_ARGS__ vnet_feature_registration_t tx_##x - - always_inline ethernet_type_info_t * ethernet_get_type_info (ethernet_main_t * em, ethernet_type_t type) { diff --git a/vnet/vnet/ethernet/init.c b/vnet/vnet/ethernet/init.c index b636c4af1a8..2d20adc9610 100644 --- a/vnet/vnet/ethernet/init.c +++ b/vnet/vnet/ethernet/init.c @@ -61,36 +61,24 @@ add_type (ethernet_main_t * em, ethernet_type_t type, char *type_name) hash_set_mem (em->type_info_by_name, ti->name, i); } -static char *feature_start_nodes[] = { - "adj-l2-midchain", -}; - /* Built-in ip4 tx feature path definition */ /* *INDENT-OFF* */ -VNET_ETHERNET_TX_FEATURE_INIT (ethernet_tx_drop, static) = +VNET_FEATURE_ARC_INIT (ethernet_output, static) = +{ + .arc_name = "ethernet-output", + .start_nodes = VNET_FEATURES ("adj-l2-midchain"), + .arc_index_ptr = ðernet_main.output_feature_arc_index, +}; + +VNET_FEATURE_INIT (ethernet_tx_drop, static) = { + .arc_name = "ethernet-output", .node_name = "error-drop", .runs_before = 0, /* not before any other features */ - .feature_index = ðernet_main.ethernet_tx_feature_drop, }; /* *INDENT-ON* */ static clib_error_t * -ethernet_feature_init (vlib_main_t * vm) -{ - vnet_feature_config_main_t *cm = - ðernet_main.feature_config_mains[VNET_IP_TX_FEAT]; - vnet_config_main_t *vcm = &cm->config_main; - - return (vnet_feature_arc_init (vm, vcm, - feature_start_nodes, - ARRAY_LEN (feature_start_nodes), - ethernet_main.next_feature[VNET_IP_TX_FEAT], - ðernet_main.feature_nodes - [VNET_IP_TX_FEAT])); -} - -static clib_error_t * ethernet_init (vlib_main_t * vm) { ethernet_main_t *em = ðernet_main; @@ -116,8 +104,10 @@ ethernet_init (vlib_main_t * vm) return error; if ((error = vlib_call_init_function (vm, ethernet_input_init))) return error; + if ((error = vlib_call_init_function (vm, vnet_feature_init))) + return error; - return (ethernet_feature_init (vm)); + return 0; } VLIB_INIT_FUNCTION (ethernet_init); diff --git a/vnet/vnet/feature/feature.c b/vnet/vnet/feature/feature.c index 25f098d33ad..1f46285aa21 100644 --- a/vnet/vnet/feature/feature.c +++ b/vnet/vnet/feature/feature.c @@ -34,6 +34,8 @@ vnet_feature_init (vlib_main_t * vm) 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)); @@ -111,8 +113,6 @@ vnet_feature_init (vlib_main_t * vm) arc_index++; } - fm->device_input_feature_arc_index = - vnet_get_feature_arc_index ("device-input"); return 0; } @@ -164,29 +164,27 @@ vnet_get_feature_index (u8 arc, const char *s) return ~0; reg = uword_to_pointer (p[0], vnet_feature_registration_t *); - return reg->feature_index_u32; + return reg->feature_index; } 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) +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; - u32 feature_index, ci; - u8 arc_index; - - arc_index = vnet_get_feature_arc_index (arc_name); + u32 ci; if (arc_index == (u8) ~ 0) return VNET_API_ERROR_INVALID_VALUE; - cm = &fm->feature_config_mains[arc_index]; - vec_validate_init_empty (cm->config_index_by_sw_if_index, sw_if_index, ~0); - feature_index = vnet_get_feature_index (arc_index, node_name); if (feature_index == ~0) return VNET_API_ERROR_INVALID_VALUE_2; + + 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]; ci = (enable_disable @@ -202,6 +200,27 @@ vnet_feature_enable_disable (const char *arc_name, const char *node_name, return 0; } +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); +} + /** Display the set of available driver features. Useful for verifying that expected features are present diff --git a/vnet/vnet/feature/feature.h b/vnet/vnet/feature/feature.h index 793678b74fc..b026cdf1c8f 100644 --- a/vnet/vnet/feature/feature.h +++ b/vnet/vnet/feature/feature.h @@ -31,6 +31,7 @@ typedef struct _vnet_feature_arc_registration int n_start_nodes; /* Feature arc index, assigned by init function */ u8 feature_arc_index; + u8 *arc_index_ptr; } vnet_feature_arc_registration_t; /** feature registration object */ @@ -43,8 +44,8 @@ typedef struct _vnet_feature_registration /** Graph node name */ char *node_name; /** Pointer to this feature index, filled in by vnet_feature_arc_init */ - u32 *feature_index; - u32 feature_index_u32; + u32 *feature_index_ptr; + u32 feature_index; /** Constraints of the form "this feature runs before X" */ char **runs_before; /** Constraints of the form "this feature runs after Y" */ @@ -122,11 +123,27 @@ u32 vnet_get_feature_index (u8 arc, const char *s); u8 vnet_get_feature_arc_index (const char *s); int +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); + +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); +static inline vnet_feature_config_main_t * +vnet_get_feature_arc_config_main (u8 arc_index) +{ + vnet_feature_main_t *fm = &feature_main; + + if (arc_index == (u8) ~ 0) + return 0; + + return &fm->feature_config_mains[arc_index]; +} static_always_inline int vnet_have_features (u8 arc, u32 sw_if_index) @@ -259,7 +276,6 @@ vnet_feature_start_device_input_x2 (u32 sw_if_index, } -#define ORDER_CONSTRAINTS (char*[]) #define VNET_FEATURES(...) (char*[]) { __VA_ARGS__, 0} clib_error_t *vnet_feature_arc_init (vlib_main_t * vm, diff --git a/vnet/vnet/feature/registration.c b/vnet/vnet/feature/registration.c index e6b0968e53c..1deeeef904c 100644 --- a/vnet/vnet/feature/registration.c +++ b/vnet/vnet/feature/registration.c @@ -79,7 +79,6 @@ vnet_feature_next. */ -static const char *vnet_cast_names[] = VNET_CAST_NAMES; static int comma_split (u8 * s, u8 ** a, u8 ** b) @@ -196,7 +195,7 @@ vnet_feature_arc_init (vlib_main_t * vm, p = hash_get_mem (index_by_name, a_name); /* - * Note: the next two errors mean that the xxx_FEATURE_INIT macros are + * Note: the next two errors mean that something is * b0rked. As in: if you code "A depends on B," and you forget * to define a FEATURE_INIT macro for B, you lose. * Nonexistent graph nodes are tolerated. @@ -260,9 +259,9 @@ again: p = hash_get (reg_by_index, result[i]); ASSERT (p != 0); this_reg = (vnet_feature_registration_t *) p[0]; - if (this_reg->feature_index) - *this_reg->feature_index = n_features - (i + 1); - this_reg->feature_index_u32 = n_features - (i + 1); + if (this_reg->feature_index_ptr) + *this_reg->feature_index_ptr = n_features - (i + 1); + this_reg->feature_index = n_features - (i + 1); vec_add1 (feature_nodes, this_reg->node_name); } @@ -293,208 +292,6 @@ again: return 0; } -#define foreach_af_cast \ -_(4, VNET_IP_RX_UNICAST_FEAT, "ip4 unicast") \ -_(4, VNET_IP_RX_MULTICAST_FEAT, "ip4 multicast") \ -_(4, VNET_IP_TX_FEAT, "ip4 output") \ -_(6, VNET_IP_RX_UNICAST_FEAT, "ip6 unicast") \ -_(6, VNET_IP_RX_MULTICAST_FEAT, "ip6 multicast") \ -_(6, VNET_IP_TX_FEAT, "ip6 output") - -/** Display the set of available ip features. - Useful for verifying that expected features are present -*/ - -static clib_error_t * -show_ip_features_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - ip4_main_t *im4 = &ip4_main; - ip6_main_t *im6 = &ip6_main; - int i; - char **features; - - vlib_cli_output (vm, "Available IP feature nodes"); - -#define _(a,c,s) \ - do { \ - features = im##a->feature_nodes[c]; \ - vlib_cli_output (vm, "%s:", s); \ - for (i = 0; i < vec_len(features); i++) \ - vlib_cli_output (vm, " %s\n", features[i]); \ - } while(0); - foreach_af_cast; -#undef _ - - return 0; -} - -/*? - * This command is used to display the set of available IP features. - * This can be useful for verifying that expected features are present. - * - * @cliexpar - * Example of how to display the set of available IP features: - * @cliexstart{show ip features} - * Available IP feature nodes - * ip4 unicast: - * ip4-inacl - * ip4-source-check-via-rx - * ip4-source-check-via-any - * ip4-source-and-port-range-check-rx - * ip4-policer-classify - * ipsec-input-ip4 - * vpath-input-ip4 - * snat-in2out - * snat-out2in - * ip4-lookup - * ip4 multicast: - * vpath-input-ip4 - * ip4-lookup-multicast - * ip4 output: - * ip4-source-and-port-range-check-tx - * interface-output - * ip6 unicast: - * ip6-inacl - * ip6-policer-classify - * ipsec-input-ip6 - * l2tp-decap - * vpath-input-ip6 - * sir-to-ila - * ip6-lookup - * ip6 multicast: - * vpath-input-ip6 - * ip6-lookup - * ip6 output: - * interface-output - * @cliexend -?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (show_ip_features_command, static) = { - .path = "show ip features", - .short_help = "show ip features", - .function = show_ip_features_command_fn, -}; -/* *INDENT-ON* */ - -/** Display the set of IP features configured on a specific interface - */ - -void -ip_interface_features_show (vlib_main_t * vm, - const char *pname, - vnet_feature_config_main_t * cm, u32 sw_if_index) -{ - u32 node_index, current_config_index; - vnet_cast_t cast; - vnet_config_main_t *vcm; - vnet_config_t *cfg; - u32 cfg_index; - vnet_config_feature_t *feat; - vlib_node_t *n; - int i; - - vlib_cli_output (vm, "%s feature paths configured on %U...", - pname, format_vnet_sw_if_index_name, - vnet_get_main (), sw_if_index); - - for (cast = VNET_IP_RX_UNICAST_FEAT; cast < VNET_N_IP_FEAT; cast++) - { - vcm = &(cm[cast].config_main); - - vlib_cli_output (vm, "\n%s %s:", pname, vnet_cast_names[cast]); - - if (NULL == cm[cast].config_index_by_sw_if_index || - vec_len (cm[cast].config_index_by_sw_if_index) < sw_if_index) - { - vlib_cli_output (vm, "none configured"); - continue; - } - - current_config_index = vec_elt (cm[cast].config_index_by_sw_if_index, - sw_if_index); - - ASSERT (current_config_index - < vec_len (vcm->config_pool_index_by_user_index)); - - cfg_index = 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); - vlib_cli_output (vm, " %v", n->name); - } - } -} - -static clib_error_t * -show_ip_interface_features_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - vnet_main_t *vnm = vnet_get_main (); - ip4_main_t *im4 = &ip4_main; - ip_lookup_main_t *lm4 = &im4->lookup_main; - ip6_main_t *im6 = &ip6_main; - ip_lookup_main_t *lm6 = &im6->lookup_main; - - ip_lookup_main_t *lm; - u32 sw_if_index, af; - - if (!unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index)) - return clib_error_return (0, "Interface not specified..."); - - vlib_cli_output (vm, "IP feature paths configured on %U...", - format_vnet_sw_if_index_name, vnm, sw_if_index); - - for (af = 0; af < 2; af++) - { - if (af == 0) - lm = lm4; - else - lm = lm6; - - ip_interface_features_show (vm, (af == 0) ? "ip4" : "ip6", - lm->feature_config_mains, sw_if_index); - } - - return 0; -} - -/*? - * This command is used to display the set of IP features configured - * on a specific interface - * - * @cliexpar - * Example of how to display the set of available IP features on an interface: - * @cliexstart{show ip interface features GigabitEthernet2/0/0} - * IP feature paths configured on GigabitEthernet2/0/0... - * ipv4 unicast: - * ip4-lookup - * ipv4 multicast: - * ip4-lookup-multicast - * ipv4 multicast: - * interface-output - * ipv6 unicast: - * ip6-lookup - * ipv6 multicast: - * ip6-lookup - * ipv6 multicast: - * interface-output - * @cliexend -?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (show_ip_interface_features_command, static) = { - .path = "show ip interface features", - .short_help = "show ip interface features <interface>", - .function = show_ip_interface_features_command_fn, -}; -/* *INDENT-ON* */ - /* * fd.io coding-style-patch-verification: ON * diff --git a/vnet/vnet/ip/ip.h b/vnet/vnet/ip/ip.h index a57d162c8c3..c9a82930a67 100644 --- a/vnet/vnet/ip/ip.h +++ b/vnet/vnet/ip/ip.h @@ -217,10 +217,4 @@ void ip_del_all_interface_addresses (vlib_main_t *vm, u32 sw_if_index); extern vlib_node_registration_t ip4_inacl_node; extern vlib_node_registration_t ip6_inacl_node; -void -vnet_config_update_tx_feature_count (ip_lookup_main_t * lm, - vnet_feature_config_main_t * tx_cm, - u32 sw_if_index, - int is_add); - #endif /* included_ip_main_h */ diff --git a/vnet/vnet/ip/ip4.h b/vnet/vnet/ip/ip4.h index f0806c08449..62bb5f8513c 100644 --- a/vnet/vnet/ip/ip4.h +++ b/vnet/vnet/ip/ip4.h @@ -116,46 +116,6 @@ typedef struct ip4_main_t { /** Template used to generate IP4 ARP packets. */ vlib_packet_template_t ip4_arp_request_packet_template; - /** Feature path configuration lists */ - vnet_feature_registration_t * next_feature[VNET_N_IP_FEAT]; - - /** Built-in unicast feature path index, see @ref vnet_feature_arc_init() */ - u32 ip4_unicast_rx_feature_check_access; - /** Built-in unicast feature path index, see @ref vnet_feature_arc_init() */ - u32 ip4_unicast_rx_feature_source_reachable_via_rx; - /** Built-in unicast feature path index, see @ref vnet_feature_arc_init() */ - u32 ip4_unicast_rx_feature_source_reachable_via_any; - /** Built-in unicast feature path index, see @ref vnet_feature_arc_init() */ - u32 ip4_unicast_rx_feature_policer_classify; - /** Built-in unicast feature path index, see @ref vnet_feature_arc_init() */ - u32 ip4_unicast_rx_feature_flow_classify; - /** Built-in unicast feature path indix, see @ref vnet_feature_arc_init() */ - u32 ip4_unicast_rx_feature_ipsec; - /** Built-in unicast feature path index, see @ref vnet_feature_arc_init() */ - u32 ip4_unicast_rx_feature_vpath; - /** Built-in unicast feature path index, see @ref vnet_feature_arc_init() */ - u32 ip4_unicast_rx_feature_lookup; - /** Built-in unicast feature path index, see @ref vnet_feature_arc_init() */ - u32 ip4_unicast_rx_feature_source_and_port_range_check; - /** Built-in unicast feature path indice, see @ref vnet_feature_arc_init() */ - u32 ip4_unicast_rx_feature_drop; - - /** Built-in multicast feature path index */ - u32 ip4_multicast_rx_feature_vpath; - /** Built-in multicast feature path index */ - u32 ip4_multicast_rx_feature_lookup; - /** Built-in multicast feature path indices */ - u32 ip4_multicast_rx_feature_drop; - - /** Built-in unicast feature path index, see @ref vnet_feature_arc_init() */ - u32 ip4_unicast_tx_feature_source_and_port_range_check; - - /** Built-in tx feature path index */ - u32 ip4_tx_feature_interface_output; - - /** Save results for show command */ - char ** feature_nodes[VNET_N_IP_FEAT]; - /** Seed for Jenkins hash used to compute ip4 flow hash. */ u32 flow_hash_seed; @@ -174,43 +134,6 @@ typedef struct ip4_main_t { /** Global ip4 main structure. */ extern ip4_main_t ip4_main; -#define VNET_IP4_UNICAST_FEATURE_INIT(x,...) \ - __VA_ARGS__ vnet_feature_registration_t uc_##x; \ -static void __vnet_add_feature_registration_uc_##x (void) \ - __attribute__((__constructor__)) ; \ -static void __vnet_add_feature_registration_uc_##x (void) \ -{ \ - ip4_main_t * im = &ip4_main; \ - uc_##x.next = im->next_feature[VNET_IP_RX_UNICAST_FEAT]; \ - im->next_feature[VNET_IP_RX_UNICAST_FEAT] = &uc_##x; \ -} \ -__VA_ARGS__ vnet_feature_registration_t uc_##x - -#define VNET_IP4_MULTICAST_FEATURE_INIT(x,...) \ - __VA_ARGS__ vnet_feature_registration_t mc_##x; \ -static void __vnet_add_feature_registration_mc_##x (void) \ - __attribute__((__constructor__)) ; \ -static void __vnet_add_feature_registration_mc_##x (void) \ -{ \ - ip4_main_t * im = &ip4_main; \ - mc_##x.next = im->next_feature[VNET_IP_RX_MULTICAST_FEAT]; \ - im->next_feature[VNET_IP_RX_MULTICAST_FEAT] = &mc_##x; \ -} \ -__VA_ARGS__ vnet_feature_registration_t mc_##x - -#define VNET_IP4_TX_FEATURE_INIT(x,...) \ - __VA_ARGS__ vnet_feature_registration_t tx_##x; \ -static void __vnet_add_feature_registration_tx_##x (void) \ - __attribute__((__constructor__)) ; \ -static void __vnet_add_feature_registration_tx_##x (void) \ -{ \ - ip4_main_t * im = &ip4_main; \ - tx_##x.next = im->next_feature[VNET_IP_TX_FEAT]; \ - im->next_feature[VNET_IP_TX_FEAT] = &tx_##x; \ -} \ -__VA_ARGS__ vnet_feature_registration_t tx_##x - - /** Global ip4 input node. Errors get attached to ip4 input node. */ extern vlib_node_registration_t ip4_input_node; extern vlib_node_registration_t ip4_lookup_node; diff --git a/vnet/vnet/ip/ip4_forward.c b/vnet/vnet/ip/ip4_forward.c index 632925a4a59..6d3dd88b176 100644 --- a/vnet/vnet/ip/ip4_forward.c +++ b/vnet/vnet/ip/ip4_forward.c @@ -709,11 +709,7 @@ void ip4_sw_interface_enable_disable (u32 sw_if_index, u32 is_enable) { - vlib_main_t * vm = vlib_get_main(); ip4_main_t * im = &ip4_main; - ip_lookup_main_t * lm = &im->lookup_main; - u32 ci, cast; - u32 lookup_feature_index; vec_validate_init_empty (im->ip_enabled_by_sw_if_index, sw_if_index, 0); @@ -731,34 +727,12 @@ ip4_sw_interface_enable_disable (u32 sw_if_index, if (0 != --im->ip_enabled_by_sw_if_index[sw_if_index]) return; } + vnet_feature_enable_disable ("ip4-unicast", "ip4-lookup", sw_if_index, + is_enable, 0, 0); - for (cast = 0; cast <= VNET_IP_RX_MULTICAST_FEAT; cast++) - { - vnet_feature_config_main_t * cm = &lm->feature_config_mains[cast]; - vnet_config_main_t * vcm = &cm->config_main; - - 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]; + vnet_feature_enable_disable ("ip4-multicast", "ip4-lookup-multicast", sw_if_index, + is_enable, 0, 0); - if (cast == VNET_IP_RX_UNICAST_FEAT) - lookup_feature_index = im->ip4_unicast_rx_feature_lookup; - else - lookup_feature_index = im->ip4_multicast_rx_feature_lookup; - - if (is_enable) - ci = vnet_config_add_feature (vm, vcm, - ci, - lookup_feature_index, - /* config data */ 0, - /* # bytes of config data */ 0); - else - ci = vnet_config_del_feature (vm, vcm, - ci, - lookup_feature_index, - /* config data */ 0, - /* # bytes of config data */ 0); - cm->config_index_by_sw_if_index[sw_if_index] = ci; - } } static clib_error_t * @@ -854,202 +828,140 @@ ip4_add_del_interface_address (vlib_main_t * vm, u32 sw_if_index, } /* Built-in ip4 unicast rx feature path definition */ -VNET_IP4_UNICAST_FEATURE_INIT (ip4_flow_classify, static) = { +VNET_FEATURE_ARC_INIT (ip4_unicast, static) = +{ + .arc_name = "ip4-unicast", + .start_nodes = VNET_FEATURES ("ip4-input", "ip4-input-no-checksum"), + .arc_index_ptr = &ip4_main.lookup_main.ucast_feature_arc_index, +}; + +VNET_FEATURE_INIT (ip4_flow_classify, static) = { + .arc_name = "ip4-unicast", .node_name = "ip4-flow-classify", - .runs_before = ORDER_CONSTRAINTS {"ip4-inacl", 0}, - .feature_index = &ip4_main.ip4_unicast_rx_feature_flow_classify, + .runs_before = VNET_FEATURES ("ip4-inacl"), }; -VNET_IP4_UNICAST_FEATURE_INIT (ip4_inacl, static) = { +VNET_FEATURE_INIT (ip4_inacl, static) = { + .arc_name = "ip4-unicast", .node_name = "ip4-inacl", - .runs_before = ORDER_CONSTRAINTS {"ip4-source-check-via-rx", 0}, - .feature_index = &ip4_main.ip4_unicast_rx_feature_check_access, + .runs_before = VNET_FEATURES ("ip4-source-check-via-rx"), }; -VNET_IP4_UNICAST_FEATURE_INIT (ip4_source_check_1, static) = { +VNET_FEATURE_INIT (ip4_source_check_1, static) = { + .arc_name = "ip4-unicast", .node_name = "ip4-source-check-via-rx", - .runs_before = ORDER_CONSTRAINTS {"ip4-source-check-via-any", 0}, - .feature_index = - &ip4_main.ip4_unicast_rx_feature_source_reachable_via_rx, + .runs_before = VNET_FEATURES ("ip4-source-check-via-any"), }; -VNET_IP4_UNICAST_FEATURE_INIT (ip4_source_check_2, static) = { +VNET_FEATURE_INIT (ip4_source_check_2, static) = { + .arc_name = "ip4-unicast", .node_name = "ip4-source-check-via-any", - .runs_before = ORDER_CONSTRAINTS {"ip4-policer-classify", 0}, - .feature_index = - &ip4_main.ip4_unicast_rx_feature_source_reachable_via_any, + .runs_before = VNET_FEATURES ("ip4-policer-classify"), }; -VNET_IP4_UNICAST_FEATURE_INIT (ip4_source_and_port_range_check_rx, static) = { +VNET_FEATURE_INIT (ip4_source_and_port_range_check_rx, static) = { + .arc_name = "ip4-unicast", .node_name = "ip4-source-and-port-range-check-rx", - .runs_before = ORDER_CONSTRAINTS {"ip4-policer-classify", 0}, - .feature_index = - &ip4_main.ip4_unicast_rx_feature_source_and_port_range_check, + .runs_before = VNET_FEATURES ("ip4-policer-classify"), }; -VNET_IP4_UNICAST_FEATURE_INIT (ip4_policer_classify, static) = { +VNET_FEATURE_INIT (ip4_policer_classify, static) = { + .arc_name = "ip4-unicast", .node_name = "ip4-policer-classify", - .runs_before = ORDER_CONSTRAINTS {"ipsec-input-ip4", 0}, - .feature_index = - &ip4_main.ip4_unicast_rx_feature_policer_classify, + .runs_before = VNET_FEATURES ("ipsec-input-ip4"), }; -VNET_IP4_UNICAST_FEATURE_INIT (ip4_ipsec, static) = { +VNET_FEATURE_INIT (ip4_ipsec, static) = { + .arc_name = "ip4-unicast", .node_name = "ipsec-input-ip4", - .runs_before = ORDER_CONSTRAINTS {"vpath-input-ip4", 0}, - .feature_index = &ip4_main.ip4_unicast_rx_feature_ipsec, + .runs_before = VNET_FEATURES ("vpath-input-ip4"), }; -VNET_IP4_UNICAST_FEATURE_INIT (ip4_vpath, static) = { +VNET_FEATURE_INIT (ip4_vpath, static) = { + .arc_name = "ip4-unicast", .node_name = "vpath-input-ip4", - .runs_before = ORDER_CONSTRAINTS {"ip4-lookup", 0}, - .feature_index = &ip4_main.ip4_unicast_rx_feature_vpath, + .runs_before = VNET_FEATURES ("ip4-lookup"), }; -VNET_IP4_UNICAST_FEATURE_INIT (ip4_lookup, static) = { +VNET_FEATURE_INIT (ip4_lookup, static) = { + .arc_name = "ip4-unicast", .node_name = "ip4-lookup", - .runs_before = ORDER_CONSTRAINTS {"ip4-drop", 0}, - .feature_index = &ip4_main.ip4_unicast_rx_feature_lookup, + .runs_before = VNET_FEATURES ("ip4-drop"), }; -VNET_IP4_UNICAST_FEATURE_INIT (ip4_drop, static) = { +VNET_FEATURE_INIT (ip4_drop, static) = { + .arc_name = "ip4-unicast", .node_name = "ip4-drop", .runs_before = 0, /* not before any other features */ - .feature_index = &ip4_main.ip4_unicast_rx_feature_drop, }; /* Built-in ip4 multicast rx feature path definition */ -VNET_IP4_MULTICAST_FEATURE_INIT (ip4_vpath_mc, static) = { +VNET_FEATURE_ARC_INIT (ip4_multicast, static) = +{ + .arc_name = "ip4-multicast", + .start_nodes = VNET_FEATURES ("ip4-input", "ip4-input-no-checksum"), + .arc_index_ptr = &ip4_main.lookup_main.mcast_feature_arc_index, +}; + +VNET_FEATURE_INIT (ip4_vpath_mc, static) = { + .arc_name = "ip4-multicast", .node_name = "vpath-input-ip4", - .runs_before = ORDER_CONSTRAINTS {"ip4-lookup-multicast", 0}, - .feature_index = &ip4_main.ip4_multicast_rx_feature_vpath, + .runs_before = VNET_FEATURES ("ip4-lookup-multicast"), }; -VNET_IP4_MULTICAST_FEATURE_INIT (ip4_lookup_mc, static) = { +VNET_FEATURE_INIT (ip4_lookup_mc, static) = { + .arc_name = "ip4-multicast", .node_name = "ip4-lookup-multicast", - .runs_before = ORDER_CONSTRAINTS {"ip4-drop", 0}, - .feature_index = &ip4_main.ip4_multicast_rx_feature_lookup, + .runs_before = VNET_FEATURES ("ip4-drop"), }; -VNET_IP4_MULTICAST_FEATURE_INIT (ip4_mc_drop, static) = { +VNET_FEATURE_INIT (ip4_mc_drop, static) = { + .arc_name = "ip4-multicast", .node_name = "ip4-drop", .runs_before = 0, /* last feature */ - .feature_index = &ip4_main.ip4_multicast_rx_feature_drop, }; -static char * rx_feature_start_nodes[] = - { "ip4-input", "ip4-input-no-checksum"}; - -static char * tx_feature_start_nodes[] = +/* Source and port-range check ip4 tx feature path definition */ +VNET_FEATURE_ARC_INIT (ip4_output, static) = { - "ip4-rewrite-transit", - "ip4-midchain", + .arc_name = "ip4-output", + .start_nodes = VNET_FEATURES ("ip4-rewrite-transit", "ip4-midchain"), + .arc_index_ptr = &ip4_main.lookup_main.output_feature_arc_index, }; -/* Source and port-range check ip4 tx feature path definition */ -VNET_IP4_TX_FEATURE_INIT (ip4_source_and_port_range_check_tx, static) = { +VNET_FEATURE_INIT (ip4_source_and_port_range_check_tx, static) = { + .arc_name = "ip4-output", .node_name = "ip4-source-and-port-range-check-tx", - .runs_before = ORDER_CONSTRAINTS {"interface-output", 0}, - .feature_index = - &ip4_main.ip4_unicast_tx_feature_source_and_port_range_check, - + .runs_before = VNET_FEATURES ("interface-output"), }; /* Built-in ip4 tx feature path definition */ -VNET_IP4_TX_FEATURE_INIT (interface_output, static) = { +VNET_FEATURE_INIT (ip4_interface_output, static) = { + .arc_name = "ip4-output", .node_name = "interface-output", .runs_before = 0, /* not before any other features */ - .feature_index = &ip4_main.ip4_tx_feature_interface_output, }; -static clib_error_t * -ip4_feature_init (vlib_main_t * vm, ip4_main_t * im) -{ - ip_lookup_main_t * lm = &im->lookup_main; - clib_error_t * error; - vnet_cast_t cast; - vnet_feature_config_main_t * cm; - vnet_config_main_t * vcm; - char **feature_start_nodes; - int feature_start_len; - - for (cast = 0; cast < VNET_N_IP_FEAT; cast++) - { - cm = &lm->feature_config_mains[cast]; - vcm = &cm->config_main; - - if (cast < VNET_IP_TX_FEAT) - { - feature_start_nodes = rx_feature_start_nodes; - feature_start_len = ARRAY_LEN(rx_feature_start_nodes); - } - else - { - feature_start_nodes = tx_feature_start_nodes; - feature_start_len = ARRAY_LEN(tx_feature_start_nodes); - } - - if ((error = vnet_feature_arc_init (vm, vcm, - feature_start_nodes, - feature_start_len, - im->next_feature[cast], - &im->feature_nodes[cast]))) - return error; - } - - return 0; -} static clib_error_t * ip4_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add) { - vlib_main_t * vm = vnm->vlib_main; ip4_main_t * im = &ip4_main; - ip_lookup_main_t * lm = &im->lookup_main; - u32 ci, cast; - u32 feature_index; /* Fill in lookup tables with default table (0). */ vec_validate (im->fib_index_by_sw_if_index, sw_if_index); - for (cast = 0; cast < VNET_N_IP_FEAT; cast++) - { - vnet_feature_config_main_t * cm = &lm->feature_config_mains[cast]; - vnet_config_main_t * vcm = &cm->config_main; + vnet_feature_enable_disable ("ip4-unicast", "ip4-drop", sw_if_index, + is_add, 0, 0); - 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]; + vnet_feature_enable_disable ("ip4-multicast", "ip4-drop", sw_if_index, + is_add, 0, 0); - if (cast == VNET_IP_RX_UNICAST_FEAT) - feature_index = im->ip4_unicast_rx_feature_drop; - else if (cast == VNET_IP_RX_MULTICAST_FEAT) - feature_index = im->ip4_multicast_rx_feature_drop; - else - feature_index = im->ip4_tx_feature_interface_output; - - if (is_add) - ci = vnet_config_add_feature (vm, vcm, - ci, - feature_index, - /* config data */ 0, - /* # bytes of config data */ 0); - else - { - ci = vnet_config_del_feature (vm, vcm, ci, - feature_index, - /* config data */ 0, - /* # bytes of config data */ 0); - if (vec_len(im->ip_enabled_by_sw_if_index) > sw_if_index) - im->ip_enabled_by_sw_if_index[sw_if_index] = 0; - } - cm->config_index_by_sw_if_index[sw_if_index] = ci; - /* - * note: do not update the tx feature count here. - */ - } + vnet_feature_enable_disable ("ip4-output", "interface-output", sw_if_index, + is_add, 0, 0); return /* no error */ 0; } @@ -1066,6 +978,9 @@ ip4_lookup_init (vlib_main_t * vm) clib_error_t * error; uword i; + if ((error = vlib_call_init_function (vm, vnet_feature_init))) + return error; + for (i = 0; i < ARRAY_LEN (im->fib_masks); i++) { u32 m; @@ -1114,8 +1029,6 @@ ip4_lookup_init (vlib_main_t * vm) "ip4 arp"); } - error = ip4_feature_init (vm, im); - return error; } @@ -2184,7 +2097,6 @@ ip4_rewrite_inline (vlib_main_t * vm, u32 n_left_from, n_left_to_next, * to_next, next_index; vlib_node_runtime_t * error_node = vlib_node_get_runtime (vm, ip4_input_node.index); vlib_rx_or_tx_t adj_rx_tx = rewrite_for_locally_received_packets ? VLIB_RX : VLIB_TX; - vnet_feature_config_main_t * cm = &lm->feature_config_mains[VNET_IP_TX_FEAT]; n_left_from = frame->n_vectors; next_index = node->cached_next_index; @@ -2362,18 +2274,8 @@ ip4_rewrite_inline (vlib_main_t * vm, vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0; - if (PREDICT_FALSE - (clib_bitmap_get (lm->tx_sw_if_has_ip_output_features, - tx_sw_if_index0))) - { - p0->current_config_index = - vec_elt (cm->config_index_by_sw_if_index, - tx_sw_if_index0); - vnet_get_config_data (&cm->config_main, - &p0->current_config_index, - &next0, - /* # bytes of config data */ 0); - } + vnet_feature_arc_start(lm->output_feature_arc_index, + tx_sw_if_index0, &next0, p0); } if (PREDICT_TRUE(error1 == IP4_ERROR_NONE)) { @@ -2384,18 +2286,8 @@ ip4_rewrite_inline (vlib_main_t * vm, vnet_buffer (p1)->sw_if_index[VLIB_TX] = tx_sw_if_index1; - if (PREDICT_FALSE - (clib_bitmap_get (lm->tx_sw_if_has_ip_output_features, - tx_sw_if_index1))) - { - p1->current_config_index = - vec_elt (cm->config_index_by_sw_if_index, - tx_sw_if_index1); - vnet_get_config_data (&cm->config_main, - &p1->current_config_index, - &next1, - /* # bytes of config data */ 0); - } + vnet_feature_arc_start(lm->output_feature_arc_index, + tx_sw_if_index1, &next1, p1); } /* Guess we are only writing on simple Ethernet header. */ @@ -2525,18 +2417,9 @@ ip4_rewrite_inline (vlib_main_t * vm, adj0->sub_type.midchain.fixup_func(vm, adj0, p0); } - if (PREDICT_FALSE - (clib_bitmap_get (lm->tx_sw_if_has_ip_output_features, - tx_sw_if_index0))) - { - p0->current_config_index = - vec_elt (cm->config_index_by_sw_if_index, - tx_sw_if_index0); - vnet_get_config_data (&cm->config_main, - &p0->current_config_index, - &next0, - /* # bytes of config data */ 0); - } + vnet_feature_arc_start(lm->output_feature_arc_index, + tx_sw_if_index0, &next0, p0); + } if (rewrite_for_locally_received_packets) diff --git a/vnet/vnet/ip/ip4_input.c b/vnet/vnet/ip/ip4_input.c index 268f7afa828..a3620de8b42 100644 --- a/vnet/vnet/ip/ip4_input.c +++ b/vnet/vnet/ip/ip4_input.c @@ -108,11 +108,10 @@ ip4_input_inline (vlib_main_t * vm, { vlib_buffer_t * p0, * p1; ip4_header_t * ip0, * ip1; - vnet_feature_config_main_t * cm0, * cm1; - u32 sw_if_index0, pi0, ip_len0, cur_len0, next0; - u32 sw_if_index1, pi1, ip_len1, cur_len1, next1; + u32 sw_if_index0, pi0, ip_len0, cur_len0, next0 = 0; + u32 sw_if_index1, pi1, ip_len1, cur_len1, next1 = 0; i32 len_diff0, len_diff1; - u8 error0, error1, cast0, cast1; + u8 error0, error1, arc0, arc1; /* Prefetch next iteration. */ { @@ -144,26 +143,14 @@ ip4_input_inline (vlib_main_t * vm, sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX]; sw_if_index1 = vnet_buffer (p1)->sw_if_index[VLIB_RX]; - cast0 = ip4_address_is_multicast (&ip0->dst_address) ? VNET_IP_RX_MULTICAST_FEAT : VNET_IP_RX_UNICAST_FEAT; - cast1 = ip4_address_is_multicast (&ip1->dst_address) ? VNET_IP_RX_MULTICAST_FEAT : VNET_IP_RX_UNICAST_FEAT; - - cm0 = lm->feature_config_mains + cast0; - cm1 = lm->feature_config_mains + cast1; - - p0->current_config_index = vec_elt (cm0->config_index_by_sw_if_index, sw_if_index0); - p1->current_config_index = vec_elt (cm1->config_index_by_sw_if_index, sw_if_index1); + arc0 = ip4_address_is_multicast (&ip0->dst_address) ? lm->mcast_feature_arc_index : lm->ucast_feature_arc_index; + arc1 = ip4_address_is_multicast (&ip1->dst_address) ? lm->mcast_feature_arc_index : lm->ucast_feature_arc_index; vnet_buffer (p0)->ip.adj_index[VLIB_RX] = ~0; vnet_buffer (p1)->ip.adj_index[VLIB_RX] = ~0; - vnet_get_config_data (&cm0->config_main, - &p0->current_config_index, - &next0, - /* # bytes of config data */ 0); - vnet_get_config_data (&cm1->config_main, - &p1->current_config_index, - &next1, - /* # bytes of config data */ 0); + vnet_feature_arc_start (arc0, sw_if_index0, &next0, p0); + vnet_feature_arc_start (arc1, sw_if_index1, &next1, p1); vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1); vlib_increment_simple_counter (cm, cpu_index, sw_if_index1, 1); @@ -195,8 +182,8 @@ ip4_input_inline (vlib_main_t * vm, error1 = ip4_get_fragment_offset (ip1) == 1 ? IP4_ERROR_FRAGMENT_OFFSET_ONE : error1; /* TTL < 1? Drop it. */ - error0 = (ip0->ttl < 1 && cast0 == VNET_IP_RX_UNICAST_FEAT) ? IP4_ERROR_TIME_EXPIRED : error0; - error1 = (ip1->ttl < 1 && cast1 == VNET_IP_RX_UNICAST_FEAT) ? IP4_ERROR_TIME_EXPIRED : error1; + error0 = (ip0->ttl < 1 && arc0 == lm->ucast_feature_arc_index) ? IP4_ERROR_TIME_EXPIRED : error0; + error1 = (ip1->ttl < 1 && arc1 == lm->ucast_feature_arc_index) ? IP4_ERROR_TIME_EXPIRED : error1; /* Verify lengths. */ ip_len0 = clib_net_to_host_u16 (ip0->length); @@ -245,10 +232,9 @@ ip4_input_inline (vlib_main_t * vm, { vlib_buffer_t * p0; ip4_header_t * ip0; - vnet_feature_config_main_t * cm0; - u32 sw_if_index0, pi0, ip_len0, cur_len0, next0; + u32 sw_if_index0, pi0, ip_len0, cur_len0, next0 = 0; i32 len_diff0; - u8 error0, cast0; + u8 error0, arc0; pi0 = from[0]; to_next[0] = pi0; @@ -262,14 +248,9 @@ ip4_input_inline (vlib_main_t * vm, sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX]; - cast0 = ip4_address_is_multicast (&ip0->dst_address) ? VNET_IP_RX_MULTICAST_FEAT : VNET_IP_RX_UNICAST_FEAT; - cm0 = lm->feature_config_mains + cast0; - p0->current_config_index = vec_elt (cm0->config_index_by_sw_if_index, sw_if_index0); + arc0 = ip4_address_is_multicast (&ip0->dst_address) ? lm->mcast_feature_arc_index : lm->ucast_feature_arc_index; vnet_buffer (p0)->ip.adj_index[VLIB_RX] = ~0; - vnet_get_config_data (&cm0->config_main, - &p0->current_config_index, - &next0, - /* # bytes of config data */ 0); + vnet_feature_arc_start (arc0, sw_if_index0, &next0, p0); vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1); @@ -294,7 +275,7 @@ ip4_input_inline (vlib_main_t * vm, error0 = ip4_get_fragment_offset (ip0) == 1 ? IP4_ERROR_FRAGMENT_OFFSET_ONE : error0; /* TTL < 1? Drop it. */ - error0 = (ip0->ttl < 1 && cast0 == VNET_IP_RX_UNICAST_FEAT) ? IP4_ERROR_TIME_EXPIRED : error0; + error0 = (ip0->ttl < 1 && arc0 == lm->ucast_feature_arc_index) ? IP4_ERROR_TIME_EXPIRED : error0; /* Verify lengths. */ ip_len0 = clib_net_to_host_u16 (ip0->length); diff --git a/vnet/vnet/ip/ip4_source_and_port_range_check.c b/vnet/vnet/ip/ip4_source_and_port_range_check.c index 8b69522aebe..28dabeb3f41 100644 --- a/vnet/vnet/ip/ip4_source_and_port_range_check.c +++ b/vnet/vnet/ip/ip4_source_and_port_range_check.c @@ -155,11 +155,6 @@ ip4_source_and_port_range_check_inline (vlib_main_t * vm, vlib_frame_t * frame, int is_tx) { ip4_main_t *im = &ip4_main; - ip_lookup_main_t *lm = &im->lookup_main; - vnet_feature_config_main_t *rx_cm = - &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; - vnet_feature_config_main_t *tx_cm = - &lm->feature_config_mains[VNET_IP_TX_FEAT]; u32 n_left_from, *from, *to_next; u32 next_index; vlib_node_runtime_t *error_node = node; @@ -434,6 +429,7 @@ ip4_source_and_port_range_check_inline (vlib_main_t * vm, udp_header_t *udp0; const protocol_port_range_dpo_t *ppr_dpo0 = NULL; const dpo_id_t *dpo; + u32 sw_if_index0; bi0 = from[0]; to_next[0] = bi0; @@ -443,28 +439,17 @@ ip4_source_and_port_range_check_inline (vlib_main_t * vm, n_left_to_next -= 1; b0 = vlib_get_buffer (vm, bi0); + sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - fib_index0 = - vec_elt (im->fib_index_by_sw_if_index, - vnet_buffer (b0)->sw_if_index[VLIB_RX]); + fib_index0 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index0); if (is_tx) vlib_buffer_advance (b0, sizeof (ethernet_header_t)); ip0 = vlib_buffer_get_current (b0); - if (is_tx) - { - c0 = vnet_get_config_data - (&tx_cm->config_main, &b0->current_config_index, - &next0, sizeof (c0[0])); - } - else - { - c0 = vnet_get_config_data - (&rx_cm->config_main, &b0->current_config_index, - &next0, sizeof (c0[0])); - } + c0 = vnet_feature_next_with_data (sw_if_index0, &next0, + b0, sizeof (c0[0])); /* we can't use the default VRF here... */ for (i = 0; i < IP_SOURCE_AND_PORT_RANGE_CHECK_N_PROTOCOLS; i++) @@ -570,7 +555,6 @@ ip4_source_and_port_range_check_inline (vlib_main_t * vm, IP4_SOURCE_AND_PORT_RANGE_CHECK_ERROR_CHECK_OK, good_packets); return frame->n_vectors; - return 0; } static uword @@ -639,15 +623,7 @@ set_ip_source_and_port_range_check (vlib_main_t * vm, u32 * fib_index, u32 sw_if_index, u32 is_add) { - ip4_main_t *im = &ip4_main; - ip_lookup_main_t *lm = &im->lookup_main; - vnet_feature_config_main_t *rx_cm = - &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; - vnet_feature_config_main_t *tx_cm = - &lm->feature_config_mains[VNET_IP_TX_FEAT]; - u32 ci; ip_source_and_port_range_check_config_t config; - u32 feature_index; int rv = 0; int i; @@ -660,36 +636,20 @@ set_ip_source_and_port_range_check (vlib_main_t * vm, if ((fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_OUT] != ~0) || (fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_OUT] != ~0)) { - feature_index = im->ip4_unicast_rx_feature_source_and_port_range_check; - - vec_validate (rx_cm->config_index_by_sw_if_index, sw_if_index); - - ci = rx_cm->config_index_by_sw_if_index[sw_if_index]; - ci = (is_add - ? vnet_config_add_feature - : vnet_config_del_feature) - (vm, &rx_cm->config_main, ci, feature_index, &config, - sizeof (config)); - rx_cm->config_index_by_sw_if_index[sw_if_index] = ci; + vnet_feature_enable_disable ("ip4-unicast", + "ip4-source-and-port-range-check-rx", + sw_if_index, is_add, &config, + sizeof (config)); } /* For IN we are in the TX path */ if ((fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_TCP_IN] != ~0) || (fib_index[IP_SOURCE_AND_PORT_RANGE_CHECK_PROTOCOL_UDP_IN] != ~0)) { - feature_index = im->ip4_unicast_tx_feature_source_and_port_range_check; - - vec_validate (tx_cm->config_index_by_sw_if_index, sw_if_index); - - ci = tx_cm->config_index_by_sw_if_index[sw_if_index]; - ci = (is_add - ? vnet_config_add_feature - : vnet_config_del_feature) - (vm, &tx_cm->config_main, ci, feature_index, &config, - sizeof (config)); - tx_cm->config_index_by_sw_if_index[sw_if_index] = ci; - - vnet_config_update_tx_feature_count (lm, tx_cm, sw_if_index, is_add); + vnet_feature_enable_disable ("ip4-output", + "ip4-source-and-port-range-check-tx", + sw_if_index, is_add, &config, + sizeof (config)); } return rv; } diff --git a/vnet/vnet/ip/ip4_source_check.c b/vnet/vnet/ip/ip4_source_check.c index 62ebcb7268a..f7900d304c2 100644 --- a/vnet/vnet/ip/ip4_source_check.c +++ b/vnet/vnet/ip/ip4_source_check.c @@ -88,9 +88,6 @@ ip4_source_check_inline (vlib_main_t * vm, vlib_frame_t * frame, ip4_source_check_type_t source_check_type) { - ip4_main_t * im = &ip4_main; - ip_lookup_main_t * lm = &im->lookup_main; - vnet_feature_config_main_t * cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; u32 n_left_from, * from, * to_next; u32 next_index; vlib_node_runtime_t * error_node = vlib_node_get_runtime (vm, ip4_input_node.index); @@ -149,14 +146,8 @@ ip4_source_check_inline (vlib_main_t * vm, ip0 = vlib_buffer_get_current (p0); ip1 = vlib_buffer_get_current (p1); - c0 = vnet_get_config_data (&cm->config_main, - &p0->current_config_index, - &next0, - sizeof (c0[0])); - c1 = vnet_get_config_data (&cm->config_main, - &p1->current_config_index, - &next1, - sizeof (c1[0])); + c0 = vnet_feature_next_with_data(vnet_buffer (p0)->sw_if_index[VLIB_RX] , &next0, p0, sizeof (c0[0])); + c1 = vnet_feature_next_with_data(vnet_buffer (p1)->sw_if_index[VLIB_RX] , &next1, p1, sizeof (c1[0])); mtrie0 = &ip4_fib_get (c0->fib_index)->mtrie; mtrie1 = &ip4_fib_get (c1->fib_index)->mtrie; @@ -228,10 +219,7 @@ ip4_source_check_inline (vlib_main_t * vm, p0 = vlib_get_buffer (vm, pi0); ip0 = vlib_buffer_get_current (p0); - c0 = vnet_get_config_data (&cm->config_main, - &p0->current_config_index, - &next0, - sizeof (c0[0])); + c0 = vnet_feature_next_with_data(vnet_buffer (p0)->sw_if_index[VLIB_RX] , &next0, p0, sizeof (c0[0])); mtrie0 = &ip4_fib_get (c0->fib_index)->mtrie; @@ -334,16 +322,13 @@ set_ip_source_check (vlib_main_t * vm, unformat_input_t _line_input, * line_input = &_line_input; vnet_main_t * vnm = vnet_get_main(); ip4_main_t * im = &ip4_main; - ip_lookup_main_t * lm = &im->lookup_main; - vnet_feature_config_main_t * rx_cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; clib_error_t * error = 0; - u32 sw_if_index, is_del, ci; + u32 sw_if_index, is_del; ip4_source_check_config_t config; - u32 feature_index; + char * feature_name = "ip4-source-check-via-rx"; sw_if_index = ~0; is_del = 0; - feature_index = im->ip4_unicast_rx_feature_source_reachable_via_rx; if (! unformat_user (input, unformat_line_input, line_input)) return 0; @@ -354,10 +339,8 @@ set_ip_source_check (vlib_main_t * vm, ; else if (unformat (line_input, "del")) is_del = 1; - else if (unformat (line_input, "strict")) - feature_index = im->ip4_unicast_rx_feature_source_reachable_via_rx; else if (unformat (line_input, "loose")) - feature_index = im->ip4_unicast_rx_feature_source_reachable_via_any; + feature_name = "ip4-source-check-via-any"; else { error = unformat_parse_error (line_input); @@ -373,17 +356,8 @@ set_ip_source_check (vlib_main_t * vm, } config.fib_index = im->fib_index_by_sw_if_index[sw_if_index]; - ci = rx_cm->config_index_by_sw_if_index[sw_if_index]; - ci = (is_del - ? vnet_config_del_feature - : vnet_config_add_feature) - (vm, &rx_cm->config_main, - ci, - feature_index, - &config, - sizeof (config)); - rx_cm->config_index_by_sw_if_index[sw_if_index] = ci; - + vnet_feature_enable_disable ("ip4-unicast", feature_name, sw_if_index, + is_del == 0, &config, sizeof (config)); done: return error; } diff --git a/vnet/vnet/ip/ip6.h b/vnet/vnet/ip/ip6.h index 8b3b9973bf4..428a16f60aa 100644 --- a/vnet/vnet/ip/ip6.h +++ b/vnet/vnet/ip/ip6.h @@ -46,7 +46,6 @@ #include <vnet/ip/ip6_packet.h> #include <vnet/ip/ip6_hop_by_hop_packet.h> #include <vnet/ip/lookup.h> -#include <vnet/feature/feature.h> #include <stdbool.h> #include <vppinfra/bihash_24_8.h> #include <vppinfra/bihash_template.h> @@ -160,30 +159,6 @@ typedef struct ip6_main_t { u32 lookup_table_nbuckets; uword lookup_table_size; - /* feature path configuration lists */ - vnet_feature_registration_t * next_feature[VNET_N_IP_FEAT]; - - /* Built-in unicast feature path indices, see vnet_feature_arc_init(...) */ - u32 ip6_unicast_rx_feature_check_access; - u32 ip6_unicast_rx_feature_policer_classify; - u32 ip6_unicast_rx_feature_flow_classify; - u32 ip6_unicast_rx_feature_ipsec; - u32 ip6_unicast_rx_feature_l2tp_decap; - u32 ip6_unicast_rx_feature_vpath; - u32 ip6_unicast_rx_feature_lookup; - u32 ip6_unicast_rx_feature_drop; - - /* Built-in multicast feature path indices */ - u32 ip6_multicast_rx_feature_drop; - u32 ip6_multicast_rx_feature_vpath; - u32 ip6_multicast_rx_feature_lookup; - - /* Built-in tx feature path index */ - u32 ip6_tx_feature_interface_output; - - /* Save results for show command */ - char ** feature_nodes[VNET_N_IP_FEAT]; - /* Seed for Jenkins hash used to compute ip6 flow hash. */ u32 flow_hash_seed; @@ -201,43 +176,6 @@ typedef struct ip6_main_t { /* Global ip6 main structure. */ extern ip6_main_t ip6_main; -#define VNET_IP6_UNICAST_FEATURE_INIT(x,...) \ - __VA_ARGS__ vnet_feature_registration_t uc_##x; \ -static void __vnet_add_feature_registration_uc_##x (void) \ - __attribute__((__constructor__)) ; \ -static void __vnet_add_feature_registration_uc_##x (void) \ -{ \ - ip6_main_t * im = &ip6_main; \ - uc_##x.next = im->next_feature[VNET_IP_RX_UNICAST_FEAT]; \ - im->next_feature[VNET_IP_RX_UNICAST_FEAT] = &uc_##x; \ -} \ -__VA_ARGS__ vnet_feature_registration_t uc_##x - -#define VNET_IP6_MULTICAST_FEATURE_INIT(x,...) \ - __VA_ARGS__ vnet_feature_registration_t mc_##x; \ -static void __vnet_add_feature_registration_mc_##x (void) \ - __attribute__((__constructor__)) ; \ -static void __vnet_add_feature_registration_mc_##x (void) \ -{ \ - ip6_main_t * im = &ip6_main; \ - mc_##x.next = im->next_feature[VNET_IP_RX_MULTICAST_FEAT]; \ - im->next_feature[VNET_IP_RX_MULTICAST_FEAT] = &mc_##x; \ -} \ -__VA_ARGS__ vnet_feature_registration_t mc_##x - -#define VNET_IP6_TX_FEATURE_INIT(x,...) \ - __VA_ARGS__ vnet_feature_registration_t tx_##x; \ -static void __vnet_add_feature_registration_tx_##x (void) \ - __attribute__((__constructor__)) ; \ -static void __vnet_add_feature_registration_tx_##x (void) \ -{ \ - ip6_main_t * im = &ip6_main; \ - tx_##x.next = im->next_feature[VNET_IP_TX_FEAT]; \ - im->next_feature[VNET_IP_TX_FEAT] = &tx_##x; \ -} \ -__VA_ARGS__ vnet_feature_registration_t tx_##x - - /* Global ip6 input node. Errors get attached to ip6 input node. */ extern vlib_node_registration_t ip6_input_node; extern vlib_node_registration_t ip6_rewrite_node; diff --git a/vnet/vnet/ip/ip6_forward.c b/vnet/vnet/ip/ip6_forward.c index 53d13db2be3..899203c84b3 100644 --- a/vnet/vnet/ip/ip6_forward.c +++ b/vnet/vnet/ip/ip6_forward.c @@ -412,11 +412,7 @@ void ip6_sw_interface_enable_disable (u32 sw_if_index, u32 is_enable) { - vlib_main_t * vm = vlib_get_main(); ip6_main_t * im = &ip6_main; - ip_lookup_main_t * lm = &im->lookup_main; - u32 ci, cast; - u32 lookup_feature_index; vec_validate_init_empty (im->ip_enabled_by_sw_if_index, sw_if_index, 0); @@ -435,34 +431,12 @@ ip6_sw_interface_enable_disable (u32 sw_if_index, return; } - for (cast = 0; cast <= VNET_IP_RX_MULTICAST_FEAT; cast++) - { - vnet_feature_config_main_t * cm = &lm->feature_config_mains[cast]; - vnet_config_main_t * vcm = &cm->config_main; + vnet_feature_enable_disable ("ip6-unicast", "ip6-lookup", sw_if_index, + is_enable, 0, 0); - 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]; - - if (cast == VNET_IP_RX_UNICAST_FEAT) - lookup_feature_index = im->ip6_unicast_rx_feature_lookup; - else - lookup_feature_index = im->ip6_multicast_rx_feature_lookup; - - if (is_enable) - ci = vnet_config_add_feature (vm, vcm, - ci, - lookup_feature_index, - /* config data */ 0, - /* # bytes of config data */ 0); - else - ci = vnet_config_del_feature (vm, vcm, - ci, - lookup_feature_index, - /* config data */ 0, - /* # bytes of config data */ 0); + vnet_feature_enable_disable ("ip6-multicast", "ip6-lookup", sw_if_index, + is_enable, 0, 0); - cm->config_index_by_sw_if_index[sw_if_index] = ci; - } } /* get first interface address */ @@ -584,172 +558,115 @@ ip6_sw_interface_admin_up_down (vnet_main_t * vnm, VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ip6_sw_interface_admin_up_down); /* Built-in ip6 unicast rx feature path definition */ -VNET_IP6_UNICAST_FEATURE_INIT (ip6_flow_classify, static) = { +VNET_FEATURE_ARC_INIT (ip6_unicast, static) = +{ + .arc_name = "ip6-unicast", + .start_nodes = VNET_FEATURES ("ip6-input"), + .arc_index_ptr = &ip6_main.lookup_main.ucast_feature_arc_index, +}; + +VNET_FEATURE_INIT (ip6_flow_classify, static) = { + .arc_name = "ip6-unicast", .node_name = "ip6-flow-classify", - .runs_before = ORDER_CONSTRAINTS {"ip6-inacl", 0}, - .feature_index = &ip6_main.ip6_unicast_rx_feature_flow_classify, + .runs_before = VNET_FEATURES ("ip6-inacl"), }; -VNET_IP6_UNICAST_FEATURE_INIT (ip6_inacl, static) = { +VNET_FEATURE_INIT (ip6_inacl, static) = { + .arc_name = "ip6-unicast", .node_name = "ip6-inacl", - .runs_before = ORDER_CONSTRAINTS {"ip6-policer-classify", 0}, - .feature_index = &ip6_main.ip6_unicast_rx_feature_check_access, + .runs_before = VNET_FEATURES ("ip6-policer-classify"), }; -VNET_IP6_UNICAST_FEATURE_INIT (ip6_policer_classify, static) = { +VNET_FEATURE_INIT (ip6_policer_classify, static) = { + .arc_name = "ip6-unicast", .node_name = "ip6-policer-classify", - .runs_before = ORDER_CONSTRAINTS {"ipsec-input-ip6", 0}, - .feature_index = &ip6_main.ip6_unicast_rx_feature_policer_classify, + .runs_before = VNET_FEATURES ("ipsec-input-ip6"), }; -VNET_IP6_UNICAST_FEATURE_INIT (ip6_ipsec, static) = { +VNET_FEATURE_INIT (ip6_ipsec, static) = { + .arc_name = "ip6-unicast", .node_name = "ipsec-input-ip6", - .runs_before = ORDER_CONSTRAINTS {"l2tp-decap", 0}, - .feature_index = &ip6_main.ip6_unicast_rx_feature_ipsec, + .runs_before = VNET_FEATURES ("l2tp-decap"), }; -VNET_IP6_UNICAST_FEATURE_INIT (ip6_l2tp, static) = { +VNET_FEATURE_INIT (ip6_l2tp, static) = { + .arc_name = "ip6-unicast", .node_name = "l2tp-decap", - .runs_before = ORDER_CONSTRAINTS {"vpath-input-ip6", 0}, - .feature_index = &ip6_main.ip6_unicast_rx_feature_l2tp_decap, + .runs_before = VNET_FEATURES ("vpath-input-ip6"), }; -VNET_IP6_UNICAST_FEATURE_INIT (ip6_vpath, static) = { +VNET_FEATURE_INIT (ip6_vpath, static) = { + .arc_name = "ip6-unicast", .node_name = "vpath-input-ip6", - .runs_before = ORDER_CONSTRAINTS {"ip6-lookup", 0}, - .feature_index = &ip6_main.ip6_unicast_rx_feature_vpath, + .runs_before = VNET_FEATURES ("ip6-lookup"), }; -VNET_IP6_UNICAST_FEATURE_INIT (ip6_lookup, static) = { +VNET_FEATURE_INIT (ip6_lookup, static) = { + .arc_name = "ip6-unicast", .node_name = "ip6-lookup", - .runs_before = ORDER_CONSTRAINTS {"ip6-drop", 0}, - .feature_index = &ip6_main.ip6_unicast_rx_feature_lookup, + .runs_before = VNET_FEATURES ("ip6-drop"), }; -VNET_IP6_UNICAST_FEATURE_INIT (ip6_drop, static) = { +VNET_FEATURE_INIT (ip6_drop, static) = { + .arc_name = "ip6-unicast", .node_name = "ip6-drop", .runs_before = 0, /*last feature*/ - .feature_index = &ip6_main.ip6_unicast_rx_feature_drop, }; /* Built-in ip6 multicast rx feature path definition (none now) */ -VNET_IP6_MULTICAST_FEATURE_INIT (ip6_vpath_mc, static) = { +VNET_FEATURE_ARC_INIT (ip6_multicast, static) = +{ + .arc_name = "ip6-multicast", + .start_nodes = VNET_FEATURES ("ip6-input"), + .arc_index_ptr = &ip6_main.lookup_main.mcast_feature_arc_index, +}; + +VNET_FEATURE_INIT (ip6_vpath_mc, static) = { + .arc_name = "ip6-multicast", .node_name = "vpath-input-ip6", - .runs_before = ORDER_CONSTRAINTS {"ip6-lookup", 0}, - .feature_index = &ip6_main.ip6_multicast_rx_feature_vpath, + .runs_before = VNET_FEATURES ("ip6-lookup"), }; -VNET_IP6_MULTICAST_FEATURE_INIT (ip6_lookup, static) = { +VNET_FEATURE_INIT (ip6_mc_lookup, static) = { + .arc_name = "ip6-multicast", .node_name = "ip6-lookup", - .runs_before = ORDER_CONSTRAINTS {"ip6-drop", 0}, - .feature_index = &ip6_main.ip6_multicast_rx_feature_lookup, + .runs_before = VNET_FEATURES ("ip6-drop"), }; -VNET_IP6_MULTICAST_FEATURE_INIT (ip6_drop_mc, static) = { +VNET_FEATURE_INIT (ip6_drop_mc, static) = { + .arc_name = "ip6-multicast", .node_name = "ip6-drop", .runs_before = 0, /* last feature */ - .feature_index = &ip6_main.ip6_multicast_rx_feature_drop, }; -static char * rx_feature_start_nodes[] = - {"ip6-input"}; - -static char * tx_feature_start_nodes[] = +/* Built-in ip4 tx feature path definition */ +VNET_FEATURE_ARC_INIT (ip6_output, static) = { - "ip6-rewrite", - "ip6-midchain", + .arc_name = "ip6-output", + .start_nodes = VNET_FEATURES ("ip6-rewrite", "ip6-midchain"), + .arc_index_ptr = &ip6_main.lookup_main.output_feature_arc_index, }; -/* Built-in ip4 tx feature path definition */ -VNET_IP6_TX_FEATURE_INIT (interface_output, static) = { +VNET_FEATURE_INIT (ip6_interface_output, static) = { + .arc_name = "ip6-output", .node_name = "interface-output", .runs_before = 0, /* not before any other features */ - .feature_index = &ip6_main.ip6_tx_feature_interface_output, }; -static clib_error_t * -ip6_feature_init (vlib_main_t * vm, ip6_main_t * im) -{ - ip_lookup_main_t * lm = &im->lookup_main; - clib_error_t * error; - vnet_cast_t cast; - vnet_feature_config_main_t * cm; - vnet_config_main_t * vcm; - char **feature_start_nodes; - int feature_start_len; - - for (cast = 0; cast < VNET_N_IP_FEAT; cast++) - { - cm = &lm->feature_config_mains[cast]; - vcm = &cm->config_main; - - if (cast < VNET_IP_TX_FEAT) - { - feature_start_nodes = rx_feature_start_nodes; - feature_start_len = ARRAY_LEN(rx_feature_start_nodes); - } - else - { - feature_start_nodes = tx_feature_start_nodes; - feature_start_len = ARRAY_LEN(tx_feature_start_nodes); - } - - if ((error = vnet_feature_arc_init (vm, vcm, - feature_start_nodes, - feature_start_len, - im->next_feature[cast], - &im->feature_nodes[cast]))) - return error; - } - return 0; -} - clib_error_t * ip6_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add) { - vlib_main_t * vm = vnm->vlib_main; - ip6_main_t * im = &ip6_main; - ip_lookup_main_t * lm = &im->lookup_main; - u32 ci, cast; - u32 feature_index; + vnet_feature_enable_disable ("ip6-unicast", "ip6-drop", sw_if_index, + is_add, 0, 0); - for (cast = 0; cast < VNET_N_IP_FEAT; cast++) - { - vnet_feature_config_main_t * cm = &lm->feature_config_mains[cast]; - vnet_config_main_t * vcm = &cm->config_main; + vnet_feature_enable_disable ("ip6-multicast", "ip6-drop", sw_if_index, + is_add, 0, 0); - 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]; + vnet_feature_enable_disable ("ip6-output", "interface-output", sw_if_index, + is_add, 0, 0); - if (cast == VNET_IP_RX_UNICAST_FEAT) - feature_index = im->ip6_unicast_rx_feature_drop; - else if (cast == VNET_IP_RX_MULTICAST_FEAT) - feature_index = im->ip6_multicast_rx_feature_drop; - else - feature_index = im->ip6_tx_feature_interface_output; - - if (is_add) - ci = vnet_config_add_feature (vm, vcm, - ci, - feature_index, - /* config data */ 0, - /* # bytes of config data */ 0); - else - { - ci = vnet_config_del_feature (vm, vcm, ci, - feature_index, - /* config data */ 0, - /* # bytes of config data */ 0); - if (vec_len(im->ip_enabled_by_sw_if_index) > sw_if_index) - im->ip_enabled_by_sw_if_index[sw_if_index] = 0; - } - cm->config_index_by_sw_if_index[sw_if_index] = ci; - /* - * note: do not update the tx feature count here. - */ - } return /* no error */ 0; } @@ -1835,7 +1752,6 @@ ip6_rewrite_inline (vlib_main_t * vm, u32 n_left_from, n_left_to_next, * to_next, next_index; vlib_node_runtime_t * error_node = vlib_node_get_runtime (vm, ip6_input_node.index); vlib_rx_or_tx_t adj_rx_tx = rewrite_for_locally_received_packets ? VLIB_RX : VLIB_TX; - vnet_feature_config_main_t * cm = &lm->feature_config_mains[VNET_IP_TX_FEAT]; n_left_from = frame->n_vectors; next_index = node->cached_next_index; @@ -1969,18 +1885,8 @@ ip6_rewrite_inline (vlib_main_t * vm, tx_sw_if_index0; next0 = adj0[0].rewrite_header.next_index; - if (PREDICT_FALSE - (clib_bitmap_get (lm->tx_sw_if_has_ip_output_features, - tx_sw_if_index0))) - { - p0->current_config_index = - vec_elt (cm->config_index_by_sw_if_index, - tx_sw_if_index0); - vnet_get_config_data (&cm->config_main, - &p0->current_config_index, - &next0, - /* # bytes of config data */ 0); - } + vnet_feature_arc_start(lm->output_feature_arc_index, + tx_sw_if_index0, &next0, p0); } if (PREDICT_TRUE(error1 == IP6_ERROR_NONE)) { @@ -1992,18 +1898,8 @@ ip6_rewrite_inline (vlib_main_t * vm, tx_sw_if_index1; next1 = adj1[0].rewrite_header.next_index; - if (PREDICT_FALSE - (clib_bitmap_get (lm->tx_sw_if_has_ip_output_features, - tx_sw_if_index1))) - { - p1->current_config_index = - vec_elt (cm->config_index_by_sw_if_index, - tx_sw_if_index1); - vnet_get_config_data (&cm->config_main, - &p1->current_config_index, - &next1, - /* # bytes of config data */ 0); - } + vnet_feature_arc_start(lm->output_feature_arc_index, + tx_sw_if_index1, &next1, p1); } /* Guess we are only writing on simple Ethernet header. */ @@ -2102,18 +1998,8 @@ ip6_rewrite_inline (vlib_main_t * vm, vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0; next0 = adj0[0].rewrite_header.next_index; - if (PREDICT_FALSE - (clib_bitmap_get (lm->tx_sw_if_has_ip_output_features, - tx_sw_if_index0))) - { - p0->current_config_index = - vec_elt (cm->config_index_by_sw_if_index, - tx_sw_if_index0); - vnet_get_config_data (&cm->config_main, - &p0->current_config_index, - &next0, - /* # bytes of config data */ 0); - } + vnet_feature_arc_start(lm->output_feature_arc_index, + tx_sw_if_index0, &next0, p0); } if (is_midchain) @@ -2661,6 +2547,9 @@ ip6_lookup_init (vlib_main_t * vm) clib_error_t * error; uword i; + if ((error = vlib_call_init_function (vm, vnet_feature_init))) + return error; + for (i = 0; i < ARRAY_LEN (im->fib_masks); i++) { u32 j, i0, i1; @@ -2730,8 +2619,6 @@ ip6_lookup_init (vlib_main_t * vm) "ip6 neighbor discovery"); } - error = ip6_feature_init (vm, im); - return error; } @@ -3209,58 +3096,3 @@ ip6_config (vlib_main_t * vm, unformat_input_t * input) } VLIB_EARLY_CONFIG_FUNCTION (ip6_config, "ip6"); - -#define TEST_CODE 1 -#if TEST_CODE > 0 - -static clib_error_t * -set_interface_ip6_output_feature_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - vnet_main_t * vnm = vnet_get_main(); - u32 sw_if_index = ~0; - int is_add = 1; - ip6_main_t * im = &ip6_main; - ip_lookup_main_t * lm = &im->lookup_main; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index)) - ; - else if (unformat (input, "del")) - is_add = 0; - else - break; - } - - if (sw_if_index == ~0) - return clib_error_return (0, "unknown interface `%U'", - format_unformat_error, input); - - lm->tx_sw_if_has_ip_output_features = - clib_bitmap_set (lm->tx_sw_if_has_ip_output_features, sw_if_index, is_add); - - return 0; -} - -/*? - * Enable or disable the output feature on an interface. - * - * @todo Need a more detailed description. - * - * @cliexpar - * Example of how to enable the output feature on an interface: - * @cliexcmd{set interface ip6 output feature GigabitEthernet2/0/0} - * Example of how to disable the output feature on an interface: - * @cliexcmd{set interface ip6 output feature GigabitEthernet2/0/0 del} -?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (set_interface_ip6_output_feature, static) = { - .path = "set interface ip6 output feature", - .function = set_interface_ip6_output_feature_command_fn, - .short_help = "set interface ip6 output feature <interface> [del]", -}; -/* *INDENT-ON* */ - -#endif /* TEST_CODE */ diff --git a/vnet/vnet/ip/ip6_input.c b/vnet/vnet/ip/ip6_input.c index a355abfdb39..f6d56be2829 100644 --- a/vnet/vnet/ip/ip6_input.c +++ b/vnet/vnet/ip/ip6_input.c @@ -105,10 +105,9 @@ ip6_input (vlib_main_t * vm, { vlib_buffer_t * p0, * p1; ip6_header_t * ip0, * ip1; - vnet_feature_config_main_t * cm0, * cm1; - u32 pi0, sw_if_index0, next0; - u32 pi1, sw_if_index1, next1; - u8 error0, error1, cast0, cast1; + u32 pi0, sw_if_index0, next0 = 0; + u32 pi1, sw_if_index1, next1 = 0; + u8 error0, error1, arc0, arc1; /* Prefetch next iteration. */ { @@ -143,26 +142,14 @@ ip6_input (vlib_main_t * vm, sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX]; sw_if_index1 = vnet_buffer (p1)->sw_if_index[VLIB_RX]; - cast0 = ip6_address_is_multicast (&ip0->dst_address) ? VNET_IP_RX_MULTICAST_FEAT : VNET_IP_RX_UNICAST_FEAT; - cast1 = ip6_address_is_multicast (&ip1->dst_address) ? VNET_IP_RX_MULTICAST_FEAT : VNET_IP_RX_UNICAST_FEAT; - - cm0 = lm->feature_config_mains + cast0; - cm1 = lm->feature_config_mains + cast1; - - p0->current_config_index = vec_elt (cm0->config_index_by_sw_if_index, sw_if_index0); - p1->current_config_index = vec_elt (cm1->config_index_by_sw_if_index, sw_if_index1); + arc0 = ip6_address_is_multicast (&ip0->dst_address) ? lm->mcast_feature_arc_index : lm->ucast_feature_arc_index; + arc1 = ip6_address_is_multicast (&ip1->dst_address) ? lm->mcast_feature_arc_index : lm->ucast_feature_arc_index; vnet_buffer (p0)->ip.adj_index[VLIB_RX] = ~0; vnet_buffer (p1)->ip.adj_index[VLIB_RX] = ~0; - vnet_get_config_data (&cm0->config_main, - &p0->current_config_index, - &next0, - /* # bytes of config data */ 0); - vnet_get_config_data (&cm1->config_main, - &p1->current_config_index, - &next1, - /* # bytes of config data */ 0); + vnet_feature_arc_start (arc0, sw_if_index0, &next0, p0); + vnet_feature_arc_start (arc1, sw_if_index1, &next1, p1); vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1); vlib_increment_simple_counter (cm, cpu_index, sw_if_index1, 1); @@ -217,9 +204,8 @@ ip6_input (vlib_main_t * vm, { vlib_buffer_t * p0; ip6_header_t * ip0; - vnet_feature_config_main_t * cm0; - u32 pi0, sw_if_index0, next0; - u8 error0, cast0; + u32 pi0, sw_if_index0, next0 = 0; + u8 error0, arc0; pi0 = from[0]; to_next[0] = pi0; @@ -232,15 +218,9 @@ ip6_input (vlib_main_t * vm, ip0 = vlib_buffer_get_current (p0); sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX]; - cast0 = ip6_address_is_multicast (&ip0->dst_address) ? VNET_IP_RX_MULTICAST_FEAT : VNET_IP_RX_UNICAST_FEAT; - cm0 = lm->feature_config_mains + cast0; - p0->current_config_index = vec_elt (cm0->config_index_by_sw_if_index, sw_if_index0); + arc0 = ip6_address_is_multicast (&ip0->dst_address) ? lm->mcast_feature_arc_index : lm->ucast_feature_arc_index; vnet_buffer (p0)->ip.adj_index[VLIB_RX] = ~0; - - vnet_get_config_data (&cm0->config_main, - &p0->current_config_index, - &next0, - /* # bytes of config data */ 0); + vnet_feature_arc_start (arc0, sw_if_index0, &next0, p0); vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1); error0 = IP6_ERROR_NONE; diff --git a/vnet/vnet/ip/ip_init.c b/vnet/vnet/ip/ip_init.c index c89f60c09d7..d87a92efdc6 100644 --- a/vnet/vnet/ip/ip_init.c +++ b/vnet/vnet/ip/ip_init.c @@ -144,24 +144,3 @@ do { \ VLIB_INIT_FUNCTION (ip_main_init); -void -vnet_config_update_tx_feature_count (ip_lookup_main_t * lm, - vnet_feature_config_main_t * tx_cm, - u32 sw_if_index, - int is_add) -{ - ASSERT (tx_cm == &lm->feature_config_mains[VNET_IP_TX_FEAT]); - - vec_validate (lm->tx_feature_count_by_sw_if_index, sw_if_index); - - lm->tx_feature_count_by_sw_if_index[sw_if_index] += is_add ? 1 : -1; - - ASSERT (lm->tx_feature_count_by_sw_if_index[sw_if_index] >= 0); - - lm->tx_sw_if_has_ip_output_features = - clib_bitmap_set (lm->tx_sw_if_has_ip_output_features, sw_if_index, - lm->tx_feature_count_by_sw_if_index[sw_if_index] > 0); -} - - - diff --git a/vnet/vnet/ip/lookup.h b/vnet/vnet/ip/lookup.h index 239ca6818be..7f9b9846cd9 100644 --- a/vnet/vnet/ip/lookup.h +++ b/vnet/vnet/ip/lookup.h @@ -337,12 +337,6 @@ typedef struct ip_lookup_main_t { /** load-balance packet/byte counters indexed by LB index. */ vlib_combined_counter_main_t load_balance_counters; - /** any-tx-feature-enabled interface bitmap */ - uword * tx_sw_if_has_ip_output_features; - - /** count of enabled features, per sw_if_index, to maintain bitmap */ - i16 * tx_feature_count_by_sw_if_index; - /** Pool of addresses that are assigned to interfaces. */ ip_interface_address_t * if_address_pool; @@ -356,8 +350,10 @@ typedef struct ip_lookup_main_t { /** First table index to use for this interface, ~0 => none */ u32 * classify_table_index_by_sw_if_index; - /** rx unicast, multicast, tx interface/feature configuration. */ - vnet_feature_config_main_t feature_config_mains[VNET_N_IP_FEAT]; + /** Feature arc indices */ + u8 mcast_feature_arc_index; + u8 ucast_feature_arc_index; + u8 output_feature_arc_index; /** Number of bytes in a fib result. Must be at least sizeof (uword). First word is always adjacency index. */ diff --git a/vnet/vnet/ipsec/ipsec.c b/vnet/vnet/ipsec/ipsec.c index 3f2bad9fc1f..7d459f6b1ab 100644 --- a/vnet/vnet/ipsec/ipsec.c +++ b/vnet/vnet/ipsec/ipsec.c @@ -40,11 +40,9 @@ ipsec_set_interface_spd (vlib_main_t * vm, u32 sw_if_index, u32 spd_id, int is_add) { ipsec_main_t *im = &ipsec_main; - ip_lookup_main_t *lm; - vnet_feature_config_main_t *rx_cm; ip4_ipsec_config_t config; - u32 spd_index, ci; + u32 spd_index; uword *p; p = hash_get (im->spd_index_by_spd_id, spd_id); @@ -74,29 +72,10 @@ ipsec_set_interface_spd (vlib_main_t * vm, u32 sw_if_index, u32 spd_id, INTF_OUTPUT_FEAT_IPSEC, is_add); /* enable IPsec on RX */ - config.spd_index = spd_index; - - /* IPv4 */ - lm = &ip4_main.lookup_main; - rx_cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; - - ci = rx_cm->config_index_by_sw_if_index[sw_if_index]; - - ci = (is_add ? vnet_config_add_feature : vnet_config_del_feature) - (vm, &rx_cm->config_main, - ci, ip4_main.ip4_unicast_rx_feature_ipsec, &config, sizeof (config)); - rx_cm->config_index_by_sw_if_index[sw_if_index] = ci; - - /* IPv6 */ - lm = &ip6_main.lookup_main; - rx_cm = &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; - - ci = rx_cm->config_index_by_sw_if_index[sw_if_index]; - - ci = (is_add ? vnet_config_add_feature : vnet_config_del_feature) - (vm, &rx_cm->config_main, - ci, ip6_main.ip6_unicast_rx_feature_ipsec, &config, sizeof (config)); - rx_cm->config_index_by_sw_if_index[sw_if_index] = ci; + vnet_feature_enable_disable ("ip4-unicast", "ipsec-input-ip4", sw_if_index, + is_add, &config, sizeof (config)); + vnet_feature_enable_disable ("ip6-unicast", "ipsec-input-ip6", sw_if_index, + is_add, &config, sizeof (config)); return 0; } diff --git a/vnet/vnet/ipsec/ipsec_input.c b/vnet/vnet/ipsec/ipsec_input.c index 8b75c1255a7..809fe6da65d 100644 --- a/vnet/vnet/ipsec/ipsec_input.c +++ b/vnet/vnet/ipsec/ipsec_input.c @@ -18,6 +18,7 @@ #include <vnet/vnet.h> #include <vnet/api_errno.h> #include <vnet/ip/ip.h> +#include <vnet/feature/feature.h> #include <vnet/ipsec/ipsec.h> #include <vnet/ipsec/esp.h> @@ -187,10 +188,6 @@ ipsec_input_ip4_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) { - ip4_main_t *i4m = &ip4_main; - ip_lookup_main_t *lm = &i4m->lookup_main; - vnet_feature_config_main_t *cm = - &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; u32 n_left_from, *from, next_index, *to_next; ipsec_main_t *im = &ipsec_main; @@ -222,9 +219,10 @@ ipsec_input_ip4_node_fn (vlib_main_t * vm, n_left_to_next -= 1; b0 = vlib_get_buffer (vm, bi0); - c0 = vnet_get_config_data (&cm->config_main, - &b0->current_config_index, - &next0, sizeof (c0[0])); + c0 = + vnet_feature_next_with_data (vnet_buffer (b0)->sw_if_index + [VLIB_RX], &next0, b0, + sizeof (c0[0])); spd0 = pool_elt_at_index (im->spds, c0->spd_index); @@ -323,10 +321,6 @@ VLIB_NODE_FUNCTION_MULTIARCH (ipsec_input_ip4_node, ipsec_input_ip4_node_fn) vlib_node_runtime_t * node, vlib_frame_t * from_frame) { - ip6_main_t *i6m = &ip6_main; - ip_lookup_main_t *lm = &i6m->lookup_main; - vnet_feature_config_main_t *cm = - &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; u32 n_left_from, *from, next_index, *to_next; ipsec_main_t *im = &ipsec_main; @@ -359,9 +353,10 @@ VLIB_NODE_FUNCTION_MULTIARCH (ipsec_input_ip4_node, ipsec_input_ip4_node_fn) n_left_to_next -= 1; b0 = vlib_get_buffer (vm, bi0); - c0 = vnet_get_config_data (&cm->config_main, - &b0->current_config_index, - &next0, sizeof (c0[0])); + c0 = + vnet_feature_next_with_data (vnet_buffer (b0)->sw_if_index + [VLIB_RX], &next0, b0, + sizeof (c0[0])); spd0 = pool_elt_at_index (im->spds, c0->spd_index); diff --git a/vnet/vnet/l2tp/decap.c b/vnet/vnet/l2tp/decap.c index e041fdf2cd4..e91e6fbb96f 100644 --- a/vnet/vnet/l2tp/decap.c +++ b/vnet/vnet/l2tp/decap.c @@ -218,15 +218,7 @@ done: else { /* Go to next node on the ip6 configuration chain */ - ip6_main_t *im = &ip6_main; - ip_lookup_main_t *lm = &im->lookup_main; - vnet_feature_config_main_t *cm = - &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; - ip6_l2tpv3_config_t *c0; - - vnet_get_config_data (&cm->config_main, - &b->current_config_index, - &next_index, sizeof (c0[0])); + vnet_feature_next (session->sw_if_index, &next_index, b); } } diff --git a/vnet/vnet/l2tp/l2tp.c b/vnet/vnet/l2tp/l2tp.c index c6da86607e3..a4531dab85c 100644 --- a/vnet/vnet/l2tp/l2tp.c +++ b/vnet/vnet/l2tp/l2tp.c @@ -600,26 +600,12 @@ int l2tpv3_interface_enable_disable (vnet_main_t * vnm, u32 sw_if_index, int enable_disable) { - ip6_main_t *im = &ip6_main; - ip_lookup_main_t *lm = &im->lookup_main; - vnet_feature_config_main_t *rx_cm = - &lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; - u32 ci; - ip6_l2tpv3_config_t config; - u32 feature_index; if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index)) return VNET_API_ERROR_INVALID_SW_IF_INDEX; - feature_index = im->ip6_unicast_rx_feature_l2tp_decap; - - ci = rx_cm->config_index_by_sw_if_index[sw_if_index]; - ci = (enable_disable - ? vnet_config_add_feature - : vnet_config_del_feature) - (vlib_get_main (), &rx_cm->config_main, - ci, feature_index, &config, sizeof (config)); - rx_cm->config_index_by_sw_if_index[sw_if_index] = ci; + vnet_feature_enable_disable ("ip6-unicast", "l2tp-decap", sw_if_index, + enable_disable, 0, 0); return 0; } diff --git a/vnet/vnet/mpls/interface.c b/vnet/vnet/mpls/interface.c index 9fd93ff8701..a0f6f2f2474 100644 --- a/vnet/vnet/mpls/interface.c +++ b/vnet/vnet/mpls/interface.c @@ -276,12 +276,7 @@ mpls_sw_interface_enable_disable (mpls_main_t * mm, u32 sw_if_index, u8 is_enable) { - vlib_main_t * vm = vlib_get_main(); - vnet_feature_config_main_t * cm = &mm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; - vnet_config_main_t * vcm = &cm->config_main; - u32 lookup_feature_index; fib_node_index_t lfib_index; - u32 ci; vec_validate_init_empty (mm->mpls_enabled_by_sw_if_index, sw_if_index, 0); @@ -308,24 +303,9 @@ mpls_sw_interface_enable_disable (mpls_main_t * mm, FIB_PROTOCOL_MPLS); } - 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]; + vnet_feature_enable_disable ("mpls-input", "mpls-lookup", sw_if_index, + is_enable, 0, 0); - lookup_feature_index = mm->mpls_rx_feature_lookup; - - if (is_enable) - ci = vnet_config_add_feature (vm, vcm, - ci, - lookup_feature_index, - /* config data */ 0, - /* # bytes of config data */ 0); - else - ci = vnet_config_del_feature (vm, vcm, ci, - lookup_feature_index, - /* config data */ 0, - /* # bytes of config data */ 0); - - cm->config_index_by_sw_if_index[sw_if_index] = ci; } u8 * format_mpls_encap_index (u8 * s, va_list * args) diff --git a/vnet/vnet/mpls/mpls.h b/vnet/vnet/mpls/mpls.h index 85973d862dc..59fc761ea2c 100644 --- a/vnet/vnet/mpls/mpls.h +++ b/vnet/vnet/mpls/mpls.h @@ -94,14 +94,6 @@ typedef struct { /** A hash table to lookup the mpls_fib by table ID */ uword *fib_index_by_table_id; - /* rx/tx interface/feature configuration. */ - vnet_feature_config_main_t feature_config_mains[VNET_N_IP_FEAT]; - - /* Built-in unicast feature path indices, see vnet_feature_arc_init(...) */ - u32 mpls_rx_feature_lookup; - u32 mpls_rx_feature_not_enabled; - u32 mpls_tx_feature_interface_output; - /* pool of ethernet tunnel instances */ mpls_eth_tunnel_t *eth_tunnels; u32 * free_eth_sw_if_indices; @@ -114,11 +106,9 @@ typedef struct { u32 ip4_classify_mpls_policy_encap_next_index; u32 ip6_classify_mpls_policy_encap_next_index; - /* feature path configuration lists */ - vnet_feature_registration_t * next_feature[VNET_N_IP_FEAT]; - - /* Save feature results for show command */ - char **feature_nodes[VNET_N_IP_FEAT]; + /* Feature arc indices */ + u8 input_feature_arc_index; + u8 output_feature_arc_index; /* IP4 enabled count by software interface */ u8 * mpls_enabled_by_sw_if_index; @@ -130,30 +120,6 @@ typedef struct { extern mpls_main_t mpls_main; -#define VNET_MPLS_FEATURE_INIT(x,...) \ - __VA_ARGS__ vnet_feature_registration_t uc_##x; \ -static void __vnet_add_feature_registration_uc_##x (void) \ - __attribute__((__constructor__)) ; \ -static void __vnet_add_feature_registration_uc_##x (void) \ -{ \ - mpls_main_t * mm = &mpls_main; \ - uc_##x.next = mm->next_feature[VNET_IP_RX_UNICAST_FEAT]; \ - mm->next_feature[VNET_IP_RX_UNICAST_FEAT] = &uc_##x; \ -} \ -__VA_ARGS__ vnet_feature_registration_t uc_##x - -#define VNET_MPLS_TX_FEATURE_INIT(x,...) \ - __VA_ARGS__ vnet_feature_registration_t tx_##x; \ -static void __vnet_add_feature_registration_tx_##x (void) \ - __attribute__((__constructor__)) ; \ -static void __vnet_add_feature_registration_tx_##x (void) \ -{ \ - mpls_main_t * mm = &mpls_main; \ - tx_##x.next = mm->next_feature[VNET_IP_TX_FEAT]; \ - mm->next_feature[VNET_IP_TX_FEAT] = &tx_##x; \ -} \ -__VA_ARGS__ vnet_feature_registration_t tx_##x - extern clib_error_t * mpls_feature_init(vlib_main_t * vm); format_function_t format_mpls_protocol; diff --git a/vnet/vnet/mpls/mpls_features.c b/vnet/vnet/mpls/mpls_features.c index 2f98867cf90..a7593c55b09 100644 --- a/vnet/vnet/mpls/mpls_features.c +++ b/vnet/vnet/mpls/mpls_features.c @@ -100,116 +100,57 @@ VLIB_REGISTER_NODE (mpls_not_enabled_node) = { VLIB_NODE_FUNCTION_MULTIARCH (mpls_not_enabled_node, mpls_not_enabled) -VNET_MPLS_FEATURE_INIT (mpls_lookup, static) = { +VNET_FEATURE_ARC_INIT (mpls_input, static) = +{ + .arc_name = "mpls-input", + .start_nodes = VNET_FEATURES ("mpls-input"), + .arc_index_ptr = &mpls_main.input_feature_arc_index, +}; + +VNET_FEATURE_INIT (mpls_lookup, static) = { + .arc_name = "mpls-input", .node_name = "mpls-lookup", - .runs_before = ORDER_CONSTRAINTS {"mpls-not-enabled", 0}, - .feature_index = &mpls_main.mpls_rx_feature_lookup, + .runs_before = VNET_FEATURES ("mpls-not-enabled"), }; -VNET_MPLS_FEATURE_INIT (mpls_not_enabled, static) = { +VNET_FEATURE_INIT (mpls_not_enabled, static) = { + .arc_name = "mpls-input", .node_name = "mpls-not-enabled", - .runs_before = ORDER_CONSTRAINTS {0}, /* not before any other features */ - .feature_index = &mpls_main.mpls_rx_feature_not_enabled, + .runs_before = VNET_FEATURES (0), /* not before any other features */ +}; + +VNET_FEATURE_ARC_INIT (mpls_output, static) = +{ + .arc_name = "mpls-output", + .start_nodes = VNET_FEATURES ("mpls-output", "mpls-midchain"), + .arc_index_ptr = &mpls_main.output_feature_arc_index, }; /* Built-in ip4 tx feature path definition */ -VNET_MPLS_TX_FEATURE_INIT (interface_output, static) = { +VNET_FEATURE_INIT (mpls_interface_output, static) = { + .arc_name = "mpls-output", .node_name = "interface-output", .runs_before = 0, /* not before any other features */ - .feature_index = &mpls_main.mpls_tx_feature_interface_output, }; - -static char * rx_feature_start_nodes[] = -{ - "mpls-input", -}; -static char * tx_feature_start_nodes[] = -{ - "mpls-output", - "mpls-midchain", -}; - -clib_error_t * -mpls_feature_init (vlib_main_t * vm) -{ - vnet_feature_config_main_t * cm = &mpls_main.feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; - vnet_config_main_t * vcm = &cm->config_main; - clib_error_t *error; - - error = vnet_feature_arc_init - (vm, vcm, rx_feature_start_nodes, - ARRAY_LEN(rx_feature_start_nodes), - mpls_main.next_feature[VNET_IP_RX_UNICAST_FEAT], - &mpls_main.feature_nodes[VNET_IP_RX_UNICAST_FEAT]); - - if (error) - return error; - - cm = &mpls_main.feature_config_mains[VNET_IP_TX_FEAT]; - vcm = &cm->config_main; - - error = vnet_feature_arc_init - (vm, vcm, - tx_feature_start_nodes, - ARRAY_LEN(tx_feature_start_nodes), - mpls_main.next_feature[VNET_IP_TX_FEAT], - &mpls_main.feature_nodes[VNET_IP_TX_FEAT]); - - return error; -} - static clib_error_t * mpls_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add) { - vlib_main_t * vm = vnm->vlib_main; mpls_main_t * mm = &mpls_main; - u32 feature_index; - u32 ci, cast; - - for (cast = 0; cast < VNET_N_IP_FEAT; cast++) - { - vnet_feature_config_main_t * cm = &mm->feature_config_mains[cast]; - vnet_config_main_t * vcm = &cm->config_main; - - if (VNET_IP_RX_MULTICAST_FEAT == cast) - continue; - - vec_validate_init_empty (mm->mpls_enabled_by_sw_if_index, sw_if_index, 0); - vec_validate_init_empty (mm->fib_index_by_sw_if_index, sw_if_index, 0); - 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]; - - if (cast == VNET_IP_RX_UNICAST_FEAT) - feature_index = mm->mpls_rx_feature_not_enabled; - else - feature_index = mm->mpls_tx_feature_interface_output; - - - if (is_add) - ci = vnet_config_add_feature (vm, vcm, ci, - feature_index, - /* config data */ 0, - /* # bytes of config data */ 0); - else - { - ci = vnet_config_del_feature (vm, vcm, ci, - feature_index, - /* config data */ 0, - /* # bytes of config data */ 0); - mm->mpls_enabled_by_sw_if_index[sw_if_index] = 0;; - } - cm->config_index_by_sw_if_index[sw_if_index] = ci; - } + + vec_validate_init_empty (mm->mpls_enabled_by_sw_if_index, sw_if_index, 0); + vec_validate_init_empty (mm->fib_index_by_sw_if_index, sw_if_index, 0); + + vnet_feature_enable_disable ("mpls-input", "mpls-not-enabled", sw_if_index, + is_add, 0, 0); + vnet_feature_enable_disable ("mpls-output", "interface-output", sw_if_index, + is_add, 0, 0); return /* no error */ 0; } VNET_SW_INTERFACE_ADD_DEL_FUNCTION (mpls_sw_interface_add_del); -#define foreach_af_cast \ -_(VNET_IP_RX_UNICAST_FEAT, "mpls input") \ -_(VNET_IP_TX_FEAT, "mpls output") \ diff --git a/vnet/vnet/mpls/node.c b/vnet/vnet/mpls/node.c index c98b98e733b..2b0461f751e 100644 --- a/vnet/vnet/mpls/node.c +++ b/vnet/vnet/mpls/node.c @@ -96,8 +96,7 @@ mpls_input_inline (vlib_main_t * vm, vlib_buffer_t * b0; mpls_unicast_header_t * h0; u32 label0; - u32 next0; - vnet_feature_config_main_t * cm0; + u32 next0 = 0; u32 sw_if_index0; bi0 = from[0]; @@ -111,10 +110,6 @@ mpls_input_inline (vlib_main_t * vm, h0 = vlib_buffer_get_current (b0); sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; - cm0 = &mm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; - b0->current_config_index = vec_elt (cm0->config_index_by_sw_if_index, - sw_if_index0); - label0 = clib_net_to_host_u32 (h0->label_exp_s_ttl); /* TTL expired? */ if (PREDICT_FALSE(vnet_mpls_uc_get_ttl (label0) == 0)) @@ -124,10 +119,7 @@ mpls_input_inline (vlib_main_t * vm, } else { - vnet_get_config_data (&cm0->config_main, - &b0->current_config_index, - &next0, - /* # bytes of config data */ 0); + vnet_feature_arc_start(mm->input_feature_arc_index, sw_if_index0, &next0, b0); vlib_increment_simple_counter (cm, cpu_index, sw_if_index0, 1); } @@ -218,7 +210,7 @@ static clib_error_t * mpls_input_init (vlib_main_t * vm) mpls_setup_nodes (vm); - return (mpls_feature_init(vm)); + return 0; } VLIB_INIT_FUNCTION (mpls_input_init); diff --git a/vnet/vnet/vnet.h b/vnet/vnet/vnet.h index a3cbd37903c..98b29e9c0d3 100644 --- a/vnet/vnet/vnet.h +++ b/vnet/vnet/vnet.h @@ -42,21 +42,6 @@ #include <vppinfra/types.h> -typedef enum -{ - VNET_IP_RX_UNICAST_FEAT, - VNET_IP_RX_MULTICAST_FEAT, - VNET_IP_TX_FEAT, - VNET_N_IP_FEAT, -} vnet_cast_t; - -#define VNET_CAST_NAMES { \ - [VNET_IP_RX_UNICAST_FEAT] = "rx-unicast", \ - [VNET_IP_RX_MULTICAST_FEAT] = "rx-multicast", \ - [VNET_IP_TX_FEAT] = "tx", \ -} - - #include <vnet/unix/pcap.h> #include <vnet/buffer.h> #include <vnet/config.h> diff --git a/vpp/vpp-api/api.c b/vpp/vpp-api/api.c index e606673234b..6852e02a5d6 100644 --- a/vpp/vpp-api/api.c +++ b/vpp/vpp-api/api.c @@ -1571,79 +1571,21 @@ vl_api_sw_interface_set_table_t_handler (vl_api_sw_interface_set_table_t * mp) static void vl_api_sw_interface_set_vpath_t_handler (vl_api_sw_interface_set_vpath_t * mp) { - vlib_main_t *vm = vlib_get_main (); - ip4_main_t *im4 = &ip4_main; - ip6_main_t *im6 = &ip6_main; vl_api_sw_interface_set_vpath_reply_t *rmp; int rv = 0; - u32 ci; u32 sw_if_index = ntohl (mp->sw_if_index); - ip4_main_t *ip4m = &ip4_main; - ip6_main_t *ip6m = &ip6_main; - ip_lookup_main_t *ip4lm = &ip4m->lookup_main; - ip_lookup_main_t *ip6lm = &ip6m->lookup_main; - vnet_feature_config_main_t *rx_cm4u = - &ip4lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; - vnet_feature_config_main_t *rx_cm4m = - &ip4lm->feature_config_mains[VNET_IP_RX_MULTICAST_FEAT]; - vnet_feature_config_main_t *rx_cm6u = - &ip6lm->feature_config_mains[VNET_IP_RX_UNICAST_FEAT]; - vnet_feature_config_main_t *rx_cm6m = - &ip6lm->feature_config_mains[VNET_IP_RX_MULTICAST_FEAT]; VALIDATE_SW_IF_INDEX (mp); l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_VPATH, mp->enable); - if (mp->enable) - { - ci = rx_cm4u->config_index_by_sw_if_index[sw_if_index]; //IP4 unicast - ci = vnet_config_add_feature (vm, &rx_cm4u->config_main, - ci, - im4->ip4_unicast_rx_feature_vpath, 0, 0); - rx_cm4u->config_index_by_sw_if_index[sw_if_index] = ci; - ci = rx_cm4m->config_index_by_sw_if_index[sw_if_index]; //IP4 mcast - ci = vnet_config_add_feature (vm, &rx_cm4m->config_main, - ci, - im4->ip4_multicast_rx_feature_vpath, - 0, 0); - rx_cm4m->config_index_by_sw_if_index[sw_if_index] = ci; - ci = rx_cm6u->config_index_by_sw_if_index[sw_if_index]; //IP6 unicast - ci = vnet_config_add_feature (vm, &rx_cm6u->config_main, - ci, - im6->ip6_unicast_rx_feature_vpath, 0, 0); - rx_cm6u->config_index_by_sw_if_index[sw_if_index] = ci; - ci = rx_cm6m->config_index_by_sw_if_index[sw_if_index]; //IP6 mcast - ci = vnet_config_add_feature (vm, &rx_cm6m->config_main, - ci, - im6->ip6_multicast_rx_feature_vpath, - 0, 0); - rx_cm6m->config_index_by_sw_if_index[sw_if_index] = ci; - } - else - { - ci = rx_cm4u->config_index_by_sw_if_index[sw_if_index]; //IP4 unicast - ci = vnet_config_del_feature (vm, &rx_cm4u->config_main, - ci, - im4->ip4_unicast_rx_feature_vpath, 0, 0); - rx_cm4u->config_index_by_sw_if_index[sw_if_index] = ci; - ci = rx_cm4m->config_index_by_sw_if_index[sw_if_index]; //IP4 mcast - ci = vnet_config_del_feature (vm, &rx_cm4m->config_main, - ci, - im4->ip4_multicast_rx_feature_vpath, - 0, 0); - rx_cm4m->config_index_by_sw_if_index[sw_if_index] = ci; - ci = rx_cm6u->config_index_by_sw_if_index[sw_if_index]; //IP6 unicast - ci = vnet_config_del_feature (vm, &rx_cm6u->config_main, - ci, - im6->ip6_unicast_rx_feature_vpath, 0, 0); - rx_cm6u->config_index_by_sw_if_index[sw_if_index] = ci; - ci = rx_cm6m->config_index_by_sw_if_index[sw_if_index]; //IP6 mcast - ci = vnet_config_del_feature (vm, &rx_cm6m->config_main, - ci, - im6->ip6_multicast_rx_feature_vpath, - 0, 0); - rx_cm6m->config_index_by_sw_if_index[sw_if_index] = ci; - } + vnet_feature_enable_disable ("ip4-unicast", "vpath-input-ip4", + sw_if_index, mp->enable, 0, 0); + vnet_feature_enable_disable ("ip4-multicast", "vpath-input-ip4", + sw_if_index, mp->enable, 0, 0); + vnet_feature_enable_disable ("ip6-unicast", "vpath-input-ip6", + sw_if_index, mp->enable, 0, 0); + vnet_feature_enable_disable ("ip6-multicast", "vpath-input-ip6", + sw_if_index, mp->enable, 0, 0); BAD_SW_IF_INDEX_LABEL; |