vlib: address vlib_error_t scaling issue

Encoding the vpp node index into the vlib_error_t as a 10-bit quantity
limits us to 1K graph nodes. Unfortunately, a few nodes need 6 bit
per-node error codes. Only a very few nodes have so many counters.

It turns out that there are about 2K total error counters in the system,
which is (approximately) the maximum error heap index.

The current (index,code) encoding limits the number of interfaces to
around 250, since each interface has two associated graph nodes and we
have about 500 "normal, interior" graph node

This patch adds an error-index to node-index map, so we can store
error heap indices directly in the vlib_buffer_t.

Type: refactor

Signed-off-by: Steven Luong <sluong@cisco.com>
Change-Id: Ic2e91a5b344c9df3b98b264cacda246e06092a94
This commit is contained in:
Steven Luong 2019-11-20 11:20:08 -08:00 committed by Dave Barach
parent ac0e98a675
commit 70449b9b9b
7 changed files with 48 additions and 51 deletions

View File

@ -1034,7 +1034,7 @@ map_error_counter_get (u32 node_index, map_error_t map_error)
vlib_node_t *n = vlib_get_node (vm, node_index);
u32 ci;
ci = vlib_error_get_code (e);
ci = vlib_error_get_code (&vm->node_main, e);
ASSERT (ci < n->n_errors);
ci += n->error_heap_index;

View File

