LCOV - code coverage report
Current view: top level - vlib - drop.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 98 114 86.0 %
Date: 2023-10-26 01:39:38 Functions: 19 26 73.1 %

          Line data    Source code
       1             : /*
       2             :  * drop.c - Punt and drop nodes
       3             :  *
       4             :  * Copyright (c) 2015 Cisco and/or its affiliates.
       5             :  * Licensed under the Apache License, Version 2.0 (the "License");
       6             :  * you may not use this file except in compliance with the License.
       7             :  * You may obtain a copy of the License at:
       8             :  *
       9             :  *     http://www.apache.org/licenses/LICENSE-2.0
      10             :  *
      11             :  * Unless required by applicable law or agreed to in writing, software
      12             :  * distributed under the License is distributed on an "AS IS" BASIS,
      13             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14             :  * See the License for the specific language governing permissions and
      15             :  * limitations under the License.
      16             :  */
      17             : 
      18             : #include <vlib/vlib.h>
      19             : #include <vppinfra/vector/count_equal.h>
      20             : 
      21             : typedef enum
      22             : {
      23             :   ERROR_DISPOSITION_DROP,
      24             :   ERROR_DISPOSITION_PUNT,
      25             :   ERROR_N_DISPOSITION,
      26             : } error_disposition_t;
      27             : 
      28             : static u8 *
      29           0 : validate_error (vlib_main_t * vm, vlib_error_t * e, u32 index)
      30             : {
      31           0 :   uword node_index = vlib_error_get_node (&vm->node_main, e[0]);
      32           0 :   uword code = vlib_error_get_code (&vm->node_main, e[0]);
      33             :   vlib_node_t *n;
      34             : 
      35           0 :   if (node_index >= vec_len (vm->node_main.nodes))
      36           0 :     return format (0, "[%d], node index out of range 0x%x, error 0x%x",
      37           0 :                    index, node_index, e[0]);
      38             : 
      39           0 :   n = vlib_get_node (vm, node_index);
      40           0 :   if (code >= n->n_errors)
      41           0 :     return format (0, "[%d], code %d out of range for node %v",
      42             :                    index, code, n->name);
      43             : 
      44           0 :   return 0;
      45             : }
      46             : 
      47             : static u8 *
      48        4370 : validate_error_frame (vlib_main_t * vm,
      49             :                       vlib_node_runtime_t * node, vlib_frame_t * f)
      50             : {
      51        4370 :   u32 *buffers = vlib_frame_vector_args (f);
      52             :   vlib_buffer_t *b;
      53        4370 :   u8 *msg = 0;
      54             :   uword i;
      55             : 
      56        4370 :   for (i = 0; i < f->n_vectors; i++)
      57             :     {
      58           0 :       b = vlib_get_buffer (vm, buffers[i]);
      59           0 :       msg = validate_error (vm, &b->error, i);
      60           0 :       if (msg)
      61           0 :         return msg;
      62             :     }
      63             : 
      64        4370 :   return msg;
      65             : }
      66             : 
      67             : always_inline u32
      68       32488 : counter_index (vlib_main_t * vm, vlib_error_t e)
      69             : {
      70             :   vlib_node_t *n;
      71             :   u32 ci, ni;
      72             : 
      73       32488 :   ni = vlib_error_get_node (&vm->node_main, e);
      74       32488 :   n = vlib_get_node (vm, ni);
      75             : 
      76       32488 :   ci = vlib_error_get_code (&vm->node_main, e);
      77       32488 :   if (ci >= n->n_errors)
      78           0 :     return CLIB_U32_MAX;
      79             : 
      80       32488 :   ci += n->error_heap_index;
      81             : 
      82       32488 :   return ci;
      83             : }
      84             : 
      85             : static u8 *
      86       27974 : format_error_trace (u8 * s, va_list * va)
      87             : {
      88       27974 :   vlib_main_t *vm = va_arg (*va, vlib_main_t *);
      89       27974 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
      90       27974 :   vlib_error_t *e = va_arg (*va, vlib_error_t *);
      91             :   vlib_node_t *error_node;
      92       27974 :   vlib_error_main_t *em = &vm->error_main;
      93             :   u32 i;
      94             : 
      95       27974 :   error_node = vlib_get_node (vm, vlib_error_get_node (&vm->node_main, e[0]));
      96       27974 :   i = counter_index (vm, vlib_error_get_code (&vm->node_main, e[0])) +
      97       27974 :     error_node->error_heap_index;
      98       27974 :   if (i != CLIB_U32_MAX)
      99       27974 :     s = format (s, "%v: %s", error_node->name, em->counters_heap[i].desc);
     100             : 
     101       27974 :   return s;
     102             : }
     103             : 
     104             : static void
     105        2513 : trace_errors (vlib_main_t * vm,
     106             :               vlib_node_runtime_t * node, vlib_frame_t * frame)
     107             : {
     108             :   u32 n_left, *buffers;
     109             : 
     110        2513 :   buffers = vlib_frame_vector_args (frame);
     111        2513 :   n_left = frame->n_vectors;
     112             : 
     113       24319 :   while (n_left >= 4)
     114             :     {
     115             :       u32 bi0, bi1;
     116             :       vlib_buffer_t *b0, *b1;
     117             :       vlib_error_t *t0, *t1;
     118             : 
     119             :       /* Prefetch next iteration. */
     120       21806 :       vlib_prefetch_buffer_with_index (vm, buffers[2], LOAD);
     121       21806 :       vlib_prefetch_buffer_with_index (vm, buffers[3], LOAD);
     122             : 
     123       21806 :       bi0 = buffers[0];
     124       21806 :       bi1 = buffers[1];
     125             : 
     126       21806 :       b0 = vlib_get_buffer (vm, bi0);
     127       21806 :       b1 = vlib_get_buffer (vm, bi1);
     128             : 
     129       21806 :       if (b0->flags & VLIB_BUFFER_IS_TRACED)
     130             :         {
     131       21658 :           t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
     132       21658 :           t0[0] = b0->error;
     133             :         }
     134       21806 :       if (b1->flags & VLIB_BUFFER_IS_TRACED)
     135             :         {
     136       21656 :           t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
     137       21656 :           t1[0] = b1->error;
     138             :         }
     139       21806 :       buffers += 2;
     140       21806 :       n_left -= 2;
     141             :     }
     142             : 
     143        6988 :   while (n_left >= 1)
     144             :     {
     145             :       u32 bi0;
     146             :       vlib_buffer_t *b0;
     147             :       vlib_error_t *t0;
     148             : 
     149        4475 :       bi0 = buffers[0];
     150             : 
     151        4475 :       b0 = vlib_get_buffer (vm, bi0);
     152             : 
     153        4475 :       if (b0->flags & VLIB_BUFFER_IS_TRACED)
     154             :         {
     155        4455 :           t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
     156        4455 :           t0[0] = b0->error;
     157             :         }
     158        4475 :       buffers += 1;
     159        4475 :       n_left -= 1;
     160             :     }
     161        2513 : }
     162             : 
     163             : static_always_inline uword
     164        4370 : process_drop_punt (vlib_main_t * vm,
     165             :                    vlib_node_runtime_t * node,
     166             :                    vlib_frame_t * frame, error_disposition_t disposition)
     167             : {
     168             :   u32 errors[VLIB_FRAME_SIZE], *error, *from, n_left;
     169             :   vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
     170        4370 :   vlib_error_main_t *em = &vm->error_main;
     171             : 
     172        4370 :   from = vlib_frame_vector_args (frame);
     173        4370 :   n_left = frame->n_vectors;
     174        4370 :   b = bufs;
     175        4370 :   error = errors;
     176             : 
     177        4370 :   vlib_get_buffers (vm, from, bufs, n_left);
     178             : 
     179        4370 :   if (node->flags & VLIB_NODE_FLAG_TRACE)
     180        2513 :     trace_errors (vm, node, frame);
     181             : 
     182             :   /* collect the array of error first ... */
     183       16099 :   while (n_left >= 4)
     184             :     {
     185       11729 :       if (n_left >= 12)
     186             :         {
     187             :           /* Prefetch 8 ahead - there's not much going on in each iteration */
     188        9939 :           vlib_prefetch_buffer_header (b[4], LOAD);
     189        9939 :           vlib_prefetch_buffer_header (b[5], LOAD);
     190        9939 :           vlib_prefetch_buffer_header (b[6], LOAD);
     191        9939 :           vlib_prefetch_buffer_header (b[7], LOAD);
     192             :         }
     193       11729 :       error[0] = b[0]->error;
     194       11729 :       error[1] = b[1]->error;
     195       11729 :       error[2] = b[2]->error;
     196       11729 :       error[3] = b[3]->error;
     197             : 
     198       11729 :       error += 4;
     199       11729 :       n_left -= 4;
     200       11729 :       b += 4;
     201             :     }
     202        9829 :   while (n_left)
     203             :     {
     204        5459 :       error[0] = b[0]->error;
     205             : 
     206        5459 :       error += 1;
     207        5459 :       n_left -= 1;
     208        5459 :       b += 1;
     209             :     }
     210             : 
     211             :   /* ... then count against them in blocks */
     212        4370 :   n_left = frame->n_vectors;
     213             : 
     214        8884 :   while (n_left)
     215             :     {
     216             :       u16 off, count;
     217             :       u32 c_index;
     218             : 
     219        4514 :       off = frame->n_vectors - n_left;
     220             : 
     221        4514 :       error = errors + off;
     222             : 
     223        4514 :       count = clib_count_equal_u32 (error, n_left);
     224        4514 :       n_left -= count;
     225             : 
     226        4514 :       c_index = counter_index (vm, error[0]);
     227        4514 :       if (c_index != CLIB_U32_MAX)
     228        4514 :         em->counters[c_index] += count;
     229             : 
     230        4514 :       vlib_error_elog_count (vm, c_index, count);
     231             :     }
     232             : 
     233        4370 :   if (disposition == ERROR_DISPOSITION_DROP || !vm->os_punt_frame)
     234             :     {
     235        4370 :       vlib_buffer_free (vm, from, frame->n_vectors);
     236             : 
     237             :       /* If there is no punt function, free the frame as well. */
     238        4370 :       if (disposition == ERROR_DISPOSITION_PUNT && !vm->os_punt_frame)
     239         181 :         vlib_frame_free (vm, frame);
     240             :     }
     241             :   else
     242           0 :     vm->os_punt_frame (vm, node, frame);
     243             : 
     244        4370 :   return frame->n_vectors;
     245             : }
     246             : 
     247        6489 : VLIB_NODE_FN (error_drop_node) (vlib_main_t * vm,
     248             :                                 vlib_node_runtime_t * node,
     249             :                                 vlib_frame_t * frame)
     250             : {
     251        4189 :   return process_drop_punt (vm, node, frame, ERROR_DISPOSITION_DROP);
     252             : }
     253             : 
     254        2481 : VLIB_NODE_FN (error_punt_node) (vlib_main_t * vm,
     255             :                                 vlib_node_runtime_t * node,
     256             :                                 vlib_frame_t * frame)
     257             : {
     258         181 :   return process_drop_punt (vm, node, frame, ERROR_DISPOSITION_PUNT);
     259             : }
     260             : 
     261             : /* *INDENT-OFF* */
     262      183788 : VLIB_REGISTER_NODE (error_drop_node) = {
     263             :   .name = "drop",
     264             :   .flags = VLIB_NODE_FLAG_IS_DROP,
     265             :   .vector_size = sizeof (u32),
     266             :   .format_trace = format_error_trace,
     267             :   .validate_frame = validate_error_frame,
     268             : };
     269             : /* *INDENT-ON* */
     270             : 
     271             : /* *INDENT-OFF* */
     272      183788 : VLIB_REGISTER_NODE (error_punt_node) = {
     273             :   .name = "punt",
     274             :   .flags = (VLIB_NODE_FLAG_FRAME_NO_FREE_AFTER_DISPATCH
     275             :             | VLIB_NODE_FLAG_IS_PUNT),
     276             :   .vector_size = sizeof (u32),
     277             :   .format_trace = format_error_trace,
     278             :   .validate_frame = validate_error_frame,
     279             : };
     280             : /* *INDENT-ON* */
     281             : 
     282             : /*
     283             :  * fd.io coding-style-patch-verification: ON
     284             :  *
     285             :  * Local Variables:
     286             :  * eval: (c-set-style "gnu")
     287             :  * End:
     288             :  */

Generated by: LCOV version 1.14