aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Luong <sluong@cisco.com>2019-11-20 11:20:08 -0800
committerDave Barach <openvpp@barachs.net>2019-11-25 15:05:51 +0000
commit70449b9b9bf8dbe3b4aa4d9af35c759789b03fe1 (patch)
tree13faf049d3007a5a3314e69680bb6f652cb84529
parentac0e98a67553747b823d8398896559bb07cafe3d (diff)
vlib: address vlib_error_t scaling issuestable/1901
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
-rw-r--r--src/plugins/map/map.c2
-rw-r--r--src/vlib/error.c32
-rw-r--r--src/vlib/error.h30
-rw-r--r--src/vlib/node.c2
-rw-r--r--src/vlib/node.h19
-rw-r--r--src/vlib/threads.c2
-rw-r--r--src/vnet/interface_output.c12
7 files changed, 48 insertions, 51 deletions
diff --git a/src/plugins/map/map.c b/src/plugins/map/map.c
index 7a44a19..08c67d0 100644
--- a/src/plugins/map/map.c
+++ b/src/plugins/map/map.c
@@ -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;
diff --git a/src/vlib/error.c b/src/vlib/error.c
index 9bd928c..a0ce0b7 100644
--- a/src/vlib/error.c
+++ b/src/vlib/error.c
@@ -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 *
diff --git a/src/vlib/error.h b/src/vlib/error.h
index 5835251..0da3a18 100644
--- a/src/vlib/error.h
+++ b/src/vlib/error.h
@@ -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. */
diff --git a/src/vlib/node.c b/src/vlib/node.c
index 69f5051..97ab044 100644
--- a/src/vlib/node.c
+++ b/src/vlib/node.c
@@ -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);
diff --git a/src/vlib/node.h b/src/vlib/node.h
index 011709b..38ae4ec 100644
--- a/src/vlib/node.h
+++ b/src/vlib/node.h
@@ -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
diff --git a/src/vlib/threads.c b/src/vlib/threads.c
index 56f9d79..5bd9476 100644
--- a/src/vlib/threads.c
+++ b/src/vlib/threads.c
@@ -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
diff --git a/src/vnet/interface_output.c b/src/vnet/interface_output.c
index ba69d36..db4949d 100644
--- a/src/vnet/interface_output.c
+++ b/src/vnet/interface_output.c
@@ -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))