@ -51,8 +51,10 @@ vlib_error_drop_buffers (vlib_main_t * vm,
{
u32 n_left_this_frame, n_buffers_left, *args, n_args_left;
vlib_error_t drop_error;
vlib_node_t *n;
drop_error = vlib_error_set (drop_error_node, drop_error_code);
n = vlib_get_node (vm, drop_error_node);
drop_error = n->error_heap_index + drop_error_code;
n_buffers_left = n_buffers;
while (n_buffers_left > 0)
@ -161,6 +163,8 @@ vlib_register_errors (vlib_main_t * vm,
u32 node_index, u32 n_errors, char *error_strings[])
{
vlib_error_main_t *em = &vm->error_main;
vlib_node_main_t *nm = &vm->node_main;
vlib_node_t *n = vlib_get_node (vm, node_index);
uword l;
void *oldheap;
@ -220,19 +224,21 @@ vlib_register_errors (vlib_main_t * vm,
/* (re)register the em->counters base address, switch back to main heap */
vlib_stats_pop_heap2 (em->counters, vm->thread_index, oldheap);
if (VLIB_ELOG_MAIN_LOOP > 0)
{
elog_event_type_t t;
uword i;
{
elog_event_type_t t;
uword i;
clib_memset (&t, 0, sizeof (t));
for (i = 0; i < n_errors; i++)
{
t.format = (char *) format (0, "%v %s: %%d",
n->name, error_strings[i]);
vm->error_elog_event_types[n->error_heap_index + i] = t;
}
}
clib_memset (&t, 0, sizeof (t));
if (n_errors > 0)
vec_validate (nm->node_by_error, n->error_heap_index + n_errors - 1);
for (i = 0; i < n_errors; i++)
{
t.format = (char *) format (0, "%v %s: %%d",
n->name, error_strings[i]);
vm->error_elog_event_types[n->error_heap_index + i] = t;
nm->node_by_error[n->error_heap_index + i] = n->index;
}
}
}
static clib_error_t *

View File

@ -40,38 +40,8 @@
#ifndef included_vlib_error_h
#define included_vlib_error_h
/* Combined 16 bit node & 16 bit code as 32 bit number. */
typedef u16 vlib_error_t;
always_inline u32
vlib_error_get_node (vlib_error_t e)
{
return e >> 6;
}
always_inline u32
vlib_error_get_code (vlib_error_t e)
{
return e & 0x3f;
}
always_inline vlib_error_t
vlib_error_set (u32 node_index, u32 code)
{
ASSERT (node_index < (1 << 10));
ASSERT (code < (1 << 6));
return (node_index << 6) | code;
}
always_inline vlib_error_t
vlib_error_set_code (vlib_error_t e, u32 code)
{
ASSERT (vlib_error_get_code (e) == 0);
ASSERT (code < (1 << 6));
e |= code;
return e;
}
typedef struct
{
/* Error counters. */

View File

@ -502,7 +502,7 @@ register_node (vlib_main_t * vm, vlib_node_registration_t * r)
vec_resize (rt->errors, r->n_errors);
for (i = 0; i < vec_len (rt->errors); i++)
rt->errors[i] = vlib_error_set (n->index, i);
rt->errors[i] = n->error_heap_index + i;
STATIC_ASSERT_SIZEOF (vlib_node_runtime_t, 128);
ASSERT (vec_len (n->runtime_data) <= VLIB_NODE_RUNTIME_DATA_SIZE);

View File

@ -784,8 +784,27 @@ typedef struct
/* Node registrations added by constructors */
vlib_node_registration_t *node_registrations;
/* Node index from error code */
u32 *node_by_error;
} vlib_node_main_t;
typedef u16 vlib_error_t;
always_inline u32
vlib_error_get_node (vlib_node_main_t * nm, vlib_error_t e)
{
return nm->node_by_error[e];
}
always_inline u32
vlib_error_get_code (vlib_node_main_t * nm, vlib_error_t e)
{
u32 node_index = nm->node_by_error[e];
vlib_node_t *n = nm->nodes[node_index];
u32 error_code = e - n->error_heap_index;
return error_code;
}
#define FRAME_QUEUE_MAX_NELTS 32
typedef struct

View File

@ -856,6 +856,7 @@ start_workers (vlib_main_t * vm)
/* zap the (per worker) frame freelists, etc */
nm_clone->frame_sizes = 0;
nm_clone->frame_size_hash = hash_create (0, sizeof (uword));
nm_clone->node_by_error = nm->node_by_error;
/* Packet trace buffers are guaranteed to be empty, nothing to do here */
@ -1175,6 +1176,7 @@ vlib_worker_thread_node_refork (void)
nm_clone->processes = vec_dup_aligned (nm->processes,
CLIB_CACHE_LINE_BYTES);
nm_clone->node_by_error = nm->node_by_error;
}
void

View File

@ -562,10 +562,10 @@ counter_index (vlib_main_t * vm, vlib_error_t e)
vlib_node_t *n;
u32 ci, ni;
ni = vlib_error_get_node (e);
ni = vlib_error_get_node (&vm->node_main, e);
n = vlib_get_node (vm, ni);
ci = vlib_error_get_code (e);
ci = vlib_error_get_code (&vm->node_main, e);
ASSERT (ci < n->n_errors);
ci += n->error_heap_index;
@ -583,8 +583,8 @@ format_vnet_error_trace (u8 * s, va_list * va)
vlib_error_main_t *em = &vm->error_main;
u32 i;
error_node = vlib_get_node (vm, vlib_error_get_node (e[0]));
i = counter_index (vm, e[0]);
error_node = vlib_get_node (vm, vlib_error_get_node (&vm->node_main, e[0]));
i = counter_index (vm, vlib_error_get_code (&vm->node_main, e[0]));
s = format (s, "%v: %s", error_node->name, em->error_strings_heap[i]);
return s;
@ -652,8 +652,8 @@ trace_errors_with_buffers (vlib_main_t * vm,
static u8 *
validate_error (vlib_main_t * vm, vlib_error_t * e, u32 index)
{
uword node_index = vlib_error_get_node (e[0]);
uword code = vlib_error_get_code (e[0]);
uword node_index = vlib_error_get_node (&vm->node_main, e[0]);
uword code = vlib_error_get_code (&vm->node_main, e[0]);
vlib_node_t *n;
if (node_index >= vec_len (vm->node_main.nodes))