LCOV - code coverage report
Current view: top level - vlib - punt.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 174 213 81.7 %
Date: 2023-10-26 01:39:38 Functions: 31 34 91.2 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2019 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             : #include <vlib/punt.h>
      17             : 
      18             : /**
      19             :  * The last allocated punt reason
      20             :  * Value 0 is reserved for invalid index.
      21             :  */
      22             : static vlib_punt_reason_t punt_reason_last = 1;
      23             : 
      24             : /**
      25             :  * Counters per punt-reason
      26             :  */
      27             : vlib_combined_counter_main_t punt_counters = {
      28             :   .name = "punt",
      29             :   .stat_segment_name = "/net/punt",
      30             : };
      31             : 
      32             : /**
      33             :  * A punt reason
      34             :  */
      35             : typedef struct punt_reason_data_t_
      36             : {
      37             :   /**
      38             :    * The reason name
      39             :    */
      40             :   u8 *pd_name;
      41             : 
      42             :   /**
      43             :    * The allocated reason value
      44             :    */
      45             :   vlib_punt_reason_t pd_reason;
      46             : 
      47             :   /**
      48             :    * Clients/owners that have registered this reason
      49             :    */
      50             :   u32 *pd_owners;
      51             : 
      52             :   /**
      53             :    * clients interested/listening to this reason
      54             :    */
      55             :   u32 pd_users;
      56             : 
      57             :   /**
      58             :    * function to invoke if a client becomes interested in the code.
      59             :    */
      60             :   punt_interested_listener_t pd_fn;
      61             : 
      62             :   /**
      63             :    * Data to pass to the callback
      64             :    */
      65             :   void *pd_data;
      66             : 
      67             :   /**
      68             :    * Flags associated to the reason
      69             :    */
      70             :   u32 flags;
      71             : 
      72             :   /**
      73             :    * Formatting function for flags;
      74             :    */
      75             :   format_function_t *flags_format;
      76             : } punt_reason_data_t;
      77             : 
      78             : /**
      79             :  * data for each punt reason
      80             :  */
      81             : static punt_reason_data_t *punt_reason_data;
      82             : 
      83             : typedef enum punt_format_flags_t_
      84             : {
      85             :   PUNT_FORMAT_FLAG_NONE = 0,
      86             :   PUNT_FORMAT_FLAG_DETAIL = (1 << 0),
      87             : } punt_format_flags_t;
      88             : 
      89             : /**
      90             :  * A registration, by a client, to direct punted traffic to a given node
      91             :  */
      92             : typedef struct punt_reg_t_
      93             : {
      94             :   /**
      95             :    * Reason the packets were punted
      96             :    */
      97             :   vlib_punt_reason_t pr_reason;
      98             : 
      99             :   /**
     100             :    * number of clients that have made this registration
     101             :    */
     102             :   u16 pr_locks;
     103             : 
     104             :   /**
     105             :    * The edge from the punt dispatch node to the requested node
     106             :    */
     107             :   u16 pr_edge;
     108             : 
     109             :   /**
     110             :    * node-index to send punted packets to
     111             :    */
     112             :   u32 pr_node_index;
     113             : } punt_reg_t;
     114             : 
     115             : /**
     116             :  * Pool of registrations
     117             :  */
     118             : static punt_reg_t *punt_reg_pool;
     119             : 
     120             : /**
     121             :  * A DB of all the register nodes against punt reason and node index
     122             :  */
     123             : static uword *punt_reg_db;
     124             : 
     125             : /**
     126             :  * A DB used in the DP per-reason to dispatch packets to the requested nodes.
     127             :  * this is a vector of edges per-reason
     128             :  */
     129             : u16 **punt_dp_db;
     130             : 
     131             : /**
     132             :  * A client using the punt serivce and its registrations
     133             :  */
     134             : typedef struct punt_client_t_
     135             : {
     136             :   /**
     137             :    * The name of the client
     138             :    */
     139             :   u8 *pc_name;
     140             : 
     141             :   /**
     142             :    * The registrations is has made
     143             :    */
     144             :   u32 *pc_regs;
     145             : } punt_client_t;
     146             : 
     147             : /**
     148             :  * Pool of clients
     149             :  */
     150             : static punt_client_t *punt_client_pool;
     151             : 
     152             : /**
     153             :  * DB of clients key'd by their name
     154             :  */
     155             : static uword *punt_client_db;
     156             : 
     157             : u8 *
     158        1720 : format_vlib_punt_reason (u8 * s, va_list * args)
     159             : {
     160        1720 :   vlib_punt_reason_t pr = va_arg (*args, int);
     161        1720 :   format_function_t *flags_format = punt_reason_data[pr].flags_format;
     162        1720 :   u32 flags = punt_reason_data[pr].flags;
     163        1720 :   if (flags_format)
     164        1715 :     return (format (s, "[%d] %v flags: %U", pr, punt_reason_data[pr].pd_name,
     165             :                     flags_format, flags));
     166             :   else
     167           5 :     return (format (s, "[%d] %v", pr, punt_reason_data[pr].pd_name));
     168             : }
     169             : 
     170             : vlib_punt_hdl_t
     171        1174 : vlib_punt_client_register (const char *who)
     172             : {
     173             :   u8 *pc_name;
     174             :   uword *p;
     175             :   u32 pci;
     176             : 
     177        1174 :   pc_name = format (NULL, "%s", who);
     178        2348 :   p = hash_get_mem (punt_client_db, pc_name);
     179             : 
     180        1174 :   if (NULL == p)
     181             :     {
     182             :       punt_client_t *pc;
     183             : 
     184        1174 :       pool_get (punt_client_pool, pc);
     185        1174 :       pci = pc - punt_client_pool;
     186             : 
     187        1174 :       pc->pc_name = pc_name;
     188             : 
     189        2348 :       hash_set_mem (punt_client_db, pc->pc_name, pci);
     190             :     }
     191             :   else
     192             :     {
     193           0 :       pci = p[0];
     194           0 :       vec_free (pc_name);
     195             :     }
     196             : 
     197        1174 :   return (pci);
     198             : }
     199             : 
     200             : static int
     201        2336 : punt_validate_client (vlib_punt_hdl_t client)
     202             : {
     203        2336 :   return (!pool_is_free_index (punt_client_pool, client));
     204             : }
     205             : 
     206             : static u64
     207         104 : punt_reg_mk_key (vlib_punt_reason_t reason, u32 node_index)
     208             : {
     209         104 :   return (((u64) node_index) << 32 | reason);
     210             : }
     211             : 
     212             : static u32
     213          53 : punt_reg_find (vlib_punt_reason_t reason, u32 node_index)
     214             : {
     215             :   uword *p;
     216             : 
     217          53 :   p = hash_get (punt_reg_db, punt_reg_mk_key (reason, node_index));
     218             : 
     219          53 :   if (p)
     220          21 :     return p[0];
     221             : 
     222          32 :   return ~0;
     223             : }
     224             : 
     225             : static void
     226          32 : punt_reg_add (const punt_reg_t * pr)
     227             : {
     228          32 :   hash_set (punt_reg_db, punt_reg_mk_key (pr->pr_reason,
     229             :                                           pr->pr_node_index),
     230             :             pr - punt_reg_pool);
     231          32 : }
     232             : 
     233             : static void
     234          19 : punt_reg_remove (const punt_reg_t * pr)
     235             : {
     236          19 :   hash_unset (punt_reg_db, punt_reg_mk_key (pr->pr_reason,
     237             :                                             pr->pr_node_index));
     238          19 : }
     239             : 
     240             : /**
     241             :  * reconstruct the DP per-reason DB
     242             :  */
     243             : static void
     244        2353 : punt_reg_mk_dp (vlib_punt_reason_t reason)
     245             : {
     246             :   u32 pri, *prip, *pris;
     247             :   const punt_reg_t *pr;
     248             :   u16 *edges, *old;
     249             :   u64 key;
     250             : 
     251        2353 :   pris = NULL;
     252        2353 :   edges = NULL;
     253        2353 :   vec_validate (punt_dp_db, reason);
     254             : 
     255        2353 :   old = punt_dp_db[reason];
     256             : 
     257             :   /* *INDENT-OFF* */
     258        5660 :   hash_foreach (key, pri, punt_reg_db,
     259             :     ({
     260             :       vec_add1(pris, pri);
     261             :     }));
     262             :   /* *INDENT-ON* */
     263             : 
     264             :   /*
     265             :    * A check for an empty vector is done in the DP, so the a zero
     266             :    * length vector here is ok
     267             :    */
     268        2396 :   vec_foreach (prip, pris)
     269             :   {
     270          43 :     pr = pool_elt_at_index (punt_reg_pool, *prip);
     271             : 
     272          43 :     if (pr->pr_reason == reason)
     273          34 :       vec_add1 (edges, pr->pr_edge);
     274             :   }
     275             : 
     276             :   /* atomic update of the DP */
     277        2353 :   punt_dp_db[reason] = edges;
     278             : 
     279        2353 :   vec_free (old);
     280        2353 : }
     281             : 
     282             : int
     283          34 : vlib_punt_register (vlib_punt_hdl_t client,
     284             :                     vlib_punt_reason_t reason, const char *node_name)
     285             : {
     286             :   vlib_node_t *punt_to, *punt_from;
     287             :   punt_client_t *pc;
     288             :   vlib_main_t *vm;
     289             :   punt_reg_t *pr;
     290             :   u32 pri;
     291             : 
     292          34 :   if (reason >= punt_reason_last)
     293           0 :     return -1;
     294          34 :   if (!punt_validate_client (client))
     295           0 :     return -2;
     296             : 
     297          34 :   vm = vlib_get_main ();
     298          34 :   pc = pool_elt_at_index (punt_client_pool, client);
     299          34 :   punt_to = vlib_get_node_by_name (vm, (u8 *) node_name);
     300          34 :   punt_from = vlib_get_node_by_name (vm, (u8 *) "punt-dispatch");
     301             : 
     302             :   /*
     303             :    * find a global matching registration
     304             :    */
     305          34 :   pri = punt_reg_find (reason, punt_to->index);
     306             : 
     307          34 :   if (~0 != pri)
     308             :     {
     309             :       u32 pos;
     310             : 
     311           3 :       pos = vec_search (pc->pc_regs, pri);
     312             : 
     313           2 :       if (~0 != pos)
     314             :         {
     315             :           /* duplicate registration for this client */
     316           2 :           return -1;
     317             :         }
     318             : 
     319           0 :       pr = pool_elt_at_index (punt_reg_pool, pri);
     320             :     }
     321             :   else
     322             :     {
     323          32 :       pool_get (punt_reg_pool, pr);
     324             : 
     325          32 :       pr->pr_reason = reason;
     326          32 :       pr->pr_node_index = punt_to->index;
     327          64 :       pr->pr_edge = vlib_node_add_next (vm,
     328          32 :                                         punt_from->index, pr->pr_node_index);
     329             : 
     330          32 :       pri = pr - punt_reg_pool;
     331             : 
     332          32 :       if (0 == punt_reason_data[reason].pd_users++ &&
     333          30 :           NULL != punt_reason_data[reason].pd_fn)
     334          28 :         punt_reason_data[reason].pd_fn (VLIB_ENABLE,
     335          28 :                                         punt_reason_data[reason].pd_data);
     336             : 
     337          32 :       punt_reg_add (pr);
     338             :     }
     339             : 
     340             :   /*
     341             :    * add this reg to the list the client has made
     342             :    */
     343          32 :   pr->pr_locks++;
     344          32 :   vec_add1 (pc->pc_regs, pri);
     345             : 
     346          32 :   punt_reg_mk_dp (reason);
     347             : 
     348          32 :   return 0;
     349             : }
     350             : 
     351             : int
     352          19 : vlib_punt_unregister (vlib_punt_hdl_t client,
     353             :                       vlib_punt_reason_t reason, const char *node_name)
     354             : {
     355             :   vlib_node_t *punt_to;
     356             :   punt_client_t *pc;
     357             :   vlib_main_t *vm;
     358             :   punt_reg_t *pr;
     359             :   u32 pri;
     360             : 
     361          19 :   if (reason >= punt_reason_last)
     362           0 :     return -1;
     363             : 
     364          19 :   vm = vlib_get_main ();
     365          19 :   pc = pool_elt_at_index (punt_client_pool, client);
     366          19 :   punt_to = vlib_get_node_by_name (vm, (u8 *) node_name);
     367             : 
     368             :   /*
     369             :    * construct a registration and check if it's one this client already has
     370             :    */
     371          19 :   pri = punt_reg_find (reason, punt_to->index);
     372             : 
     373          19 :   if (~0 != pri)
     374             :     {
     375             :       u32 pos;
     376             : 
     377          19 :       pos = vec_search (pc->pc_regs, pri);
     378             : 
     379          19 :       if (~0 == pos)
     380             :         {
     381             :           /* not a registration for this client */
     382           0 :           return -1;
     383             :         }
     384          19 :       vec_del1 (pc->pc_regs, pos);
     385             : 
     386          19 :       pr = pool_elt_at_index (punt_reg_pool, pri);
     387             : 
     388          19 :       pr->pr_locks--;
     389             : 
     390          19 :       if (0 == pr->pr_locks)
     391             :         {
     392          19 :           if (0 == --punt_reason_data[reason].pd_users &&
     393          19 :               NULL != punt_reason_data[reason].pd_fn)
     394          19 :             punt_reason_data[reason].pd_fn (VLIB_DISABLE,
     395          19 :                                             punt_reason_data[reason].pd_data);
     396          19 :           punt_reg_remove (pr);
     397          19 :           pool_put (punt_reg_pool, pr);
     398             :         }
     399             :     }
     400             : 
     401             :   /*
     402             :    * rebuild the DP data-base
     403             :    */
     404          19 :   punt_reg_mk_dp (reason);
     405             : 
     406          19 :   return (0);
     407             : }
     408             : 
     409             : int
     410          10 : vlib_punt_reason_validate (vlib_punt_reason_t reason)
     411             : {
     412          10 :   if (reason < punt_reason_last)
     413          10 :     return (0);
     414             : 
     415           0 :   return (-1);
     416             : }
     417             : 
     418             : u32
     419           0 : vlib_punt_reason_get_flags (vlib_punt_reason_t pr)
     420             : {
     421           0 :   return pr < punt_reason_last ? punt_reason_data[pr].flags : 0;
     422             : }
     423             : 
     424             : int
     425        2302 : vlib_punt_reason_alloc (vlib_punt_hdl_t client, const char *reason_name,
     426             :                         punt_interested_listener_t fn, void *data,
     427             :                         vlib_punt_reason_t *reason, u32 flags,
     428             :                         format_function_t *flags_format)
     429             : {
     430             :   vlib_punt_reason_t new;
     431             : 
     432        2302 :   if (!punt_validate_client (client))
     433           0 :     return -2;
     434             : 
     435        2302 :   new = punt_reason_last++;
     436        2302 :   vec_validate (punt_reason_data, new);
     437        2302 :   punt_reason_data[new].pd_name = format (NULL, "%s", reason_name);
     438        2302 :   punt_reason_data[new].pd_reason = new;
     439        2302 :   punt_reason_data[new].pd_fn = fn;
     440        2302 :   punt_reason_data[new].pd_data = data;
     441        2302 :   punt_reason_data[new].flags = flags;
     442        2302 :   punt_reason_data[new].flags_format = flags_format;
     443        2302 :   vec_add1 (punt_reason_data[new].pd_owners, client);
     444             : 
     445        2302 :   vlib_validate_combined_counter (&punt_counters, new);
     446        2302 :   vlib_zero_combined_counter (&punt_counters, new);
     447             : 
     448        2302 :   *reason = new;
     449             : 
     450             :   /* build the DP data-base */
     451        2302 :   punt_reg_mk_dp (*reason);
     452             : 
     453        2302 :   return (0);
     454             : }
     455             : 
     456             : void
     457           4 : punt_reason_walk (punt_reason_walk_cb_t cb, void *ctx)
     458             : {
     459             :   punt_reason_data_t *pd;
     460             : 
     461          24 :   for (pd = punt_reason_data + 1; pd < vec_end (punt_reason_data); pd++)
     462             :     {
     463          20 :       cb (pd->pd_reason, pd->pd_name, ctx);
     464             :     }
     465           4 : }
     466             : 
     467             : /* Parse node name -> node index. */
     468             : uword
     469           0 : unformat_punt_client (unformat_input_t * input, va_list * args)
     470             : {
     471           0 :   u32 *result = va_arg (*args, u32 *);
     472             : 
     473           0 :   return unformat_user (input, unformat_hash_vec_string,
     474             :                         punt_client_db, result);
     475             : }
     476             : 
     477             : /* Parse punt reason */
     478             : uword
     479           0 : unformat_punt_reason (unformat_input_t *input, va_list *args)
     480             : {
     481           0 :   u32 *result = va_arg (*args, u32 *);
     482           0 :   u8 *s = 0;
     483           0 :   u8 found = 0;
     484           0 :   for (int i = 0; i < punt_reason_last - 1; i++)
     485             :     {
     486           0 :       punt_reason_data_t *pd = vec_elt_at_index (punt_reason_data, 1 + i);
     487           0 :       vec_reset_length (s);
     488           0 :       s = format (0, "%v%c", pd->pd_name, 0);
     489           0 :       if (unformat (input, (const char *) s))
     490             :         {
     491           0 :           *result = pd->pd_reason;
     492           0 :           found = 1;
     493           0 :           break;
     494             :         }
     495             :     }
     496           0 :   vec_free (s);
     497           0 :   return found;
     498             : }
     499             : 
     500             : u8 *
     501           4 : format_punt_reg (u8 * s, va_list * args)
     502             : {
     503           4 :   u32 pri = va_arg (*args, u32);
     504             :   punt_reg_t *pr;
     505             : 
     506           4 :   pr = pool_elt_at_index (punt_reg_pool, pri);
     507             : 
     508           4 :   s = format (s, "%U -> %U",
     509           4 :               format_vlib_punt_reason, pr->pr_reason,
     510             :               format_vlib_node_name, vlib_get_main (), pr->pr_node_index);
     511             : 
     512           4 :   return (s);
     513             : }
     514             : 
     515             : u8 *
     516           7 : format_punt_reason_data (u8 * s, va_list * args)
     517             : {
     518           7 :   punt_reason_data_t *pd = va_arg (*args, punt_reason_data_t *);
     519             :   punt_client_t *pc;
     520             :   u32 *pci;
     521           7 :   if (pd->flags_format)
     522           6 :     s = format (s, "[%d] %v flags: %U from:[", pd->pd_reason, pd->pd_name,
     523             :                 pd->flags_format, pd->flags);
     524             :   else
     525           1 :     s = format (s, "[%d] %v from:[", pd->pd_reason, pd->pd_name);
     526          13 :   vec_foreach (pci, pd->pd_owners)
     527             :   {
     528           6 :     pc = pool_elt_at_index (punt_client_pool, *pci);
     529           6 :     s = format (s, "%v ", pc->pc_name);
     530             :   }
     531           7 :   s = format (s, "]");
     532             : 
     533           7 :   return (s);
     534             : }
     535             : 
     536             : u8 *
     537           3 : format_punt_client (u8 * s, va_list * args)
     538             : {
     539           3 :   u32 pci = va_arg (*args, u32);
     540           3 :   punt_format_flags_t flags = va_arg (*args, punt_format_flags_t);
     541             :   punt_client_t *pc;
     542             : 
     543           3 :   pc = pool_elt_at_index (punt_client_pool, pci);
     544             : 
     545           3 :   s = format (s, "%v", pc->pc_name);
     546             : 
     547           3 :   if (flags & PUNT_FORMAT_FLAG_DETAIL)
     548             :     {
     549             :       punt_reason_data_t *pd;
     550             :       u32 *pri;
     551             : 
     552           0 :       s = format (s, "\n registrations:");
     553           0 :       vec_foreach (pri, pc->pc_regs)
     554             :       {
     555           0 :         s = format (s, "\n  [%U]", format_punt_reg, *pri);
     556             :       }
     557             : 
     558           0 :       s = format (s, "\n reasons:");
     559             : 
     560           0 :       vec_foreach (pd, punt_reason_data)
     561             :       {
     562             :         u32 *tmp;
     563             : 
     564           0 :         vec_foreach (tmp, pd->pd_owners)
     565             :         {
     566           0 :           if (*tmp == pci)
     567           0 :             s = format (s, "\n  %U", format_punt_reason_data, pd);
     568             :         }
     569             :       }
     570             :     }
     571           3 :   return (s);
     572             : }
     573             : 
     574             : static clib_error_t *
     575           1 : punt_client_show (vlib_main_t * vm,
     576             :                   unformat_input_t * input, vlib_cli_command_t * cmd)
     577             : {
     578           1 :   u32 pci = ~0;
     579             : 
     580           1 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     581             :     {
     582           0 :       if (unformat (input, "%U", unformat_punt_client, &pci))
     583             :         ;
     584             :       else
     585           0 :         break;
     586             :     }
     587             : 
     588           1 :   if (~0 != pci)
     589             :     {
     590           0 :       vlib_cli_output (vm, "%U", format_punt_client, pci,
     591             :                        PUNT_FORMAT_FLAG_DETAIL);
     592             :     }
     593             :   else
     594             :     {
     595             :       u8 *name;
     596             : 
     597             :       /* *INDENT-OFF* */
     598          68 :       hash_foreach(name, pci, punt_client_db,
     599             :         ({
     600             :           vlib_cli_output (vm, "%U", format_punt_client, pci,
     601             :                            PUNT_FORMAT_FLAG_NONE);
     602             :         }));
     603             :       /* *INDENT-ON* */
     604             :     }
     605             : 
     606           1 :   return (NULL);
     607             : }
     608             : 
     609             : /* *INDENT-OFF* */
     610      285289 : VLIB_CLI_COMMAND (punt_client_show_command, static) =
     611             : {
     612             :   .path = "show punt client",
     613             :   .short_help = "show client[s] registered with the punt infra",
     614             :   .function = punt_client_show,
     615             : };
     616             : /* *INDENT-ON* */
     617             : 
     618             : static clib_error_t *
     619           1 : punt_reason_show (vlib_main_t * vm,
     620             :                   unformat_input_t * input, vlib_cli_command_t * cmd)
     621             : {
     622             :   const punt_reason_data_t *pd;
     623             : 
     624           8 :   vec_foreach (pd, punt_reason_data)
     625             :   {
     626           7 :     vlib_cli_output (vm, "%U", format_punt_reason_data, pd);
     627             :   }
     628             : 
     629           1 :   return (NULL);
     630             : }
     631             : 
     632             : /* *INDENT-OFF* */
     633      285289 : VLIB_CLI_COMMAND (punt_reason_show_command, static) =
     634             : {
     635             :   .path = "show punt reasons",
     636             :   .short_help = "show all punt reasons",
     637             :   .function = punt_reason_show,
     638             : };
     639             : /* *INDENT-ON* */
     640             : 
     641             : static clib_error_t *
     642           1 : punt_db_show (vlib_main_t * vm,
     643             :               unformat_input_t * input, vlib_cli_command_t * cmd)
     644             : {
     645             :   u32 pri, ii, jj;
     646             :   u64 key;
     647             : 
     648             :   /* *INDENT-OFF* */
     649          69 :   hash_foreach (key, pri, punt_reg_db,
     650             :     ({
     651             :       vlib_cli_output (vm, " %U", format_punt_reg, pri);
     652             :     }));
     653             :   /* *INDENT-ON* */
     654             : 
     655           1 :   vlib_cli_output (vm, "\nDerived data-plane data-base:");
     656           1 :   vlib_cli_output (vm,
     657             :                    "  (for each punt-reason the edge[s] from punt-dispatch)");
     658             : 
     659           8 :   vec_foreach_index (ii, punt_dp_db)
     660             :   {
     661           7 :     u8 *s = NULL;
     662           7 :     vlib_cli_output (vm, " %U", format_vlib_punt_reason, ii);
     663             : 
     664          11 :     vec_foreach_index (jj, punt_dp_db[ii])
     665             :     {
     666           4 :       s = format (s, "%d ", punt_dp_db[ii][jj]);
     667             :     }
     668           7 :     vlib_cli_output (vm, "   [%v]", s);
     669           7 :     vec_free (s);
     670             :   }
     671             : 
     672           1 :   return (NULL);
     673             : }
     674             : 
     675             : /* *INDENT-OFF* */
     676      285289 : VLIB_CLI_COMMAND (punt_db_show_command, static) =
     677             : {
     678             :   .path = "show punt db",
     679             :   .short_help = "show the punt DB",
     680             :   .function = punt_db_show,
     681             : };
     682             : /* *INDENT-ON* */
     683             : 
     684             : static clib_error_t *
     685           4 : punt_stats_show (vlib_main_t * vm,
     686             :                  unformat_input_t * input, vlib_cli_command_t * cmd)
     687             : {
     688           4 :   vlib_combined_counter_main_t *cm = &punt_counters;
     689             :   vlib_counter_t c;
     690             :   u32 ii;
     691             : 
     692          26 :   for (ii = 0; ii < vlib_combined_counter_n_counters (cm); ii++)
     693             :     {
     694          22 :       vlib_get_combined_counter (cm, ii, &c);
     695          22 :       vlib_cli_output (vm, "%U packets:%lld bytes:%lld",
     696             :                        format_vlib_punt_reason, ii, c.packets, c.bytes);
     697             :     }
     698             : 
     699           4 :   return (NULL);
     700             : }
     701             : 
     702             : /* *INDENT-OFF* */
     703      285289 : VLIB_CLI_COMMAND (punt_stats_show_command, static) =
     704             : {
     705             :   .path = "show punt stats",
     706             :   .short_help = "show the punt stats",
     707             :   .function = punt_stats_show,
     708             : };
     709             : /* *INDENT-ON* */
     710             : 
     711             : static clib_error_t *
     712         575 : punt_init (vlib_main_t * vm)
     713             : {
     714         575 :   punt_client_db = hash_create_vec (0, sizeof (u8), sizeof (u32));
     715             : 
     716         575 :   return (NULL);
     717             : }
     718             : 
     719        2879 : VLIB_INIT_FUNCTION (punt_init);
     720             : 
     721             : /*
     722             :  * fd.io coding-style-patch-verification: ON
     723             :  *
     724             :  * Local Variables:
     725             :  * eval: (c-set-style "gnu")
     726             :  * End:
     727             :  */

Generated by: LCOV version 1.14