diff options
Diffstat (limited to 'src/vlib/error.c')
-rw-r--r-- | src/vlib/error.c | 130 |
1 files changed, 71 insertions, 59 deletions
diff --git a/src/vlib/error.c b/src/vlib/error.c index e513a7d673b..f01e0b63e95 100644 --- a/src/vlib/error.c +++ b/src/vlib/error.c @@ -112,6 +112,17 @@ vlib_error_drop_buffers (vlib_main_t * vm, return n_buffers; } +static u8 * +format_stats_counter_name (u8 *s, va_list *va) +{ + u8 *id = va_arg (*va, u8 *); + + for (u32 i = 0; id[i] != 0; i++) + vec_add1 (s, id[i] == ' ' ? ' ' : id[i]); + + return s; +} + /* Reserves given number of error codes for given node. */ void vlib_register_errors (vlib_main_t *vm, u32 node_index, u32 n_errors, @@ -119,92 +130,93 @@ vlib_register_errors (vlib_main_t *vm, u32 node_index, u32 n_errors, { 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); + vlib_error_desc_t *cd; + u32 n_threads = vlib_get_n_threads (); + elog_event_type_t t = {}; uword l; - void *oldheap; + u64 **sc; ASSERT (vlib_get_thread_index () == 0); + vlib_stats_segment_lock (); + /* Free up any previous error strings. */ if (n->n_errors > 0) - heap_dealloc (em->counters_heap, n->error_heap_handle); + { + cd = vec_elt_at_index (em->counters_heap, n->error_heap_index); + for (u32 i = 0; i < n->n_errors; i++) + vlib_stats_remove_entry (cd[i].stats_entry_index); + heap_dealloc (em->counters_heap, n->error_heap_handle); + } n->n_errors = n_errors; n->error_counters = counters; if (n_errors == 0) - return; + goto done; + + n->error_heap_index = + heap_alloc (em->counters_heap, n_errors, n->error_heap_handle); + l = vec_len (em->counters_heap); + cd = vec_elt_at_index (em->counters_heap, n->error_heap_index); /* Legacy node */ if (!counters) { - counters = clib_mem_alloc (sizeof (counters[0]) * n_errors); - int i; - for (i = 0; i < n_errors; i++) + for (int i = 0; i < n_errors; i++) { - counters[i].name = error_strings[i]; - counters[i].desc = error_strings[i]; - counters[i].severity = VL_COUNTER_SEVERITY_ERROR; + cd[i].name = error_strings[i]; + cd[i].desc = error_strings[i]; + cd[i].severity = VL_COUNTER_SEVERITY_ERROR; } } - - n->error_heap_index = - heap_alloc (em->counters_heap, n_errors, n->error_heap_handle); - l = vec_len (em->counters_heap); - clib_memcpy (vec_elt_at_index (em->counters_heap, n->error_heap_index), - counters, n_errors * sizeof (counters[0])); + else + clib_memcpy (cd, counters, n_errors * sizeof (counters[0])); vec_validate (vm->error_elog_event_types, l - 1); - /* Switch to the stats segment ... */ - oldheap = vlib_stats_set_heap (); + if (em->stats_err_entry_index == 0) + em->stats_err_entry_index = vlib_stats_add_counter_vector ("/node/errors"); - /* Allocate a counter/elog type for each error. */ - vec_validate (em->counters, l - 1); + ASSERT (em->stats_err_entry_index != 0 && em->stats_err_entry_index != ~0); - /* Zero counters for re-registrations of errors. */ - if (n->error_heap_index + n_errors <= vec_len (em->counters_last_clear)) - clib_memcpy (em->counters + n->error_heap_index, - em->counters_last_clear + n->error_heap_index, - n_errors * sizeof (em->counters[0])); - else - clib_memset (em->counters + n->error_heap_index, - 0, n_errors * sizeof (em->counters[0])); + vlib_stats_validate (em->stats_err_entry_index, n_threads - 1, l - 1); + sc = vlib_stats_get_entry_data_pointer (em->stats_err_entry_index); - oldheap = clib_mem_set_heap (oldheap); + for (int i = 0; i < n_threads; i++) + { + vlib_main_t *tvm = vlib_get_main_by_index (i); + vlib_error_main_t *tem = &tvm->error_main; + tem->counters = sc[i]; + + /* Zero counters for re-registrations of errors. */ + if (n->error_heap_index + n_errors <= vec_len (tem->counters_last_clear)) + clib_memcpy (tem->counters + n->error_heap_index, + tem->counters_last_clear + n->error_heap_index, + n_errors * sizeof (tem->counters[0])); + else + clib_memset (tem->counters + n->error_heap_index, 0, + n_errors * sizeof (tem->counters[0])); + } /* Register counter indices in the stat segment directory */ - { - int i; - - for (i = 0; i < n_errors; i++) - { - vlib_stats_register_error_index (em->counters, n->error_heap_index + i, - "/err/%v/%s", n->name, - counters[i].name); - } - - } - - /* (re)register the em->counters base address, switch back to main heap */ - vlib_stats_update_error_vector (em->counters, vm->thread_index, 1); - - { - elog_event_type_t t; - uword i; - - 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, counters[i].name); - vm->error_elog_event_types[n->error_heap_index + i] = t; - nm->node_by_error[n->error_heap_index + i] = n->index; - } - } + for (int i = 0; i < n_errors; i++) + cd[i].stats_entry_index = vlib_stats_add_symlink ( + em->stats_err_entry_index, n->error_heap_index + i, "/err/%v/%U", + n->name, format_stats_counter_name, cd[i].name); + + vec_validate (nm->node_by_error, n->error_heap_index + n_errors - 1); + + for (u32 i = 0; i < n_errors; i++) + { + t.format = (char *) format (0, "%v %s: %%d", n->name, cd[i].name); + vm->error_elog_event_types[n->error_heap_index + i] = t; + nm->node_by_error[n->error_heap_index + i] = n->index; + } + +done: + vlib_stats_segment_unlock (); } uword |