X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=src%2Fvlib%2Ferror.c;h=de2020f08cb6791dfc69fe6623d9627f06dbc01f;hb=c428fd5d9476baba02edc0a10552719460e85b1e;hp=99664c618a9b2ed510869d4e29e4dcc8fb06fa78;hpb=92ccf9bcd2692b4b415f31044560c735d639a35c;p=vpp.git diff --git a/src/vlib/error.c b/src/vlib/error.c index 99664c618a9..de2020f08cb 100644 --- a/src/vlib/error.c +++ b/src/vlib/error.c @@ -39,7 +39,7 @@ #include #include -#include +#include uword vlib_error_drop_buffers (vlib_main_t * vm, @@ -112,102 +112,154 @@ 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; +} + +void +vlib_unregister_errors (vlib_main_t *vm, u32 node_index) +{ + vlib_error_main_t *em = &vm->error_main; + vlib_node_t *n = vlib_get_node (vm, node_index); + vlib_error_desc_t *cd; + + if (n->n_errors > 0) + { + 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 = 0; + } +} + /* Reserves given number of error codes for given node. */ void -vlib_register_errors (vlib_main_t * vm, - u32 node_index, u32 n_errors, char *error_strings[], - vl_counter_t counters[]) +vlib_register_errors (vlib_main_t *vm, u32 node_index, u32 n_errors, + char *error_strings[], vlib_error_desc_t counters[]) { 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); + vlib_unregister_errors (vm, node_index); 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]; // XXX Make name saner - 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_push_heap (0); + 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); + + 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; - u8 *error_name = 0; - - for (i = 0; i < n_errors; i++) - { - vec_reset_length (error_name); - error_name = - format (error_name, "/err/%v/%s%c", n->name, counters[i].name, 0); - vlib_stats_register_error_index (oldheap, error_name, em->counters, - n->error_heap_index + i); - } - - vec_free (error_name); - } - - /* (re)register the em->counters base address, switch back to main heap */ - vlib_stats_pop_heap2 (em->counters, vm->thread_index, oldheap, 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); + vec_free (vm->error_elog_event_types[n->error_heap_index + i].format); + 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 +unformat_vlib_error (unformat_input_t *input, va_list *args) +{ + vlib_main_t *vm = va_arg (*args, vlib_main_t *); + const vlib_error_main_t *em = &vm->error_main; + vlib_error_t *error_index = va_arg (*args, vlib_error_t *); + const vlib_node_t *node; + char *error_name; + u32 node_index; + vlib_error_t i; + + if (!unformat (input, "%U.%s", unformat_vlib_node, vm, &node_index, + &error_name)) + return 0; + + node = vlib_get_node (vm, node_index); + for (i = 0; i < node->n_errors; i++) + { + vlib_error_t ei = node->error_heap_index + i; + if (strcmp (em->counters_heap[ei].name, error_name) == 0) + { + *error_index = ei; + vec_free (error_name); + return 1; + } + } + + vec_free (error_name); + return 0; } static char * @@ -276,11 +328,11 @@ show_errors (vlib_main_t * vm, if (verbose) vlib_cli_output (vm, "%10lu%=35v%=35s%=10s%=6d", c, n->name, - em->counters_heap[i].name, + em->counters_heap[i].desc, sev2str (em->counters_heap[i].severity), i); else vlib_cli_output (vm, "%10lu%=35v%=35s%=10s", c, n->name, - em->counters_heap[i].name, + em->counters_heap[i].desc, sev2str (em->counters_heap[i].severity)); } } @@ -300,7 +352,7 @@ show_errors (vlib_main_t * vm, { if (verbose) vlib_cli_output (vm, "%10lu%=40v%=20s%=10d", sums[i], n->name, - em->counters_heap[i].name, i); + em->counters_heap[i].desc, i); } } }