From 3b5a013103f0eff44afbdc4937407a82931edd00 Mon Sep 17 00:00:00 2001 From: Mohammed Hawari Date: Thu, 29 Aug 2024 14:01:06 +0200 Subject: vlib: introduce lazy next node initialization 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 --- src/vlib/main.c | 3 +++ src/vlib/node.c | 49 +++++++++++++++++++++++++++++++++++++++++-------- src/vlib/node.h | 1 + src/vlib/node_funcs.h | 4 ++++ 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/vlib/main.c b/src/vlib/main.c index 8f87df997e5..bf840324b64 100644 --- a/src/vlib/main.c +++ b/src/vlib/main.c @@ -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; diff --git a/src/vlib/node.c b/src/vlib/node.c index 8f6c852188b..c0572f3cf83 100644 --- a/src/vlib/node.c +++ b/src/vlib/node.c @@ -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 * diff --git a/src/vlib/node.h b/src/vlib/node.h index 68813c2c3e1..651a39e3119 100644 --- a/src/vlib/node.h +++ b/src/vlib/node.h @@ -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; diff --git a/src/vlib/node_funcs.h b/src/vlib/node_funcs.h index 1beac33cf9b..4c7020d6a42 100644 --- a/src/vlib/node_funcs.h +++ b/src/vlib/node_funcs.h @@ -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; -- cgit 1.2.3-korg