LCOV - code coverage report
Current view: top level - vlib - trace.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 166 275 60.4 %
Date: 2023-10-26 01:39:38 Functions: 30 39 76.9 %

          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             :  * trace.c: VLIB trace buffer.
      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 <vlib/threads.h>
      42             : #include <vnet/classify/vnet_classify.h>
      43             : 
      44             : u8 *vnet_trace_placeholder;
      45             : 
      46             : /* Helper function for nodes which only trace buffer data. */
      47             : void
      48       33356 : vlib_trace_frame_buffers_only (vlib_main_t * vm,
      49             :                                vlib_node_runtime_t * node,
      50             :                                u32 * buffers,
      51             :                                uword n_buffers,
      52             :                                uword next_buffer_stride,
      53             :                                uword n_buffer_data_bytes_in_trace)
      54             : {
      55             :   u32 n_left, *from;
      56             : 
      57       33356 :   n_left = n_buffers;
      58       33356 :   from = buffers;
      59             : 
      60      505839 :   while (n_left >= 4)
      61             :     {
      62             :       u32 bi0, bi1;
      63             :       vlib_buffer_t *b0, *b1;
      64             :       u8 *t0, *t1;
      65             : 
      66             :       /* Prefetch next iteration. */
      67      472483 :       vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
      68      472512 :       vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
      69             : 
      70      472455 :       bi0 = from[0];
      71      472455 :       bi1 = from[1];
      72             : 
      73      472455 :       b0 = vlib_get_buffer (vm, bi0);
      74      472444 :       b1 = vlib_get_buffer (vm, bi1);
      75             : 
      76      472460 :       if (b0->flags & VLIB_BUFFER_IS_TRACED)
      77             :         {
      78      471939 :           t0 = vlib_add_trace (vm, node, b0, n_buffer_data_bytes_in_trace);
      79      471852 :           clib_memcpy_fast (t0, b0->data + b0->current_data,
      80             :                             n_buffer_data_bytes_in_trace);
      81             :         }
      82      472447 :       if (b1->flags & VLIB_BUFFER_IS_TRACED)
      83             :         {
      84      471921 :           t1 = vlib_add_trace (vm, node, b1, n_buffer_data_bytes_in_trace);
      85      471853 :           clib_memcpy_fast (t1, b1->data + b1->current_data,
      86             :                             n_buffer_data_bytes_in_trace);
      87             :         }
      88      472483 :       from += 2;
      89      472483 :       n_left -= 2;
      90             :     }
      91             : 
      92       95473 :   while (n_left >= 1)
      93             :     {
      94             :       u32 bi0;
      95             :       vlib_buffer_t *b0;
      96             :       u8 *t0;
      97             : 
      98       62117 :       bi0 = from[0];
      99             : 
     100       62117 :       b0 = vlib_get_buffer (vm, bi0);
     101             : 
     102       62117 :       if (b0->flags & VLIB_BUFFER_IS_TRACED)
     103             :         {
     104       62045 :           t0 = vlib_add_trace (vm, node, b0, n_buffer_data_bytes_in_trace);
     105       62045 :           clib_memcpy_fast (t0, b0->data + b0->current_data,
     106             :                             n_buffer_data_bytes_in_trace);
     107             :         }
     108       62117 :       from += 1;
     109       62117 :       n_left -= 1;
     110             :     }
     111       33356 : }
     112             : 
     113             : /* Free up all trace buffer memory. */
     114             : void
     115       17489 : clear_trace_buffer (void)
     116             : {
     117             :   int i;
     118             :   vlib_trace_main_t *tm;
     119             : 
     120       37553 :   foreach_vlib_main ()
     121             :     {
     122       20064 :       tm = &this_vlib_main->trace_main;
     123             : 
     124       20064 :       tm->trace_enable = 0;
     125       20064 :       vec_free (tm->nodes);
     126             :     }
     127             : 
     128       37553 :   foreach_vlib_main ()
     129             :     {
     130       20064 :       tm = &this_vlib_main->trace_main;
     131             : 
     132      555831 :       for (i = 0; i < vec_len (tm->trace_buffer_pool); i++)
     133      535767 :         if (!pool_is_free_index (tm->trace_buffer_pool, i))
     134      535767 :           vec_free (tm->trace_buffer_pool[i]);
     135       20064 :       pool_free (tm->trace_buffer_pool);
     136             :     }
     137       17489 : }
     138             : 
     139             : u8 *
     140      368934 : format_vlib_trace (u8 * s, va_list * va)
     141             : {
     142      368934 :   vlib_main_t *vm = va_arg (*va, vlib_main_t *);
     143      368934 :   vlib_trace_header_t *h = va_arg (*va, vlib_trace_header_t *);
     144      368934 :   vlib_trace_header_t *e = vec_end (h);
     145             :   vlib_node_t *node, *prev_node;
     146      368934 :   clib_time_t *ct = &vm->clib_time;
     147             :   f64 t;
     148             : 
     149      368934 :   prev_node = 0;
     150     4586550 :   while (h < e)
     151             :     {
     152     4217610 :       node = vlib_get_node (vm, h->node_index);
     153             : 
     154     4217610 :       if (node != prev_node)
     155             :         {
     156     4169020 :           t =
     157     4169020 :             (h->time - vm->cpu_time_main_loop_start) * ct->seconds_per_clock;
     158             :           s =
     159     4169020 :             format (s, "\n%U: %v", format_time_interval, "h:m:s:u", t,
     160             :                     node->name);
     161             :         }
     162     4217610 :       prev_node = node;
     163             : 
     164     4217610 :       if (node->format_trace)
     165     4217610 :         s = format (s, "\n  %U", node->format_trace, vm, node, h->data);
     166             :       else
     167           0 :         s = format (s, "\n  %U", node->format_buffer, h->data);
     168             : 
     169     4217610 :       h = vlib_trace_header_next (h);
     170             :     }
     171             : 
     172      368934 :   return s;
     173             : }
     174             : 
     175             : /* Root of all trace cli commands. */
     176             : /* *INDENT-OFF* */
     177      285289 : VLIB_CLI_COMMAND (trace_cli_command,static) = {
     178             :   .path = "trace",
     179             :   .short_help = "Packet tracer commands",
     180             : };
     181             : /* *INDENT-ON* */
     182             : 
     183             : int
     184     1790480 : trace_time_cmp (void *a1, void *a2)
     185             : {
     186     1790480 :   vlib_trace_header_t **t1 = a1;
     187     1790480 :   vlib_trace_header_t **t2 = a2;
     188     1790480 :   i64 dt = t1[0]->time - t2[0]->time;
     189     1790480 :   return dt < 0 ? -1 : (dt > 0 ? +1 : 0);
     190             : }
     191             : 
     192             : /*
     193             :  * Return 1 if this packet passes the trace filter, or 0 otherwise
     194             :  */
     195             : u32
     196           0 : filter_accept (vlib_trace_main_t * tm, vlib_trace_header_t * h)
     197             : {
     198           0 :   vlib_trace_header_t *e = vec_end (h);
     199             : 
     200           0 :   if (tm->filter_flag == 0)
     201           0 :     return 1;
     202             : 
     203             :   /*
     204             :    * When capturing a post-mortem dispatch trace,
     205             :    * toss all existing traces once per dispatch cycle.
     206             :    * So we can trace 4 billion pkts without running out of
     207             :    * memory...
     208             :    */
     209           0 :   if (tm->filter_flag == FILTER_FLAG_POST_MORTEM)
     210           0 :     return 0;
     211             : 
     212           0 :   if (tm->filter_flag == FILTER_FLAG_INCLUDE)
     213             :     {
     214           0 :       while (h < e)
     215             :         {
     216           0 :           if (h->node_index == tm->filter_node_index)
     217           0 :             return 1;
     218           0 :           h = vlib_trace_header_next (h);
     219             :         }
     220           0 :       return 0;
     221             :     }
     222             :   else                          /* FILTER_FLAG_EXCLUDE */
     223             :     {
     224           0 :       while (h < e)
     225             :         {
     226           0 :           if (h->node_index == tm->filter_node_index)
     227           0 :             return 0;
     228           0 :           h = vlib_trace_header_next (h);
     229             :         }
     230           0 :       return 1;
     231             :     }
     232             : 
     233             :   return 0;
     234             : }
     235             : 
     236             : /*
     237             :  * Remove traces from the trace buffer pool that don't pass the filter
     238             :  */
     239             : void
     240       32565 : trace_apply_filter (vlib_main_t * vm)
     241             : {
     242       32565 :   vlib_trace_main_t *tm = &vm->trace_main;
     243             :   vlib_trace_header_t **h;
     244       32565 :   vlib_trace_header_t ***traces_to_remove = 0;
     245             :   u32 index;
     246             :   u32 trace_index;
     247             :   u32 n_accepted;
     248             : 
     249             :   u32 accept;
     250             : 
     251       32565 :   if (tm->filter_flag == FILTER_FLAG_NONE)
     252       32565 :     return;
     253             : 
     254             :   /*
     255             :    * Ideally we would retain the first N traces that pass the filter instead
     256             :    * of any N traces.
     257             :    */
     258           0 :   n_accepted = 0;
     259             :   /* *INDENT-OFF* */
     260           0 :   pool_foreach (h, tm->trace_buffer_pool)
     261             :     {
     262           0 :       accept = filter_accept(tm, h[0]);
     263             : 
     264           0 :       if ((n_accepted == tm->filter_count) || !accept)
     265           0 :           vec_add1 (traces_to_remove, h);
     266             :       else
     267           0 :           n_accepted++;
     268             :   }
     269             :   /* *INDENT-ON* */
     270             : 
     271             :   /* remove all traces that we don't want to keep */
     272           0 :   for (index = 0; index < vec_len (traces_to_remove); index++)
     273             :     {
     274           0 :       trace_index = traces_to_remove[index] - tm->trace_buffer_pool;
     275           0 :       vec_set_len (tm->trace_buffer_pool[trace_index], 0);
     276           0 :       pool_put_index (tm->trace_buffer_pool, trace_index);
     277             :     }
     278             : 
     279           0 :   vec_free (traces_to_remove);
     280             : }
     281             : 
     282             : static clib_error_t *
     283       15013 : cli_show_trace_buffer (vlib_main_t * vm,
     284             :                        unformat_input_t * input, vlib_cli_command_t * cmd)
     285             : {
     286             :   vlib_trace_main_t *tm;
     287             :   vlib_trace_header_t **h, **traces;
     288       15013 :   u32 i, index = 0;
     289             :   char *fmt;
     290       15013 :   u8 *s = 0;
     291             :   u32 max;
     292             : 
     293             :   /*
     294             :    * By default display only this many traces. To display more, explicitly
     295             :    * specify a max. This prevents unexpectedly huge outputs.
     296             :    */
     297       15013 :   max = 50;
     298       16626 :   while (unformat_check_input (input) != (uword) UNFORMAT_END_OF_INPUT)
     299             :     {
     300        1613 :       if (unformat (input, "max %d", &max))
     301             :         ;
     302             :       else
     303           0 :         return clib_error_create ("expected 'max COUNT', got `%U'",
     304             :                                   format_unformat_error, input);
     305             :     }
     306             : 
     307             : 
     308             :   /* Get active traces from pool. */
     309             : 
     310       31501 :   foreach_vlib_main ()
     311             :     {
     312       16488 :       fmt = "------------------- Start of thread %d %s -------------------\n";
     313       16488 :       s = format (s, fmt, index, vlib_worker_threads[index].name);
     314             : 
     315       16488 :       tm = &this_vlib_main->trace_main;
     316             : 
     317       16488 :       trace_apply_filter (this_vlib_main);
     318             : 
     319       16488 :       traces = 0;
     320      567312 :       pool_foreach (h, tm->trace_buffer_pool)
     321             :         {
     322      550824 :           vec_add1 (traces, h[0]);
     323             :         }
     324             : 
     325       16488 :       if (vec_len (traces) == 0)
     326             :         {
     327        1411 :           s = format (s, "No packets in trace buffer\n");
     328        1411 :           goto done;
     329             :         }
     330             : 
     331             :       /* Sort them by increasing time. */
     332       15077 :       vec_sort_with_function (traces, trace_time_cmp);
     333             : 
     334      383911 :       for (i = 0; i < vec_len (traces); i++)
     335             :         {
     336      373663 :           if (i == max)
     337             :             {
     338        4829 :               char *warn = "Limiting display to %d packets."
     339             :                            " To display more specify max.";
     340        4829 :               vlib_cli_output (vm, warn, max);
     341        4829 :               s = format (s, warn, max);
     342        4829 :               goto done;
     343             :             }
     344             : 
     345      368834 :           s = format (s, "Packet %d\n%U\n\n", i + 1, format_vlib_trace, vm,
     346      368834 :                       traces[i]);
     347             :         }
     348             : 
     349       10248 :     done:
     350       16488 :       vec_free (traces);
     351             : 
     352       16488 :       index++;
     353             :     }
     354             : 
     355       15013 :   vlib_cli_output (vm, "%v", s);
     356       15013 :   vec_free (s);
     357       15013 :   return 0;
     358             : }
     359             : 
     360             : /* *INDENT-OFF* */
     361      285289 : VLIB_CLI_COMMAND (show_trace_cli,static) = {
     362             :   .path = "show trace",
     363             :   .short_help = "Show trace buffer [max COUNT]",
     364             :   .function = cli_show_trace_buffer,
     365             : };
     366             : /* *INDENT-ON* */
     367             : 
     368             : int vlib_enable_disable_pkt_trace_filter (int enable) __attribute__ ((weak));
     369             : 
     370             : int
     371           0 : vlib_enable_disable_pkt_trace_filter (int enable)
     372             : {
     373           0 :   return 0;
     374             : }
     375             : 
     376             : void
     377       17489 : vlib_trace_stop_and_clear (void)
     378             : {
     379       17489 :   vlib_enable_disable_pkt_trace_filter (0);     /* disble tracing */
     380       17489 :   clear_trace_buffer ();
     381       17489 : }
     382             : 
     383             : 
     384             : void
     385       15315 : trace_update_capture_options (u32 add, u32 node_index, u32 filter, u8 verbose)
     386             : {
     387             :   vlib_trace_main_t *tm;
     388             :   vlib_trace_node_t *tn;
     389             : 
     390       15315 :   if (add == ~0)
     391           0 :     add = 50;
     392             : 
     393       32887 :   foreach_vlib_main ()
     394             :     {
     395       17572 :       tm = &this_vlib_main->trace_main;
     396       17572 :       tm->verbose = verbose;
     397       17572 :       vec_validate (tm->nodes, node_index);
     398       17572 :       tn = tm->nodes + node_index;
     399             : 
     400             :       /*
     401             :        * Adding 0 makes no real sense, and there wa no other way
     402             :        * to explicilty zero-out the limits and count, so make
     403             :        * an "add 0" request really be "set to 0".
     404             :        */
     405       17572 :       if (add == 0)
     406           0 :           tn->limit = tn->count = 0;
     407             :       else
     408       17572 :           tn->limit += add;
     409             :     }
     410             : 
     411       32887 :   foreach_vlib_main ()
     412             :     {
     413       17572 :       tm = &this_vlib_main->trace_main;
     414       17572 :       tm->trace_enable = 1;
     415             :     }
     416             : 
     417       15315 :   vlib_enable_disable_pkt_trace_filter (! !filter);
     418       15315 : }
     419             : 
     420             : static clib_error_t *
     421       15315 : cli_add_trace_buffer (vlib_main_t * vm,
     422             :                       unformat_input_t * input, vlib_cli_command_t * cmd)
     423             : {
     424       15315 :   unformat_input_t _line_input, *line_input = &_line_input;
     425             :   vlib_node_t *node;
     426             :   u32 node_index, add;
     427       15315 :   u8 verbose = 0;
     428       15315 :   int filter = 0;
     429       15315 :   clib_error_t *error = 0;
     430             : 
     431       15315 :   if (!unformat_user (input, unformat_line_input, line_input))
     432           0 :     return 0;
     433             : 
     434       15315 :   if (vnet_trace_placeholder == 0)
     435         483 :     vec_validate_aligned (vnet_trace_placeholder, 2048,
     436             :                           CLIB_CACHE_LINE_BYTES);
     437             : 
     438       30635 :   while (unformat_check_input (line_input) != (uword) UNFORMAT_END_OF_INPUT)
     439             :     {
     440       15320 :       if (unformat (line_input, "%U %d",
     441             :                     unformat_vlib_node, vm, &node_index, &add))
     442             :         ;
     443           5 :       else if (unformat (line_input, "verbose"))
     444           0 :         verbose = 1;
     445           5 :       else if (unformat (line_input, "filter"))
     446           5 :         filter = 1;
     447             :       else
     448             :         {
     449           0 :           error = clib_error_create ("expected NODE COUNT, got `%U'",
     450             :                                      format_unformat_error, line_input);
     451           0 :           goto done;
     452             :         }
     453             :     }
     454             : 
     455       15315 :   node = vlib_get_node (vm, node_index);
     456             : 
     457       15315 :   if ((node->flags & VLIB_NODE_FLAG_TRACE_SUPPORTED) == 0)
     458             :     {
     459           0 :       error = clib_error_create ("node '%U' doesn't support per-node "
     460             :                                  "tracing. There may be another way to "
     461             :                                  "initiate trace on this node.",
     462             :                                  format_vlib_node_name, vm, node_index);
     463           0 :       goto done;
     464             :     }
     465             : 
     466       15315 :   u32 filter_table = classify_get_trace_chain ();
     467       15315 :   if (filter && filter_table == ~0)
     468             :     {
     469           0 :       error = clib_error_create ("No packet trace filter configured...");
     470           0 :       goto done;
     471             :     }
     472             : 
     473       15315 :   trace_update_capture_options (add, node_index, filter, verbose);
     474             : 
     475       15315 : done:
     476       15315 :   unformat_free (line_input);
     477             : 
     478       15315 :   return error;
     479             : }
     480             : 
     481             : /* *INDENT-OFF* */
     482      285289 : VLIB_CLI_COMMAND (add_trace_cli,static) = {
     483             :   .path = "trace add",
     484             :   .short_help = "trace add <input-graph-node> <add'l-pkts-for-node-> [filter] [verbose]",
     485             :   .function = cli_add_trace_buffer,
     486             : };
     487             : /* *INDENT-ON* */
     488             : 
     489             : /*
     490             :  * Configure a filter for packet traces.
     491             :  *
     492             :  * This supplements the packet trace feature so that only packets matching
     493             :  * the filter are included in the trace. Currently the only filter is to
     494             :  * keep packets that include a certain node in the trace or exclude a certain
     495             :  * node in the trace.
     496             :  *
     497             :  * The count of traced packets in the "trace add" command is still used to
     498             :  * create a certain number of traces. The "trace filter" command specifies
     499             :  * how many of those packets should be retained in the trace.
     500             :  *
     501             :  * For example, 1Mpps of traffic is arriving and one of those packets is being
     502             :  * dropped. To capture the trace for only that dropped packet, you can do:
     503             :  *     trace filter include error-drop 1
     504             :  *     trace add dpdk-input 1000000
     505             :  *     <wait one second>
     506             :  *     show trace
     507             :  *
     508             :  * Note that the filter could be implemented by capturing all traces and just
     509             :  * reducing traces displayed by the "show trace" function. But that would
     510             :  * require a lot of memory for storing the traces, making that infeasible.
     511             :  *
     512             :  * To remove traces from the trace pool that do not include a certain node
     513             :  * requires that the trace be "complete" before applying the filter. To
     514             :  * accomplish this, the trace pool is filtered upon each iteraction of the
     515             :  * main vlib loop. Doing so keeps the number of allocated traces down to a
     516             :  * reasonably low number. This requires that tracing for a buffer is not
     517             :  * performed after the vlib main loop interation completes. i.e. you can't
     518             :  * save away a buffer temporarily then inject it back into the graph and
     519             :  * expect that the trace_index is still valid (such as a traffic manager might
     520             :  * do). A new trace buffer should be allocated for those types of packets.
     521             :  *
     522             :  * The filter can be extended to support multiple nodes and other match
     523             :  * criteria (e.g. input sw_if_index, mac address) but for now just checks if
     524             :  * a specified node is in the trace or not in the trace.
     525             :  */
     526             : 
     527             : void
     528           0 : trace_filter_set (u32 node_index, u32 flag, u32 count)
     529             : {
     530           0 :   foreach_vlib_main ()
     531             :     {
     532             :       vlib_trace_main_t *tm;
     533             : 
     534           0 :       tm = &this_vlib_main->trace_main;
     535           0 :       tm->filter_node_index = node_index;
     536           0 :       tm->filter_flag = flag;
     537           0 :       tm->filter_count = count;
     538             : 
     539             :       /*
     540             :        * Clear the trace limits to stop any in-progress tracing
     541             :        * Prevents runaway trace allocations when the filter changes
     542             :        * (or is removed)
     543             :        */
     544           0 :       vec_free (tm->nodes);
     545             :     }
     546           0 : }
     547             : 
     548             : 
     549             : static clib_error_t *
     550           0 : cli_filter_trace (vlib_main_t * vm,
     551             :                   unformat_input_t * input, vlib_cli_command_t * cmd)
     552             : {
     553             :   u32 filter_node_index;
     554             :   u32 filter_flag;
     555             :   u32 filter_count;
     556             : 
     557           0 :   if (unformat (input, "include %U %d",
     558             :                 unformat_vlib_node, vm, &filter_node_index, &filter_count))
     559             :     {
     560           0 :       filter_flag = FILTER_FLAG_INCLUDE;
     561             :     }
     562           0 :   else if (unformat (input, "exclude %U %d",
     563             :                      unformat_vlib_node, vm, &filter_node_index,
     564             :                      &filter_count))
     565             :     {
     566           0 :       filter_flag = FILTER_FLAG_EXCLUDE;
     567             :     }
     568           0 :   else if (unformat (input, "none"))
     569             :     {
     570           0 :       filter_flag = FILTER_FLAG_NONE;
     571           0 :       filter_node_index = 0;
     572           0 :       filter_count = 0;
     573             :     }
     574             :   else
     575             :     return
     576           0 :       clib_error_create
     577             :       ("expected 'include NODE COUNT' or 'exclude NODE COUNT' or 'none', got `%U'",
     578             :        format_unformat_error, input);
     579             : 
     580           0 :   trace_filter_set (filter_node_index, filter_flag, filter_count);
     581             : 
     582           0 :   return 0;
     583             : }
     584             : 
     585             : /* *INDENT-OFF* */
     586      285289 : VLIB_CLI_COMMAND (filter_trace_cli,static) = {
     587             :   .path = "trace filter",
     588             :   .short_help = "trace filter none | [include|exclude] NODE COUNT",
     589             :   .function = cli_filter_trace,
     590             : };
     591             : /* *INDENT-ON* */
     592             : 
     593             : static clib_error_t *
     594       17489 : cli_clear_trace_buffer (vlib_main_t * vm,
     595             :                         unformat_input_t * input, vlib_cli_command_t * cmd)
     596             : {
     597       17489 :   vlib_trace_stop_and_clear ();
     598       17489 :   return 0;
     599             : }
     600             : 
     601             : /* *INDENT-OFF* */
     602      285289 : VLIB_CLI_COMMAND (clear_trace_cli,static) = {
     603             :   .path = "clear trace",
     604             :   .short_help = "Clear trace buffer and free memory",
     605             :   .function = cli_clear_trace_buffer,
     606             : };
     607             : /* *INDENT-ON* */
     608             : 
     609             : /* Placeholder function to get us linked in. */
     610             : void
     611         575 : vlib_trace_cli_reference (void)
     612             : {
     613         575 : }
     614             : 
     615             : void *
     616     6093550 : vlib_add_trace (vlib_main_t * vm,
     617             :                 vlib_node_runtime_t * r, vlib_buffer_t * b, u32 n_data_bytes)
     618             : {
     619     6093550 :   return vlib_add_trace_inline (vm, r, b, n_data_bytes);
     620             : }
     621             : 
     622             : vlib_is_packet_traced_fn_t *
     623           0 : vlib_is_packet_traced_function_from_name (const char *name)
     624             : {
     625           0 :   vlib_trace_filter_function_registration_t *reg =
     626             :     vlib_trace_filter_main.trace_filter_registration;
     627           0 :   while (reg)
     628             :     {
     629           0 :       if (clib_strcmp (reg->name, name) == 0)
     630           0 :         break;
     631           0 :       reg = reg->next;
     632             :     }
     633           0 :   if (!reg)
     634           0 :     return 0;
     635           0 :   return reg->function;
     636             : }
     637             : 
     638             : vlib_is_packet_traced_fn_t *
     639        1150 : vlib_is_packet_traced_default_function ()
     640             : {
     641        1150 :   vlib_trace_filter_function_registration_t *reg =
     642             :     vlib_trace_filter_main.trace_filter_registration;
     643        1150 :   vlib_trace_filter_function_registration_t *tmp_reg = reg;
     644        3450 :   while (reg)
     645             :     {
     646        2300 :       if (reg->priority > tmp_reg->priority)
     647        1150 :         tmp_reg = reg;
     648        2300 :       reg = reg->next;
     649             :     }
     650        1150 :   return tmp_reg->function;
     651             : }
     652             : 
     653             : static clib_error_t *
     654         575 : vlib_trace_filter_function_init (vlib_main_t *vm)
     655             : {
     656             :   vlib_is_packet_traced_fn_t *default_fn =
     657         575 :     vlib_is_packet_traced_default_function ();
     658        1150 :   foreach_vlib_main ()
     659             :     {
     660         575 :       vlib_trace_main_t *tm = &this_vlib_main->trace_main;
     661         575 :       tm->current_trace_filter_function = default_fn;
     662             :     }
     663         575 :   return 0;
     664             : }
     665             : 
     666             : vlib_trace_filter_main_t vlib_trace_filter_main;
     667             : 
     668        5183 : VLIB_INIT_FUNCTION (vlib_trace_filter_function_init);
     669             : 
     670             : static clib_error_t *
     671           0 : show_trace_filter_function (vlib_main_t *vm, unformat_input_t *input,
     672             :                             vlib_cli_command_t *cmd)
     673             : {
     674           0 :   vlib_trace_filter_main_t *tfm = &vlib_trace_filter_main;
     675           0 :   vlib_trace_main_t *tm = &vm->trace_main;
     676           0 :   vlib_is_packet_traced_fn_t *current_trace_filter_fn =
     677             :     tm->current_trace_filter_function;
     678           0 :   vlib_trace_filter_function_registration_t *reg =
     679             :     tfm->trace_filter_registration;
     680             : 
     681           0 :   while (reg)
     682             :     {
     683           0 :       vlib_cli_output (vm, "%sname:%s description: %s priority: %u",
     684           0 :                        reg->function == current_trace_filter_fn ? "(*) " : "",
     685             :                        reg->name, reg->description, reg->priority);
     686           0 :       reg = reg->next;
     687             :     }
     688           0 :   return 0;
     689             : }
     690             : 
     691      285289 : VLIB_CLI_COMMAND (show_trace_filter_function_cli, static) = {
     692             :   .path = "show trace filter function",
     693             :   .short_help = "show trace filter function",
     694             :   .function = show_trace_filter_function,
     695             : };
     696             : 
     697             : uword
     698           0 : unformat_vlib_trace_filter_function (unformat_input_t *input, va_list *args)
     699             : {
     700           0 :   vlib_is_packet_traced_fn_t **res =
     701             :     va_arg (*args, vlib_is_packet_traced_fn_t **);
     702           0 :   vlib_trace_filter_main_t *tfm = &vlib_trace_filter_main;
     703             : 
     704           0 :   vlib_trace_filter_function_registration_t *reg =
     705             :     tfm->trace_filter_registration;
     706           0 :   while (reg)
     707             :     {
     708           0 :       if (unformat (input, reg->name))
     709             :         {
     710           0 :           *res = reg->function;
     711           0 :           return 1;
     712             :         }
     713           0 :       reg = reg->next;
     714             :     }
     715           0 :   return 0;
     716             : }
     717             : 
     718             : void
     719           0 : vlib_set_trace_filter_function (vlib_is_packet_traced_fn_t *x)
     720             : {
     721           0 :   foreach_vlib_main ()
     722             :     {
     723           0 :       this_vlib_main->trace_main.current_trace_filter_function = x;
     724             :     }
     725           0 : }
     726             : 
     727             : static clib_error_t *
     728           0 : set_trace_filter_function (vlib_main_t *vm, unformat_input_t *input,
     729             :                            vlib_cli_command_t *cmd)
     730             : {
     731           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     732           0 :   vlib_is_packet_traced_fn_t *res = 0;
     733           0 :   clib_error_t *error = 0;
     734             : 
     735           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     736           0 :     return 0;
     737             : 
     738           0 :   while (unformat_check_input (line_input) != (uword) UNFORMAT_END_OF_INPUT)
     739             :     {
     740           0 :       if (unformat (line_input, "%U", unformat_vlib_trace_filter_function,
     741             :                     &res))
     742             :         ;
     743             :       else
     744             :         {
     745           0 :           error = clib_error_create (
     746             :             "expected valid trace filter function, got `%U'",
     747             :             format_unformat_error, line_input);
     748           0 :           goto done;
     749             :         }
     750             :     }
     751           0 :   vlib_set_trace_filter_function (res);
     752             : 
     753           0 : done:
     754           0 :   unformat_free (line_input);
     755             : 
     756           0 :   return error;
     757             : }
     758             : 
     759      285289 : VLIB_CLI_COMMAND (set_trace_filter_function_cli, static) = {
     760             :   .path = "set trace filter function",
     761             :   .short_help = "set trace filter function <func_name>",
     762             :   .function = set_trace_filter_function,
     763             : };
     764             : /*
     765             :  * fd.io coding-style-patch-verification: ON
     766             :  *
     767             :  * Local Variables:
     768             :  * eval: (c-set-style "gnu")
     769             :  * End:
     770             :  */

Generated by: LCOV version 1.14