summaryrefslogtreecommitdiffstats
path: root/src/vlib
diff options
context:
space:
mode:
authorDave Barach <dave@barachs.net>2019-07-23 10:22:31 -0400
committerDave Barach <dave@barachs.net>2019-10-25 18:00:05 -0400
commitb5bc2e0e1cc70eb301c864212d3a3099b08bac49 (patch)
treeced89d1e7d5f0076c3f38a6606f1e96303d7c55c /src/vlib
parente6329ada4401f4a7e418a48fe829bbc211e28b6f (diff)
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 Change-Id: I28101cad3d8750819e27b8785fc0cf71ff54f79a Signed-off-by: Dave Barach <dave@barachs.net> (cherry picked from commit 687c9021fda009caa2b7eb17bea2eaa51d275bde)
Diffstat (limited to 'src/vlib')
-rw-r--r--src/vlib/drop.c12
-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
6 files changed, 47 insertions, 50 deletions
diff --git a/src/vlib/drop.c b/src/vlib/drop.c
index 2b245b561e3..034a23fb759 100644
--- a/src/vlib/drop.c
+++ b/src/vlib/drop.c
@@ -27,8 +27,8 @@ typedef enum
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))
@@ -69,10 +69,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;
@@ -90,8 +90,8 @@ format_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;
diff --git a/src/vlib/error.c b/src/vlib/error.c
index 17447b07119..ec6d2b1362b 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)
@@ -130,6 +132,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;
@@ -189,19 +193,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 58352519be2..0da3a18d85d 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 49c7a40b572..f522bf55e27 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 bdc3c6b59ad..c2638d03692 100644
--- a/src/vlib/node.h
+++ b/src/vlib/node.h
@@ -761,8 +761,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 52886df37e0..cc3b1f436ce 100644
--- a/src/vlib/threads.c
+++ b/src/vlib/threads.c
@@ -871,6 +871,7 @@ start_workers (vlib_main_t * vm)
#ifdef VLIB_SUPPORTS_ARBITRARY_SCALAR_SIZES
nm_clone->frame_size_hash = hash_create (0, sizeof (uword));
#endif
+ nm_clone->node_by_error = nm->node_by_error;
/* Packet trace buffers are guaranteed to be empty, nothing to do here */
@@ -1197,6 +1198,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