feature: convert all feature nodes to new feature infra 59/3759/8
authorDamjan Marion <damarion@cisco.com>
Wed, 9 Nov 2016 18:54:20 +0000 (19:54 +0100)
committerDave Barach <openvpp@barachs.net>
Fri, 11 Nov 2016 14:39:00 +0000 (14:39 +0000)
Change-Id: I34c527ba910fb282a95458b78d1d684eb337905e
Signed-off-by: Damjan Marion <damarion@cisco.com>
40 files changed:
plugins/flowperpkt-plugin/flowperpkt/flowperpkt.c
plugins/flowperpkt-plugin/flowperpkt/flowperpkt.h
plugins/flowperpkt-plugin/flowperpkt/node.c
plugins/ila-plugin/ila/ila.c
plugins/ila-plugin/ila/ila.h
plugins/snat-plugin/snat/out2in.c
plugins/snat-plugin/snat/snat.c
plugins/snat-plugin/snat/snat.h
vnet/vnet/adj/adj_l2.c
vnet/vnet/adj/adj_midchain.c
vnet/vnet/classify/flow_classify.c
vnet/vnet/classify/input_acl.c
vnet/vnet/classify/policer_classify.c
vnet/vnet/devices/devices.c
vnet/vnet/ethernet/ethernet.h
vnet/vnet/ethernet/init.c
vnet/vnet/feature/feature.c
vnet/vnet/feature/feature.h
vnet/vnet/feature/registration.c
vnet/vnet/ip/ip.h
vnet/vnet/ip/ip4.h
vnet/vnet/ip/ip4_forward.c
vnet/vnet/ip/ip4_input.c
vnet/vnet/ip/ip4_source_and_port_range_check.c
vnet/vnet/ip/ip4_source_check.c
vnet/vnet/ip/ip6.h
vnet/vnet/ip/ip6_forward.c
vnet/vnet/ip/ip6_input.c
vnet/vnet/ip/ip_init.c
vnet/vnet/ip/lookup.h
vnet/vnet/ipsec/ipsec.c
vnet/vnet/ipsec/ipsec_input.c
vnet/vnet/l2tp/decap.c
vnet/vnet/l2tp/l2tp.c
vnet/vnet/mpls/interface.c
vnet/vnet/mpls/mpls.h
vnet/vnet/mpls/mpls_features.c
vnet/vnet/mpls/node.c
vnet/vnet/vnet.h
vpp/vpp-api/api.c

index ac50858..dbdb189 100644 (file)
@@ -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;
 }
 
index 5ddba9c..31e685e 100644 (file)
@@ -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;
 
index b01f2be..86da3a1 100644 (file)
@@ -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);
index 61ce0f7..336f4cf 100644 (file)
@@ -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;
 }
 
index 657511f..2662098 100644 (file)
@@ -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;
 
index 190350a..35edcc5 100644 (file)
@@ -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;
index 0b97211..66c0381 100644 (file)
@@ -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,
   ({
index 1469f60..ca10b76 100644 (file)
@@ -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;
index c49ec77..4d2dd70 100644 (file)
@@ -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 = &ethernet_main.feature_config_mains[VNET_IP_TX_FEAT];
+    ethernet_main_t * em = &ethernet_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
            {
index d40ea79..92ea1ea 100644 (file)
@@ -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 = &ethernet_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.
index 527b13c..0a62420 100644 (file)
@@ -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,
index ddb4332..c446f2d 100644 (file)
@@ -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;
index ada0dae..569234f 100644 (file)
@@ -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;
     }
 }
 
index 2675330..928b0b4 100644 (file)
@@ -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) = {
index c31025b..e557a2c 100644 (file)
@@ -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 = &ethernet_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)
 {
index b636c4a..2d20adc 100644 (file)
@@ -61,35 +61,23 @@ 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 = &ethernet_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 = &ethernet_main.ethernet_tx_feature_drop,
 };
 /* *INDENT-ON* */
 
-static clib_error_t *
-ethernet_feature_init (vlib_main_t * vm)
-{
-  vnet_feature_config_main_t *cm =
-    &ethernet_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],
-                                &ethernet_main.feature_nodes
-                                [VNET_IP_TX_FEAT]));
-}
-
 static clib_error_t *
 ethernet_init (vlib_main_t * vm)
 {
@@ -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);
index 25f098d..1f46285 100644 (file)
@@ -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
index 793678b..b026cdf 100644 (file)
@@ -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" */
@@ -121,12 +122,28 @@ vnet_config_update_feature_count (vnet_feature_main_t * fm, u8 arc,
 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,
index e6b0968..1deeeef 100644 (file)
@@ -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
  *
index a57d162..c9a8293 100644 (file)
@@ -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 */
index f0806c0..62bb5f8 100644 (file)
@@ -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;
index 632925a..6d3dd88 100644 (file)
@@ -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)
index 268f7af..a3620de 100644 (file)
@@ -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);
index 8b69522..28dabeb 100644 (file)
@@ -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;
 }
index 62ebcb7..f7900d3 100644 (file)
@@ -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;
 }
index 8b3b997..428a16f 100644 (file)
@@ -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;
index 53d13db..899203c 100644 (file)
@@ -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 */
index a355abf..f6d56be 100644 (file)
@@ -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;
index c89f60c..d87a92e 100644 (file)
@@ -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);
-}
-
-
-
index 239ca68..7f9b984 100644 (file)
@@ -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. */
index 3f2bad9..7d459f6 100644 (file)
@@ -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;
 }
index 8b75c12..809fe6d 100644 (file)
@@ -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);
 
index e041fdf..e91e6fb 100644 (file)
@@ -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);
        }
     }
 
index c6da866..a4531da 100644 (file)
@@ -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;
 }
 
index 9fd93ff..a0f6f2f 100644 (file)
@@ -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)
index 85973d8..59fc761 100644 (file)
@@ -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;
index 2f98867..a7593c5 100644 (file)
@@ -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")               \
 
index c98b98e..2b0461f 100644 (file)
@@ -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);
index a3cbd37..98b29e9 100644 (file)
 
 #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>
index e606673..6852e02 100644 (file)
@@ -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;