feature: Config end nodes are user specific 06/27006/4
authorNeale Ranns <nranns@cisco.com>
Tue, 12 May 2020 08:51:02 +0000 (08:51 +0000)
committerAndrew Yourtchenko <ayourtch@gmail.com>
Wed, 13 May 2020 11:30:34 +0000 (11:30 +0000)
Type: fix

it is possible for a user to change the end node of a feature arc, but
this change should only apply to that 'instnace' of the arc, not all
arcs. for example, if a tunnel has its ipx-output end node changed to
adj-midchain-tx, this shouldn't affect all ipx-output arcs. obviously...

Signed-off-by: Neale Ranns <nranns@cisco.com>
Change-Id: I41daea7ba6907963e42140307d065c8bcfdcb585

src/vnet/adj/adj_midchain.c
src/vnet/config.c
src/vnet/config.h
src/vnet/feature/feature.c
src/vnet/feature/feature.h
test/test_ipsec_tun_if_esp.py

index 4741ec9..050c25a 100644 (file)
@@ -361,7 +361,7 @@ adj_midchain_teardown (ip_adjacency_t *adj)
     dpo_reset(&adj->sub_type.midchain.next_dpo);
 
     vlib_worker_thread_barrier_sync(vm);
-    vnet_feature_modify_end_node(
+    adj->ia_cfg_index = vnet_feature_modify_end_node(
         adj_midchain_get_feature_arc_index_for_link_type (adj),
         adj->rewrite_header.sw_if_index,
         vlib_get_node_by_name (vlib_get_main(),
@@ -405,7 +405,7 @@ adj_midchain_setup (adj_index_t adj_index,
     tx_node = adj_nbr_midchain_get_tx_node(adj);
 
     vlib_worker_thread_barrier_sync(vm);
-    vnet_feature_modify_end_node(
+    adj->ia_cfg_index = vnet_feature_modify_end_node(
         adj_midchain_get_feature_arc_index_for_link_type (adj),
         adj->rewrite_header.sw_if_index,
         tx_node);
@@ -481,7 +481,7 @@ adj_nbr_midchain_update_next_node (adj_index_t adj_index,
                                                         adj->ia_node_index,
                                                         next_node);
 
-    vnet_feature_modify_end_node(
+    adj->ia_cfg_index = vnet_feature_modify_end_node(
         adj_midchain_get_feature_arc_index_for_link_type (adj),
         adj->rewrite_header.sw_if_index,
         next_node);
@@ -490,7 +490,7 @@ adj_nbr_midchain_update_next_node (adj_index_t adj_index,
 }
 
 void
-adj_nbr_midchain_reset_next_node(adj_index_t adj_index)
+adj_nbr_midchain_reset_next_node (adj_index_t adj_index)
 {
     ip_adjacency_t *adj;
     vlib_main_t * vm;
@@ -507,7 +507,7 @@ adj_nbr_midchain_reset_next_node(adj_index_t adj_index)
                            adj->ia_node_index,
                            adj_nbr_midchain_get_tx_node(adj));
 
-    vnet_feature_modify_end_node(
+    adj->ia_cfg_index = vnet_feature_modify_end_node(
         adj_midchain_get_feature_arc_index_for_link_type (adj),
         adj->rewrite_header.sw_if_index,
         adj_nbr_midchain_get_tx_node(adj));
index e341c69..5937574 100644 (file)
@@ -85,7 +85,8 @@ add_next (vlib_main_t * vm,
 static vnet_config_t *
 find_config_with_features (vlib_main_t * vm,
                           vnet_config_main_t * cm,
-                          vnet_config_feature_t * feature_vector)
+                          vnet_config_feature_t * feature_vector,
+                          u32 end_node_index)
 {
   u32 last_node_index = ~0;
   vnet_config_feature_t *f;
@@ -112,9 +113,9 @@ find_config_with_features (vlib_main_t * vm,
   }
 
   /* Terminate config string with next for end node. */
-  if (last_node_index == ~0 || last_node_index != cm->end_node_index)
+  if (last_node_index == ~0 || last_node_index != end_node_index)
     {
-      u32 next_index = add_next (vm, cm, last_node_index, cm->end_node_index);
+      u32 next_index = add_next (vm, cm, last_node_index, end_node_index);
       vec_add1 (config_string, next_index);
     }
 
@@ -152,6 +153,12 @@ find_config_with_features (vlib_main_t * vm,
       hash_set_mem (cm->config_string_hash, config_string, c->index);
 
       c->reference_count = 0;  /* will be incremented by caller. */
+
+      vec_validate_init_empty (cm->end_node_indices_by_user_index,
+                              c->config_string_heap_index + 1,
+                              cm->default_end_node_index);
+      cm->end_node_indices_by_user_index[c->config_string_heap_index + 1]
+       = end_node_index;
     }
 
   return c;
@@ -197,7 +204,7 @@ vnet_config_init (vlib_main_t * vm,
          if (n)
            {
              if (i + 1 == n_feature_node_names)
-               cm->end_node_index = n->index;
+               cm->default_end_node_index = n->index;
              cm->node_index_by_feature_index[i] = n->index;
            }
          else
@@ -263,7 +270,7 @@ vnet_config_modify_end_node (vlib_main_t * vm,
     {
       /* is the last feature the cuurent end node */
       u32 last = vec_len (new_features) - 1;
-      if (new_features[last].node_index == cm->end_node_index)
+      if (new_features[last].node_index == cm->default_end_node_index)
        {
          vec_free (new_features->feature_config);
          _vec_len (new_features) = last;
@@ -273,9 +280,7 @@ vnet_config_modify_end_node (vlib_main_t * vm,
   if (old)
     remove_reference (cm, old);
 
-  cm->end_node_index = end_node_index;
-
-  new = find_config_with_features (vm, cm, new_features);
+  new = find_config_with_features (vm, cm, new_features, end_node_index);
   new->reference_count += 1;
 
   /*
@@ -299,7 +304,7 @@ vnet_config_add_feature (vlib_main_t * vm,
 {
   vnet_config_t *old, *new;
   vnet_config_feature_t *new_features, *f;
-  u32 n_feature_config_u32s;
+  u32 n_feature_config_u32s, end_node_index;
   u32 node_index = vec_elt (cm->node_index_by_feature_index, feature_index);
 
   if (node_index == ~0)                // feature node does not exist
@@ -309,12 +314,15 @@ vnet_config_add_feature (vlib_main_t * vm,
     {
       old = 0;
       new_features = 0;
+      end_node_index = cm->default_end_node_index;
     }
   else
     {
       u32 *p = vnet_get_config_heap (cm, config_string_heap_index);
       old = pool_elt_at_index (cm->config_pool, p[-1]);
       new_features = old->features;
+      end_node_index =
+       cm->end_node_indices_by_user_index[config_string_heap_index];
       if (new_features)
        new_features = duplicate_feature_vector (new_features);
     }
@@ -336,7 +344,7 @@ vnet_config_add_feature (vlib_main_t * vm,
   if (old)
     remove_reference (cm, old);
 
-  new = find_config_with_features (vm, cm, new_features);
+  new = find_config_with_features (vm, cm, new_features, end_node_index);
   new->reference_count += 1;
 
   /*
@@ -398,7 +406,9 @@ vnet_config_del_feature (vlib_main_t * vm,
      adds a new config because none of existing config's has matching features
      and so can be reused */
   remove_reference (cm, old);
-  new = find_config_with_features (vm, cm, new_features);
+  new = find_config_with_features (vm, cm, new_features,
+                                  cm->end_node_indices_by_user_index
+                                  [config_string_heap_index]);
   new->reference_count += 1;
 
   vec_validate (cm->config_pool_index_by_user_index,
index ab9e4b1..7eb3cf0 100644 (file)
@@ -95,7 +95,8 @@ typedef struct
   u32 *config_string_heap;
 
   /* Node index which starts/ends feature processing. */
-  u32 *start_node_indices, end_node_index;
+  u32 *start_node_indices, *end_node_indices_by_user_index,
+    default_end_node_index;
 
   /* Interior feature processing nodes (not including start and end nodes). */
   u32 *node_index_by_feature_index;
index 4a5127d..09dd9cc 100644 (file)
@@ -321,7 +321,7 @@ vnet_feature_enable_disable (const char *arc_name, const char *node_name,
                                                 n_feature_config_bytes);
 }
 
-int
+u32
 vnet_feature_modify_end_node (u8 arc_index,
                              u32 sw_if_index, u32 end_node_index)
 {
@@ -342,12 +342,10 @@ vnet_feature_modify_end_node (u8 arc_index,
   ci = vnet_config_modify_end_node (vlib_get_main (), &cm->config_main,
                                    ci, end_node_index);
 
-  if (ci == ~0)
-    return 0;
-
-  cm->config_index_by_sw_if_index[sw_if_index] = ci;
+  if (ci != ~0)
+    cm->config_index_by_sw_if_index[sw_if_index] = ci;
 
-  return 0;
+  return ci;
 }
 
 static int
@@ -495,6 +493,14 @@ vnet_interface_features_show (vlib_main_t * vm, u32 sw_if_index, int verbose)
          else
            vlib_cli_output (vm, "  %v", n->name);
        }
+      if (verbose)
+       {
+         n =
+           vlib_get_node (vm,
+                          vcm->end_node_indices_by_user_index
+                          [current_config_index]);
+         vlib_cli_output (vm, "  [end] %v", n->name);
+       }
     }
 }
 
index 4d568a5..6eb6de3 100644 (file)
@@ -219,7 +219,7 @@ vnet_feature_enable_disable (const char *arc_name, const char *node_name,
                             void *feature_config,
                             u32 n_feature_config_bytes);
 
-int
+u32
 vnet_feature_modify_end_node (u8 arc_index, u32 sw_if_index, u32 node_index);
 
 static_always_inline u32
index 3ab0e73..a59baf1 100644 (file)
@@ -21,6 +21,7 @@ from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint
 from vpp_teib import VppTeib
 from util import ppp
 from vpp_papi import VppEnum
+from vpp_acl import AclRule, VppAcl, VppAclInterface
 
 
 def config_tun_params(p, encryption_type, tun_if):
@@ -2027,6 +2028,17 @@ class TestIpsec4TunProtectTun(TemplateIpsec,
         self.config_sa_tun(p)
         self.config_protect(p)
 
+        # also add an output features on the tunnel and physical interface
+        # so we test they still work
+        r_all = AclRule(True,
+                        src_prefix="0.0.0.0/0",
+                        dst_prefix="0.0.0.0/0",
+                        proto=0)
+        a = VppAcl(self, [r_all]).add_vpp_config()
+
+        VppAclInterface(self, self.pg0.sw_if_index, [a]).add_vpp_config()
+        VppAclInterface(self, p.tun_if.sw_if_index, [a]).add_vpp_config()
+
         self.verify_tun_44(p, count=127)
 
         c = p.tun_if.get_rx_stats()