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 <mohammed@hawari.fr>
This commit is contained in:
Mohammed Hawari
committed by
Damjan Marion
parent
47968438dc
commit
3b5a013103
@ -569,6 +569,9 @@ vlib_node_sync_stats (vlib_main_t * vm, vlib_node_t * n)
|
|||||||
uword i;
|
uword i;
|
||||||
for (i = 0; i < rt->n_next_nodes; 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);
|
nf = vlib_node_runtime_get_next_frame (vm, rt, i);
|
||||||
vec_elt (n->n_vectors_by_next_node, i) +=
|
vec_elt (n->n_vectors_by_next_node, i) +=
|
||||||
nf->vectors_since_last_overflow;
|
nf->vectors_since_last_overflow;
|
||||||
|
@ -805,7 +805,8 @@ vlib_node_main_init (vlib_main_t * vm)
|
|||||||
if (!a)
|
if (!a)
|
||||||
continue;
|
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
|
error = clib_error_create
|
||||||
("node `%v' refers to unknown node `%s'", n->name, a);
|
("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. */
|
/* 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++)
|
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. */
|
next = vlib_get_node (vm, n->next_nodes[i]);
|
||||||
ASSERT (nf[i].node_runtime_index == next->runtime_index);
|
|
||||||
|
|
||||||
nf[i].flags = 0;
|
/* Validate node runtime indices are correctly initialized. */
|
||||||
if (next->flags & VLIB_NODE_FLAG_FRAME_NO_FREE_AFTER_DISPATCH)
|
ASSERT (nf[i].node_runtime_index == next->runtime_index);
|
||||||
nf[i].flags |= VLIB_FRAME_NO_FREE_AFTER_DISPATCH;
|
|
||||||
|
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;
|
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
|
* fd.io coding-style-patch-verification: ON
|
||||||
*
|
*
|
||||||
|
@ -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_SWITCH_FROM_POLLING_TO_INTERRUPT_MODE (1 << 7)
|
||||||
#define VLIB_NODE_FLAG_TRACE_SUPPORTED (1 << 8)
|
#define VLIB_NODE_FLAG_TRACE_SUPPORTED (1 << 8)
|
||||||
#define VLIB_NODE_FLAG_ADAPTIVE_MODE (1 << 9)
|
#define VLIB_NODE_FLAG_ADAPTIVE_MODE (1 << 9)
|
||||||
|
#define VLIB_NODE_FLAG_ALLOW_LAZY_NEXT_NODES (1 << 10)
|
||||||
|
|
||||||
/* State for input nodes. */
|
/* State for input nodes. */
|
||||||
u8 state;
|
u8 state;
|
||||||
|
@ -1338,6 +1338,10 @@ void vlib_node_runtime_sync_stats_node (vlib_node_t *n, vlib_node_runtime_t *r,
|
|||||||
/* Node graph initialization function. */
|
/* Node graph initialization function. */
|
||||||
clib_error_t *vlib_node_main_init (vlib_main_t * vm);
|
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_graph;
|
||||||
format_function_t format_vlib_node_name;
|
format_function_t format_vlib_node_name;
|
||||||
format_function_t format_vlib_next_node_name;
|
format_function_t format_vlib_next_node_name;
|
||||||
|
Reference in New Issue
Block a user