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