LCOV - code coverage report
Current view: top level - vlib - error.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 164 181 90.6 %
Date: 2023-10-26 01:39:38 Functions: 16 16 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2015 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : /*
      16             :  * error.c: VLIB error handler
      17             :  *
      18             :  * Copyright (c) 2008 Eliot Dresselhaus
      19             :  *
      20             :  * Permission is hereby granted, free of charge, to any person obtaining
      21             :  * a copy of this software and associated documentation files (the
      22             :  * "Software"), to deal in the Software without restriction, including
      23             :  * without limitation the rights to use, copy, modify, merge, publish,
      24             :  * distribute, sublicense, and/or sell copies of the Software, and to
      25             :  * permit persons to whom the Software is furnished to do so, subject to
      26             :  * the following conditions:
      27             :  *
      28             :  * The above copyright notice and this permission notice shall be
      29             :  * included in all copies or substantial portions of the Software.
      30             :  *
      31             :  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      32             :  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      33             :  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      34             :  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      35             :  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
      36             :  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
      37             :  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      38             :  */
      39             : 
      40             : #include <vlib/vlib.h>
      41             : #include <vppinfra/heap.h>
      42             : #include <vlib/stats/stats.h>
      43             : 
      44             : uword
      45          26 : vlib_error_drop_buffers (vlib_main_t * vm,
      46             :                          vlib_node_runtime_t * node,
      47             :                          u32 * buffers,
      48             :                          u32 next_buffer_stride,
      49             :                          u32 n_buffers,
      50             :                          u32 next_index,
      51             :                          u32 drop_error_node, u32 drop_error_code)
      52             : {
      53             :   u32 n_left_this_frame, n_buffers_left, *args, n_args_left;
      54             :   vlib_error_t drop_error;
      55             :   vlib_node_t *n;
      56             : 
      57          26 :   n = vlib_get_node (vm, drop_error_node);
      58          26 :   drop_error = n->error_heap_index + drop_error_code;
      59             : 
      60          26 :   n_buffers_left = n_buffers;
      61          52 :   while (n_buffers_left > 0)
      62             :     {
      63          26 :       vlib_get_next_frame (vm, node, next_index, args, n_args_left);
      64             : 
      65          26 :       n_left_this_frame = clib_min (n_buffers_left, n_args_left);
      66          26 :       n_buffers_left -= n_left_this_frame;
      67          26 :       n_args_left -= n_left_this_frame;
      68             : 
      69         154 :       while (n_left_this_frame >= 4)
      70             :         {
      71             :           u32 bi0, bi1, bi2, bi3;
      72             :           vlib_buffer_t *b0, *b1, *b2, *b3;
      73             : 
      74         128 :           args[0] = bi0 = buffers[0];
      75         128 :           args[1] = bi1 = buffers[1];
      76         128 :           args[2] = bi2 = buffers[2];
      77         128 :           args[3] = bi3 = buffers[3];
      78             : 
      79         128 :           b0 = vlib_get_buffer (vm, bi0);
      80         128 :           b1 = vlib_get_buffer (vm, bi1);
      81         128 :           b2 = vlib_get_buffer (vm, bi2);
      82         128 :           b3 = vlib_get_buffer (vm, bi3);
      83             : 
      84         128 :           b0->error = drop_error;
      85         128 :           b1->error = drop_error;
      86         128 :           b2->error = drop_error;
      87         128 :           b3->error = drop_error;
      88             : 
      89         128 :           buffers += 4;
      90         128 :           args += 4;
      91         128 :           n_left_this_frame -= 4;
      92             :         }
      93             : 
      94          51 :       while (n_left_this_frame >= 1)
      95             :         {
      96             :           u32 bi0;
      97             :           vlib_buffer_t *b0;
      98             : 
      99          25 :           args[0] = bi0 = buffers[0];
     100             : 
     101          25 :           b0 = vlib_get_buffer (vm, bi0);
     102          25 :           b0->error = drop_error;
     103             : 
     104          25 :           buffers += 1;
     105          25 :           args += 1;
     106          25 :           n_left_this_frame -= 1;
     107             :         }
     108             : 
     109          26 :       vlib_put_next_frame (vm, node, next_index, n_args_left);
     110             :     }
     111             : 
     112          26 :   return n_buffers;
     113             : }
     114             : 
     115             : static u8 *
     116     2278460 : format_stats_counter_name (u8 *s, va_list *va)
     117             : {
     118     2278460 :   u8 *id = va_arg (*va, u8 *);
     119             : 
     120    38557100 :   for (u32 i = 0; id[i] != 0; i++)
     121    36278600 :     vec_add1 (s, id[i] == ' ' ? ' ' : id[i]);
     122             : 
     123     2278460 :   return s;
     124             : }
     125             : 
     126             : void
     127      418928 : vlib_unregister_errors (vlib_main_t *vm, u32 node_index)
     128             : {
     129      418928 :   vlib_error_main_t *em = &vm->error_main;
     130      418928 :   vlib_node_t *n = vlib_get_node (vm, node_index);
     131             :   vlib_error_desc_t *cd;
     132             : 
     133      418928 :   if (n->n_errors > 0)
     134             :     {
     135         741 :       cd = vec_elt_at_index (em->counters_heap, n->error_heap_index);
     136        4713 :       for (u32 i = 0; i < n->n_errors; i++)
     137        3972 :         vlib_stats_remove_entry (cd[i].stats_entry_index);
     138         741 :       heap_dealloc (em->counters_heap, n->error_heap_handle);
     139         741 :       n->n_errors = 0;
     140             :     }
     141      418928 : }
     142             : 
     143             : /* Reserves given number of error codes for given node. */
     144             : void
     145      417408 : vlib_register_errors (vlib_main_t *vm, u32 node_index, u32 n_errors,
     146             :                       char *error_strings[], vlib_error_desc_t counters[])
     147             : {
     148      417408 :   vlib_error_main_t *em = &vm->error_main;
     149      417408 :   vlib_node_main_t *nm = &vm->node_main;
     150      417408 :   vlib_node_t *n = vlib_get_node (vm, node_index);
     151             :   vlib_error_desc_t *cd;
     152      417408 :   u32 n_threads = vlib_get_n_threads ();
     153      417408 :   elog_event_type_t t = {};
     154             :   uword l;
     155             :   u64 **sc;
     156             : 
     157      417408 :   ASSERT (vlib_get_thread_index () == 0);
     158             : 
     159      417408 :   vlib_stats_segment_lock ();
     160             : 
     161             :   /* Free up any previous error strings. */
     162      417408 :   vlib_unregister_errors (vm, node_index);
     163             : 
     164      417408 :   n->n_errors = n_errors;
     165      417408 :   n->error_counters = counters;
     166             : 
     167      417408 :   if (n_errors == 0)
     168      135616 :     goto done;
     169             : 
     170      281792 :   n->error_heap_index =
     171      281792 :     heap_alloc (em->counters_heap, n_errors, n->error_heap_handle);
     172      281792 :   l = vec_len (em->counters_heap);
     173      281792 :   cd = vec_elt_at_index (em->counters_heap, n->error_heap_index);
     174             : 
     175             :   /*  Legacy node */
     176      281792 :   if (!counters)
     177             :     {
     178      955921 :       for (int i = 0; i < n_errors; i++)
     179             :         {
     180      747182 :           cd[i].name = error_strings[i];
     181      747182 :           cd[i].desc = error_strings[i];
     182      747182 :           cd[i].severity = VL_COUNTER_SEVERITY_ERROR;
     183             :         }
     184             :     }
     185             :   else
     186       73053 :     clib_memcpy (cd, counters, n_errors * sizeof (counters[0]));
     187             : 
     188      281792 :   vec_validate (vm->error_elog_event_types, l - 1);
     189             : 
     190      281792 :   if (em->stats_err_entry_index == 0)
     191         575 :     em->stats_err_entry_index = vlib_stats_add_counter_vector ("/node/errors");
     192             : 
     193      281792 :   ASSERT (em->stats_err_entry_index != 0 && em->stats_err_entry_index != ~0);
     194             : 
     195      281792 :   vlib_stats_validate (em->stats_err_entry_index, n_threads - 1, l - 1);
     196      281792 :   sc = vlib_stats_get_entry_data_pointer (em->stats_err_entry_index);
     197             : 
     198      563760 :   for (int i = 0; i < n_threads; i++)
     199             :     {
     200      281968 :       vlib_main_t *tvm = vlib_get_main_by_index (i);
     201      281968 :       vlib_error_main_t *tem = &tvm->error_main;
     202      281968 :       tem->counters = sc[i];
     203             : 
     204             :       /* Zero counters for re-registrations of errors. */
     205      281968 :       if (n->error_heap_index + n_errors <= vec_len (tem->counters_last_clear))
     206           0 :         clib_memcpy (tem->counters + n->error_heap_index,
     207             :                      tem->counters_last_clear + n->error_heap_index,
     208             :                      n_errors * sizeof (tem->counters[0]));
     209             :       else
     210      281968 :         clib_memset (tem->counters + n->error_heap_index, 0,
     211             :                      n_errors * sizeof (tem->counters[0]));
     212             :     }
     213             : 
     214             :   /* Register counter indices in the stat segment directory */
     215     2560260 :   for (int i = 0; i < n_errors; i++)
     216     2278460 :     cd[i].stats_entry_index = vlib_stats_add_symlink (
     217     2278460 :       em->stats_err_entry_index, n->error_heap_index + i, "/err/%v/%U",
     218     2278460 :       n->name, format_stats_counter_name, cd[i].name);
     219             : 
     220      281792 :   vec_validate (nm->node_by_error, n->error_heap_index + n_errors - 1);
     221             : 
     222     2560260 :   for (u32 i = 0; i < n_errors; i++)
     223             :     {
     224     2278460 :       t.format = (char *) format (0, "%v %s: %%d", n->name, cd[i].name);
     225     2278460 :       vec_free (vm->error_elog_event_types[n->error_heap_index + i].format);
     226     2278460 :       vm->error_elog_event_types[n->error_heap_index + i] = t;
     227     2278460 :       nm->node_by_error[n->error_heap_index + i] = n->index;
     228             :     }
     229             : 
     230      281792 : done:
     231      417408 :   vlib_stats_segment_unlock ();
     232      417408 : }
     233             : 
     234             : uword
     235           4 : unformat_vlib_error (unformat_input_t *input, va_list *args)
     236             : {
     237           4 :   vlib_main_t *vm = va_arg (*args, vlib_main_t *);
     238           4 :   const vlib_error_main_t *em = &vm->error_main;
     239           4 :   vlib_error_t *error_index = va_arg (*args, vlib_error_t *);
     240             :   const vlib_node_t *node;
     241             :   char *error_name;
     242             :   u32 node_index;
     243             :   vlib_error_t i;
     244             : 
     245           4 :   if (!unformat (input, "%U.%s", unformat_vlib_node, vm, &node_index,
     246             :                  &error_name))
     247           2 :     return 0;
     248             : 
     249           2 :   node = vlib_get_node (vm, node_index);
     250          22 :   for (i = 0; i < node->n_errors; i++)
     251             :     {
     252          22 :       vlib_error_t ei = node->error_heap_index + i;
     253          22 :       if (strcmp (em->counters_heap[ei].name, error_name) == 0)
     254             :         {
     255           2 :           *error_index = ei;
     256           2 :           vec_free (error_name);
     257           2 :           return 1;
     258             :         }
     259             :     }
     260             : 
     261           0 :   vec_free (error_name);
     262           0 :   return 0;
     263             : }
     264             : 
     265             : static char *
     266       54781 : sev2str (enum vl_counter_severity_e s)
     267             : {
     268       54781 :   switch (s)
     269             :     {
     270       30941 :     case VL_COUNTER_SEVERITY_ERROR:
     271       30941 :       return "error";
     272           0 :     case VL_COUNTER_SEVERITY_WARN:
     273           0 :       return "warn";
     274       23840 :     case VL_COUNTER_SEVERITY_INFO:
     275       23840 :       return "info";
     276           0 :     default:
     277           0 :       return "unknown";
     278             :     }
     279             : }
     280             : 
     281             : static clib_error_t *
     282        8013 : show_errors (vlib_main_t * vm,
     283             :              unformat_input_t * input, vlib_cli_command_t * cmd)
     284             : {
     285        8013 :   vlib_error_main_t *em = &vm->error_main;
     286             :   vlib_node_t *n;
     287             :   u32 code, i, ni;
     288             :   u64 c;
     289        8013 :   int index = 0;
     290        8013 :   int verbose = 0;
     291        8013 :   u64 *sums = 0;
     292             : 
     293        8013 :   if (unformat (input, "verbose %d", &verbose))
     294             :     ;
     295        8013 :   else if (unformat (input, "verbose"))
     296           0 :     verbose = 1;
     297             : 
     298        8013 :   vec_validate (sums, vec_len (em->counters));
     299             : 
     300        8013 :   if (verbose)
     301           0 :     vlib_cli_output (vm, "%=10s%=35s%=35s%=10s%=6s", "Count", "Node",
     302             :                      "Reason", "Severity", "Index");
     303             :   else
     304        8013 :     vlib_cli_output (vm, "%=10s%=35s%=35s%=10s", "Count", "Node", "Reason",
     305             :                      "Severity");
     306             : 
     307       16050 :   foreach_vlib_main ()
     308             :     {
     309        8037 :       em = &this_vlib_main->error_main;
     310             : 
     311        8037 :       if (verbose)
     312           0 :         vlib_cli_output (vm, "Thread %u (%v):", index,
     313           0 :                          vlib_worker_threads[index].name);
     314             : 
     315     5802730 :       for (ni = 0; ni < vec_len (this_vlib_main->node_main.nodes); ni++)
     316             :         {
     317     5794690 :           n = vlib_get_node (this_vlib_main, ni);
     318    37589100 :           for (code = 0; code < n->n_errors; code++)
     319             :             {
     320    31794400 :               i = n->error_heap_index + code;
     321    31794400 :               c = em->counters[i];
     322    31794400 :               if (i < vec_len (em->counters_last_clear))
     323    31592600 :                 c -= em->counters_last_clear[i];
     324    31794400 :               sums[i] += c;
     325             : 
     326    31794400 :               if (c == 0 && verbose < 2)
     327    31739600 :                 continue;
     328             : 
     329       54781 :               if (verbose)
     330           0 :                 vlib_cli_output (vm, "%10lu%=35v%=35s%=10s%=6d", c, n->name,
     331           0 :                                  em->counters_heap[i].desc,
     332           0 :                                  sev2str (em->counters_heap[i].severity), i);
     333             :               else
     334      109562 :                 vlib_cli_output (vm, "%10lu%=35v%=35s%=10s", c, n->name,
     335       54781 :                                  em->counters_heap[i].desc,
     336       54781 :                                  sev2str (em->counters_heap[i].severity));
     337             :             }
     338             :         }
     339        8037 :       index++;
     340             :     }
     341             : 
     342        8013 :   if (verbose)
     343           0 :     vlib_cli_output (vm, "Total:");
     344             : 
     345     5785400 :   for (ni = 0; ni < vec_len (vm->node_main.nodes); ni++)
     346             :     {
     347     5777390 :       n = vlib_get_node (vm, ni);
     348    37476800 :       for (code = 0; code < n->n_errors; code++)
     349             :         {
     350    31699400 :           i = n->error_heap_index + code;
     351    31699400 :           if (sums[i])
     352             :             {
     353       54729 :               if (verbose)
     354           0 :                 vlib_cli_output (vm, "%10lu%=40v%=20s%=10d", sums[i], n->name,
     355           0 :                                  em->counters_heap[i].desc, i);
     356             :             }
     357             :         }
     358             :     }
     359             : 
     360        8013 :   vec_free (sums);
     361             : 
     362        8013 :   return 0;
     363             : }
     364             : 
     365             : /* *INDENT-OFF* */
     366      285289 : VLIB_CLI_COMMAND (vlib_cli_show_errors) = {
     367             :   .path = "show errors",
     368             :   .short_help = "Show error counts",
     369             :   .function = show_errors,
     370             : };
     371             : /* *INDENT-ON* */
     372             : 
     373             : /* *INDENT-OFF* */
     374      285289 : VLIB_CLI_COMMAND (cli_show_node_counters, static) = {
     375             :   .path = "show node counters",
     376             :   .short_help = "Show node counters",
     377             :   .function = show_errors,
     378             : };
     379             : /* *INDENT-ON* */
     380             : 
     381             : static clib_error_t *
     382        2942 : clear_error_counters (vlib_main_t * vm,
     383             :                       unformat_input_t * input, vlib_cli_command_t * cmd)
     384             : {
     385             :   vlib_error_main_t *em;
     386             :   u32 i;
     387             : 
     388        5900 :   foreach_vlib_main ()
     389             :     {
     390        2958 :       em = &this_vlib_main->error_main;
     391        2958 :       vec_validate (em->counters_last_clear, vec_len (em->counters) - 1);
     392    11704800 :       for (i = 0; i < vec_len (em->counters); i++)
     393    11701800 :         em->counters_last_clear[i] = em->counters[i];
     394             :     }
     395        2942 :   return 0;
     396             : }
     397             : 
     398             : /* *INDENT-OFF* */
     399      285289 : VLIB_CLI_COMMAND (cli_clear_error_counters, static) = {
     400             :   .path = "clear errors",
     401             :   .short_help = "Clear error counters",
     402             :   .function = clear_error_counters,
     403             : };
     404             : /* *INDENT-ON* */
     405             : 
     406             : /* *INDENT-OFF* */
     407      285289 : VLIB_CLI_COMMAND (cli_clear_node_counters, static) = {
     408             :   .path = "clear node counters",
     409             :   .short_help = "Clear node counters",
     410             :   .function = clear_error_counters,
     411             : };
     412             : /* *INDENT-ON* */
     413             : 
     414             : /*
     415             :  * fd.io coding-style-patch-verification: ON
     416             :  *
     417             :  * Local Variables:
     418             :  * eval: (c-set-style "gnu")
     419             :  * End:
     420             :  */

Generated by: LCOV version 1.14