vlib: introduce lazy next node initialization 96/41496/6
authorMohammed Hawari <[email protected]>
Thu, 29 Aug 2024 12:01:06 +0000 (14:01 +0200)
committerDamjan Marion <[email protected]>
Thu, 12 Sep 2024 10:11:30 +0000 (10:11 +0000)
This change allow a node registration A to name a next node B that does not
exist yet at registration time. When node B is effectively created,
vlib_node_main_lazy_next_update need to be called so that the vlib graph
is updated accordingly. To enable this behavior, node A needs to bear
the new VLIB_NODE_FLAG_ALLOW_LAZY_NEXT_NODES.

Change-Id: I561d3a0de19a0b7bd1045760a2ba8e27d27caa9a
Type: improvement
Signed-off-by: Mohammed Hawari <[email protected]>
src/vlib/main.c
src/vlib/node.c
src/vlib/node.h
src/vlib/node_funcs.h

index 8f87df9..bf84032 100644 (file)
@@ -569,6 +569,9 @@ vlib_node_sync_stats (vlib_main_t * vm, vlib_node_t * n)
     uword i;
     for (i = 0; i < rt->n_next_nodes; i++)
       {
+       if (n->flags & VLIB_NODE_FLAG_ALLOW_LAZY_NEXT_NODES &&
+           n->next_nodes[i] == VLIB_INVALID_NODE_INDEX)
+         continue;
        nf = vlib_node_runtime_get_next_frame (vm, rt, i);
        vec_elt (n->n_vectors_by_next_node, i) +=
          nf->vectors_since_last_overflow;
index 8f6c852..c0572f3 100644 (file)
@@ -805,7 +805,8 @@ vlib_node_main_init (vlib_main_t * vm)
          if (!a)
            continue;
 
-         if (~0 == vlib_node_add_named_next_with_slot (vm, n->index, a, i))
+         if (~0 == vlib_node_add_named_next_with_slot (vm, n->index, a, i) &&
+             !(n->flags & VLIB_NODE_FLAG_ALLOW_LAZY_NEXT_NODES))
            {
              error = clib_error_create
                ("node `%v' refers to unknown node `%s'", n->name, a);
@@ -813,7 +814,8 @@ vlib_node_main_init (vlib_main_t * vm)
            }
        }
 
-      vec_free (n->next_node_names);
+      if (!(n->flags & VLIB_NODE_FLAG_ALLOW_LAZY_NEXT_NODES))
+       vec_free (n->next_node_names);
     }
 
   /* Set previous node pointers. */
@@ -851,14 +853,18 @@ vlib_node_main_init (vlib_main_t * vm)
 
       for (i = 0; i < vec_len (n->next_nodes); i++)
        {
-         next = vlib_get_node (vm, n->next_nodes[i]);
+           if (n->flags & VLIB_NODE_FLAG_ALLOW_LAZY_NEXT_NODES &&
+               n->next_nodes[i] >= vec_len (nm->nodes))
+             continue;
 
-         /* Validate node runtime indices are correctly initialized. */
-         ASSERT (nf[i].node_runtime_index == next->runtime_index);
+           next = vlib_get_node (vm, n->next_nodes[i]);
 
-         nf[i].flags = 0;
-         if (next->flags & VLIB_NODE_FLAG_FRAME_NO_FREE_AFTER_DISPATCH)
-           nf[i].flags |= VLIB_FRAME_NO_FREE_AFTER_DISPATCH;
+           /* Validate node runtime indices are correctly initialized. */
+           ASSERT (nf[i].node_runtime_index == next->runtime_index);
+
+           nf[i].flags = 0;
+           if (next->flags & VLIB_NODE_FLAG_FRAME_NO_FREE_AFTER_DISPATCH)
+             nf[i].flags |= VLIB_FRAME_NO_FREE_AFTER_DISPATCH;
        }
     }
   }
@@ -927,6 +933,33 @@ vlib_node_set_march_variant (vlib_main_t *vm, u32 node_index,
     }
   return -1;
 }
+
+clib_error_t *
+vlib_node_main_lazy_next_update (vlib_main_t *vm)
+{
+  vlib_node_main_t *nm = &vm->node_main;
+  uword ni;
+  vlib_node_t *n;
+  for (ni = 0; ni < vec_len (nm->nodes); ni++)
+    {
+      uword nni;
+      n = vec_elt (nm->nodes, ni);
+
+      if (!(n->flags & VLIB_NODE_FLAG_ALLOW_LAZY_NEXT_NODES))
+       continue;
+
+      for (nni = 0; nni < vec_len (n->next_node_names); nni++)
+       {
+         char *a = n->next_node_names[nni];
+
+         if (!a)
+           continue;
+
+         vlib_node_add_named_next_with_slot (vm, n->index, a, nni);
+       }
+    }
+  return 0;
+}
 /*
  * fd.io coding-style-patch-verification: ON
  *
index 68813c2..651a39e 100644 (file)
@@ -297,6 +297,7 @@ typedef struct vlib_node_t
 #define VLIB_NODE_FLAG_SWITCH_FROM_POLLING_TO_INTERRUPT_MODE (1 << 7)
 #define VLIB_NODE_FLAG_TRACE_SUPPORTED (1 << 8)
 #define VLIB_NODE_FLAG_ADAPTIVE_MODE                        (1 << 9)
+#define VLIB_NODE_FLAG_ALLOW_LAZY_NEXT_NODES                (1 << 10)
 
   /* State for input nodes. */
   u8 state;
index 1beac33..4c7020d 100644 (file)
@@ -1338,6 +1338,10 @@ void vlib_node_runtime_sync_stats_node (vlib_node_t *n, vlib_node_runtime_t *r,
 /* Node graph initialization function. */
 clib_error_t *vlib_node_main_init (vlib_main_t * vm);
 
+/* Refresh graph after the creation of a node that was potentially mentionned
+ * as a named next for a node with VLIB_NODE_FLAG_ALLOW_LAZY_NEXT_NODES */
+clib_error_t *vlib_node_main_lazy_next_update (vlib_main_t *vm);
+
 format_function_t format_vlib_node_graph;
 format_function_t format_vlib_node_name;
 format_function_t format_vlib_next_node_name;