build: add missing openssl-devel package for centos-8 vpp-ext-deps
[vpp.git] / src / vnet / config.c
index 9beda4a..c9d4909 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
@@ -234,6 +241,68 @@ vnet_get_config_heap (vnet_config_main_t * cm, u32 ci)
   return heap_elt_at_index (cm->config_string_heap, ci);
 }
 
+void
+vnet_config_del (vnet_config_main_t * cm, u32 config_id)
+{
+  u32 *p = vnet_get_config_heap (cm, config_id);
+  vnet_config_t *old = pool_elt_at_index (cm->config_pool, p[-1]);
+  remove_reference (cm, old);
+}
+
+u32
+vnet_config_modify_end_node (vlib_main_t * vm,
+                            vnet_config_main_t * cm,
+                            u32 config_string_heap_index, u32 end_node_index)
+{
+  vnet_config_feature_t *new_features;
+  vnet_config_t *old, *new;
+
+  if (end_node_index == ~0)    // feature node does not exist
+    return ~0;
+
+  if (config_string_heap_index == ~0)
+    {
+      old = 0;
+      new_features = 0;
+    }
+  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;
+      if (new_features)
+       new_features = duplicate_feature_vector (new_features);
+    }
+
+  if (vec_len (new_features))
+    {
+      /* is the last feature the cuurent end node */
+      u32 last = vec_len (new_features) - 1;
+      if (new_features[last].node_index == cm->default_end_node_index)
+       {
+         vec_free (new_features->feature_config);
+         _vec_len (new_features) = last;
+       }
+    }
+
+  if (old)
+    remove_reference (cm, old);
+
+  new = find_config_with_features (vm, cm, new_features, end_node_index);
+  new->reference_count += 1;
+
+  /*
+   * User gets pointer to config string first element
+   * (which defines the pool index
+   * this config string comes from).
+   */
+  vec_validate (cm->config_pool_index_by_user_index,
+               new->config_string_heap_index + 1);
+  cm->config_pool_index_by_user_index[new->config_string_heap_index + 1]
+    = new - cm->config_pool;
+  return new->config_string_heap_index + 1;
+}
+
 u32
 vnet_config_add_feature (vlib_main_t * vm,
                         vnet_config_main_t * cm,
@@ -243,7 +312,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
@@ -253,12 +322,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);
     }
@@ -267,11 +339,16 @@ vnet_config_add_feature (vlib_main_t * vm,
   f->feature_index = feature_index;
   f->node_index = node_index;
 
-  n_feature_config_u32s =
-    round_pow2 (n_feature_config_bytes,
-               sizeof (f->feature_config[0])) /
-    sizeof (f->feature_config[0]);
-  vec_add (f->feature_config, feature_config, n_feature_config_u32s);
+  if (n_feature_config_bytes)
+    {
+      n_feature_config_u32s =
+       round_pow2 (n_feature_config_bytes,
+                   sizeof (f->feature_config[0])) /
+       sizeof (f->feature_config[0]);
+      vec_validate (f->feature_config, n_feature_config_u32s - 1);
+      clib_memcpy_fast (f->feature_config, feature_config,
+                       n_feature_config_bytes);
+    }
 
   /* Sort (prioritize) features. */
   if (vec_len (new_features) > 1)
@@ -280,7 +357,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;
 
   /*
@@ -342,7 +419,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,