session: api to add new transport types
[vpp.git] / src / vnet / feature / registration.c
index 1deeeef..030486a 100644 (file)
@@ -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 <node> before <last-in-arc> 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.