X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Ffeature%2Fregistration.c;h=537a4ada6e49a79a13f5e8f21e2d57519c304492;hb=dc01471be72b272922bf6c9ef9e6221162ab906a;hp=1deeeef904cf0f19ab6984aefbf2af0b0e90d704;hpb=7cd468a3d7dee7d6c92f69a0bb7061ae208ec727;p=vpp.git diff --git a/src/vnet/feature/registration.c b/src/vnet/feature/registration.c index 1deeeef904c..537a4ada6e4 100644 --- a/src/vnet/feature/registration.c +++ b/src/vnet/feature/registration.c @@ -50,7 +50,7 @@
     VNET_FEATURE_INIT (ip4_lookup, static) =
     {
-      .arch_name = "ip4-unicast",
+      .arc_name = "ip4-unicast",
       .node_name = "my-ip4-unicast-feature",
       .runs_before = VLIB_FEATURES ("ip4-lookup")
     };
@@ -107,6 +107,9 @@ comma_split (u8 * s, u8 ** a, u8 ** b)
  * @param first_reg first element in
  *        [an __attribute__((constructor)) function built, or
  *        otherwise created] singly-linked list of feature registrations
+ * @param first_const first element in
+ *        [an __attribute__((constructor)) function built, or
+ *        otherwise created] singly-linked list of bulk order constraints
  * @param [out] in_feature_nodes returned vector of
  *        topologically-sorted feature node names, for use in
  *        show commands
@@ -119,13 +122,16 @@ vnet_feature_arc_init (vlib_main_t * vm,
 		       vnet_config_main_t * vcm,
 		       char **feature_start_nodes,
 		       int num_feature_start_nodes,
+		       char *last_in_arc,
 		       vnet_feature_registration_t * first_reg,
-		       char ***in_feature_nodes)
+		       vnet_feature_constraint_registration_t *
+		       first_const_set, char ***in_feature_nodes)
 {
   uword *index_by_name;
   uword *reg_by_index;
   u8 **node_names = 0;
   u8 *node_name;
+  char *prev_name;
   char **these_constraints;
   char *this_constraint_c;
   u8 **constraints = 0;
@@ -139,6 +145,7 @@ vnet_feature_arc_init (vlib_main_t * vm,
   int n_features;
   u32 *result = 0;
   vnet_feature_registration_t *this_reg = 0;
+  vnet_feature_constraint_registration_t *this_const_set = 0;
   char **feature_nodes = 0;
   hash_pair_t *hp;
   u8 **keys_to_delete = 0;
@@ -148,6 +155,27 @@ vnet_feature_arc_init (vlib_main_t * vm,
 
   this_reg = first_reg;
 
+  /* Autogenerate  before  constraints */
+  if (last_in_arc)
+    {
+      while (this_reg)
+	{
+	  /* If this isn't the last node in the arc... */
+	  if (clib_strcmp (this_reg->node_name, last_in_arc))
+	    {
+	      /*
+	       * Add an explicit constraint so this feature will run
+	       * before the last node in the arc
+	       */
+	      constraint_tuple = format (0, "%s,%s%c", this_reg->node_name,
+					 last_in_arc, 0);
+	      vec_add1 (constraints, constraint_tuple);
+	    }
+	  this_reg = this_reg->next_in_arc;
+	}
+      this_reg = first_reg;
+    }
+
   /* pass 1, collect feature node names, construct a before b pairs */
   while (this_reg)
     {
@@ -180,7 +208,45 @@ vnet_feature_arc_init (vlib_main_t * vm,
 	  these_constraints++;
 	}
 
-      this_reg = this_reg->next;
+      this_reg = this_reg->next_in_arc;
+    }
+
+  /* pass 2, collect bulk "a then b then c then d" constraints */
+  this_const_set = first_const_set;
+  while (this_const_set)
+    {
+      these_constraints = this_const_set->node_names;
+
+      prev_name = 0;
+      /* Across the list of constraints */
+      while (these_constraints && these_constraints[0])
+	{
+	  this_constraint_c = these_constraints[0];
+	  p = hash_get_mem (index_by_name, this_constraint_c);
+	  if (p == 0)
+	    {
+	      clib_warning
+		("bulk constraint feature node '%s' not found for arc '%s'",
+		 this_constraint_c);
+	      these_constraints++;
+	      continue;
+	    }
+
+	  if (prev_name == 0)
+	    {
+	      prev_name = this_constraint_c;
+	      these_constraints++;
+	      continue;
+	    }
+
+	  constraint_tuple = format (0, "%s,%s%c", prev_name,
+				     this_constraint_c, 0);
+	  vec_add1 (constraints, constraint_tuple);
+	  prev_name = this_constraint_c;
+	  these_constraints++;
+	}
+
+      this_const_set = this_const_set->next_in_arc;
     }
 
   n_features = vec_len (node_names);
@@ -201,12 +267,20 @@ vnet_feature_arc_init (vlib_main_t * vm,
        * Nonexistent graph nodes are tolerated.
        */
       if (p == 0)
-	return clib_error_return (0, "feature node '%s' not found", a_name);
+	{
+	  clib_warning ("feature node '%s' not found (before '%s', arc '%s')",
+			a_name, b_name, first_reg->arc_name);
+	  continue;
+	}
       a_index = p[0];
 
       p = hash_get_mem (index_by_name, b_name);
       if (p == 0)
-	return clib_error_return (0, "feature node '%s' not found", b_name);
+	{
+	  clib_warning ("feature node '%s' not found (after '%s', arc '%s')",
+			b_name, a_name, first_reg->arc_name);
+	  continue;
+	}
       b_index = p[0];
 
       /* add a before b to the original set of constraints */
@@ -244,7 +318,9 @@ again:
 
   /* see if we got a partial order... */
   if (vec_len (result) != n_features)
-    return clib_error_return (0, "%d feature_init_cast no partial order!");
+    return clib_error_return
+      (0, "Arc '%s': failed to find a suitable feature order!",
+       first_reg->arc_name);
 
   /*
    * We win.