FD.io VPP  v20.05-21-gb1500e9ff
Vector Packet Processing
dpo.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 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  * @brief
17  * A Data-Path Object is an object that represents actions that are
18  * applied to packets are they are switched through VPP.
19  *
20  * The DPO is a base class that is specialised by other objects to provide
21  * concrete actions
22  *
23  * The VLIB graph nodes are graph of types, the DPO graph is a graph of instances.
24  */
25 
26 #include <vnet/dpo/dpo.h>
27 #include <vnet/ip/lookup.h>
28 #include <vnet/ip/format.h>
29 #include <vnet/adj/adj.h>
30 
31 #include <vnet/dpo/load_balance.h>
33 #include <vnet/dpo/lookup_dpo.h>
34 #include <vnet/dpo/drop_dpo.h>
35 #include <vnet/dpo/receive_dpo.h>
36 #include <vnet/dpo/punt_dpo.h>
37 #include <vnet/dpo/classify_dpo.h>
38 #include <vnet/dpo/ip_null_dpo.h>
39 #include <vnet/dpo/replicate_dpo.h>
43 #include <vnet/dpo/dvr_dpo.h>
44 #include <vnet/dpo/l3_proxy_dpo.h>
45 #include <vnet/dpo/ip6_ll_dpo.h>
46 #include <vnet/dpo/pw_cw.h>
47 
48 /**
49  * Array of char* names for the DPO types and protos
50  */
51 static const char* dpo_type_names[] = DPO_TYPES;
52 static const char* dpo_proto_names[] = DPO_PROTOS;
53 
54 /**
55  * @brief Vector of virtual function tables for the DPO types
56  *
57  * This is a vector so we can dynamically register new DPO types in plugins.
58  */
60 
61 /**
62  * @brief vector of graph node names associated with each DPO type and protocol.
63  *
64  * dpo_nodes[child_type][child_proto][node_X] = node_name;
65  * i.e.
66  * dpo_node[DPO_LOAD_BALANCE][DPO_PROTO_IP4][0] = "ip4-lookup"
67  * dpo_node[DPO_LOAD_BALANCE][DPO_PROTO_IP4][1] = "ip4-load-balance"
68  *
69  * This is a vector so we can dynamically register new DPO types in plugins.
70  */
71 static const char* const * const ** dpo_nodes;
72 
73 /**
74  * @brief Vector of edge indicies from parent DPO nodes to child
75  *
76  * dpo_edges[child_type][child_proto][parent_type][parent_proto] = edge_index
77  *
78  * This array is derived at init time from the dpo_nodes above. Note that
79  * the third dimension in dpo_nodes is lost, hence, the edge index from each
80  * node MUST be the same.
81  * Including both the child and parent protocol is required to support the
82  * case where it changes as the graph is traversed, most notably when an
83  * MPLS label is popped.
84  *
85  * Note that this array is child type specific, not child instance specific.
86  */
87 static u32 ****dpo_edges;
88 
89 /**
90  * @brief The DPO type value that can be assigned to the next dynamic
91  * type registration.
92  */
94 
97 {
98  switch (linkt)
99  {
100  case VNET_LINK_IP6:
101  return (DPO_PROTO_IP6);
102  case VNET_LINK_IP4:
103  return (DPO_PROTO_IP4);
104  case VNET_LINK_MPLS:
105  return (DPO_PROTO_MPLS);
106  case VNET_LINK_ETHERNET:
107  return (DPO_PROTO_ETHERNET);
108  case VNET_LINK_NSH:
109  return (DPO_PROTO_NSH);
110  case VNET_LINK_ARP:
111  break;
112  }
113  ASSERT(0);
114  return (0);
115 }
116 
119 {
120  switch (dp)
121  {
122  case DPO_PROTO_IP6:
123  return (VNET_LINK_IP6);
124  case DPO_PROTO_IP4:
125  return (VNET_LINK_IP4);
126  case DPO_PROTO_MPLS:
127  case DPO_PROTO_BIER:
128  return (VNET_LINK_MPLS);
129  case DPO_PROTO_ETHERNET:
130  return (VNET_LINK_ETHERNET);
131  case DPO_PROTO_NSH:
132  return (VNET_LINK_NSH);
133  }
134  return (~0);
135 }
136 
137 u8 *
138 format_dpo_type (u8 * s, va_list * args)
139 {
140  dpo_type_t type = va_arg (*args, int);
141 
142  s = format(s, "%s", dpo_type_names[type]);
143 
144  return (s);
145 }
146 
147 u8 *
148 format_dpo_id (u8 * s, va_list * args)
149 {
150  dpo_id_t *dpo = va_arg (*args, dpo_id_t*);
151  u32 indent = va_arg (*args, u32);
152 
153  s = format(s, "[@%d]: ", dpo->dpoi_next_node);
154 
155  if (NULL != dpo_vfts[dpo->dpoi_type].dv_format)
156  {
157  s = format(s, "%U",
158  dpo_vfts[dpo->dpoi_type].dv_format,
159  dpo->dpoi_index,
160  indent);
161  }
162  else
163  {
164  switch (dpo->dpoi_type)
165  {
166  case DPO_FIRST:
167  s = format(s, "unset");
168  break;
169  default:
170  s = format(s, "unknown");
171  break;
172  }
173  }
174  return (s);
175 }
176 
177 u8 *
178 format_dpo_proto (u8 * s, va_list * args)
179 {
180  dpo_proto_t proto = va_arg (*args, int);
181 
182  return (format(s, "%s", dpo_proto_names[proto]));
183 }
184 
185 void
189  index_t index)
190 {
191  dpo_id_t tmp = *dpo;
192 
193  dpo->dpoi_type = type;
194  dpo->dpoi_proto = proto,
195  dpo->dpoi_index = index;
196 
197  if (DPO_ADJACENCY == type)
198  {
199  /*
200  * set the adj subtype
201  */
202  ip_adjacency_t *adj;
203 
204  adj = adj_get(index);
205 
206  switch (adj->lookup_next_index)
207  {
208  case IP_LOOKUP_NEXT_ARP:
210  break;
213  break;
216  break;
219  break;
222  break;
223  default:
224  break;
225  }
226  }
227  dpo_lock(dpo);
228  dpo_unlock(&tmp);
229 }
230 
231 void
233 {
234  dpo_id_t tmp = DPO_INVALID;
235 
236  /*
237  * use the atomic copy operation.
238  */
239  dpo_copy(dpo, &tmp);
240 }
241 
242 /**
243  * \brief
244  * Compare two Data-path objects
245  *
246  * like memcmp, return 0 is matching, !0 otherwise.
247  */
248 int
249 dpo_cmp (const dpo_id_t *dpo1,
250  const dpo_id_t *dpo2)
251 {
252  int res;
253 
254  res = dpo1->dpoi_type - dpo2->dpoi_type;
255 
256  if (0 != res) return (res);
257 
258  return (dpo1->dpoi_index - dpo2->dpoi_index);
259 }
260 
261 void
263  const dpo_id_t *src)
264 {
265  dpo_id_t tmp = *dst;
266 
267  /*
268  * the destination is written in a single u64 write - hence atomically w.r.t
269  * any packets inflight.
270  */
271  *((u64*)dst) = *(u64*)src;
272 
273  dpo_lock(dst);
274  dpo_unlock(&tmp);
275 }
276 
277 int
278 dpo_is_adj (const dpo_id_t *dpo)
279 {
280  return ((dpo->dpoi_type == DPO_ADJACENCY) ||
282  (dpo->dpoi_type == DPO_ADJACENCY_MIDCHAIN) ||
283  (dpo->dpoi_type == DPO_ADJACENCY_GLEAN));
284 }
285 
286 static u32 *
288 {
289  u32 *node_indices = NULL;
290  const char *node_name;
291  u32 ii = 0;
292 
293  node_name = dpo_nodes[dpo->dpoi_type][dpo->dpoi_proto][ii];
294  while (NULL != node_name)
295  {
296  vlib_node_t *node;
297 
298  node = vlib_get_node_by_name(vlib_get_main(), (u8*) node_name);
299  ASSERT(NULL != node);
300  vec_add1(node_indices, node->index);
301 
302  ++ii;
303  node_name = dpo_nodes[dpo->dpoi_type][dpo->dpoi_proto][ii];
304  }
305 
306  return (node_indices);
307 }
308 
309 /**
310  * A default variant of the make interpose function that just returns
311  * the original
312  */
313 static void
315  const dpo_id_t *parent,
316  dpo_id_t *clone)
317 {
318  dpo_copy(clone, original);
319 }
320 
321 void
323  const dpo_vft_t *vft,
324  const char * const * const * nodes)
325 {
326  vec_validate(dpo_vfts, type);
327  dpo_vfts[type] = *vft;
328  if (NULL == dpo_vfts[type].dv_get_next_node)
329  {
331  }
332  if (NULL == dpo_vfts[type].dv_mk_interpose)
333  {
335  }
336 
337  vec_validate(dpo_nodes, type);
338  dpo_nodes[type] = nodes;
339 }
340 
343  const char * const * const * nodes)
344 {
346 
347  dpo_register(type, vft, nodes);
348 
349  return (type);
350 }
351 
352 void
353 dpo_mk_interpose (const dpo_id_t *original,
354  const dpo_id_t *parent,
355  dpo_id_t *clone)
356 {
357  if (!dpo_id_is_valid(original))
358  return;
359 
360  dpo_vfts[original->dpoi_type].dv_mk_interpose(original, parent, clone);
361 }
362 
363 void
365 {
366  if (!dpo_id_is_valid(dpo))
367  return;
368 
369  dpo_vfts[dpo->dpoi_type].dv_lock(dpo);
370 }
371 
372 void
374 {
375  if (!dpo_id_is_valid(dpo))
376  return;
377 
378  dpo_vfts[dpo->dpoi_type].dv_unlock(dpo);
379 }
380 
381 u32
383 {
384  if (dpo_id_is_valid(dpo) &&
385  (NULL != dpo_vfts[dpo->dpoi_type].dv_get_urpf))
386  {
387  return (dpo_vfts[dpo->dpoi_type].dv_get_urpf(dpo));
388  }
389 
390  return (~0);
391 }
392 
393 static u32
395  dpo_proto_t child_proto,
396  const dpo_id_t *parent_dpo)
397 {
398  dpo_proto_t parent_proto;
399  dpo_type_t parent_type;
400 
401  parent_type = parent_dpo->dpoi_type;
402  parent_proto = parent_dpo->dpoi_proto;
403 
404  vec_validate(dpo_edges, child_type);
405  vec_validate(dpo_edges[child_type], child_proto);
406  vec_validate(dpo_edges[child_type][child_proto], parent_type);
408  dpo_edges[child_type][child_proto][parent_type],
409  parent_proto, ~0);
410 
411  /*
412  * if the edge index has not yet been created for this node to node transition
413  */
414  if (~0 == dpo_edges[child_type][child_proto][parent_type][parent_proto])
415  {
416  vlib_node_t *child_node;
417  u32 *parent_indices;
418  vlib_main_t *vm;
419  u32 edge, *pi, cc;
420 
421  vm = vlib_get_main();
422 
423  ASSERT(NULL != dpo_vfts[parent_type].dv_get_next_node);
424  ASSERT(NULL != dpo_nodes[child_type]);
425  ASSERT(NULL != dpo_nodes[child_type][child_proto]);
426 
427  cc = 0;
428  parent_indices = dpo_vfts[parent_type].dv_get_next_node(parent_dpo);
429 
431 
432  /*
433  * create a graph arc from each of the child's registered node types,
434  * to each of the parent's.
435  */
436  while (NULL != dpo_nodes[child_type][child_proto][cc])
437  {
438  child_node =
440  (u8*) dpo_nodes[child_type][child_proto][cc]);
441 
442  vec_foreach(pi, parent_indices)
443  {
444  edge = vlib_node_add_next(vm, child_node->index, *pi);
445 
446  if (~0 == dpo_edges[child_type][child_proto][parent_type][parent_proto])
447  {
448  dpo_edges[child_type][child_proto][parent_type][parent_proto] = edge;
449  }
450  else
451  {
452  ASSERT(dpo_edges[child_type][child_proto][parent_type][parent_proto] == edge);
453  }
454  }
455  cc++;
456  }
457 
459  vec_free(parent_indices);
460  }
461 
462  return (dpo_edges[child_type][child_proto][parent_type][parent_proto]);
463 }
464 
465 /**
466  * @brief return already stacked up next node index for a given
467  * child_type/child_proto and parent_type/patent_proto.
468  * The VLIB graph arc used is taken from the parent and child types
469  * passed.
470  */
471 u32
473  dpo_proto_t child_proto,
474  dpo_type_t parent_type,
475  dpo_proto_t parent_proto)
476 {
477  return (dpo_edges[child_type][child_proto][parent_type][parent_proto]);
478 }
479 
480 /**
481  * @brief Stack one DPO object on another, and thus establish a child parent
482  * relationship. The VLIB graph arc used is taken from the parent and child types
483  * passed.
484  */
485 static void
487  dpo_id_t *dpo,
488  const dpo_id_t *parent)
489 {
490  /*
491  * in order to get an atomic update of the parent we create a temporary,
492  * from a copy of the child, and add the next_node. then we copy to the parent
493  */
494  dpo_id_t tmp = DPO_INVALID;
495  dpo_copy(&tmp, parent);
496 
497  /*
498  * get the edge index for the parent to child VLIB graph transition
499  */
500  tmp.dpoi_next_node = edge;
501 
502  /*
503  * this update is atomic.
504  */
505  dpo_copy(dpo, &tmp);
506 
507  dpo_reset(&tmp);
508 }
509 
510 /**
511  * @brief Stack one DPO object on another, and thus establish a child-parent
512  * relationship. The VLIB graph arc used is taken from the parent and child types
513  * passed.
514  */
515 void
516 dpo_stack (dpo_type_t child_type,
517  dpo_proto_t child_proto,
518  dpo_id_t *dpo,
519  const dpo_id_t *parent)
520 {
521  dpo_stack_i(dpo_get_next_node(child_type, child_proto, parent), dpo, parent);
522 }
523 
524 /**
525  * @brief Stack one DPO object on another, and thus establish a child parent
526  * relationship. A new VLIB graph arc is created from the child node passed
527  * to the nodes registered by the parent. The VLIB infra will ensure this arc
528  * is added only once.
529  */
530 void
531 dpo_stack_from_node (u32 child_node_index,
532  dpo_id_t *dpo,
533  const dpo_id_t *parent)
534 {
535  dpo_type_t parent_type;
536  u32 *parent_indices;
537  vlib_main_t *vm;
538  u32 edge, *pi;
539 
540  edge = 0;
541  parent_type = parent->dpoi_type;
542  vm = vlib_get_main();
543 
544  ASSERT(NULL != dpo_vfts[parent_type].dv_get_next_node);
545  parent_indices = dpo_vfts[parent_type].dv_get_next_node(parent);
546  ASSERT(parent_indices);
547 
548  /*
549  * This loop is purposefully written with the worker thread lock in the
550  * inner loop because;
551  * 1) the likelihood that the edge does not exist is smaller
552  * 2) the likelihood there is more than one node is even smaller
553  * so we are optimising for not need to take the lock
554  */
555  vec_foreach(pi, parent_indices)
556  {
557  edge = vlib_node_get_next(vm, child_node_index, *pi);
558 
559  if (~0 == edge)
560  {
562 
563  edge = vlib_node_add_next(vm, child_node_index, *pi);
564 
566  }
567  }
568  dpo_stack_i(edge, dpo, parent);
569 
570  /* should free this local vector to avoid memory leak */
571  vec_free(parent_indices);
572 }
573 
574 static clib_error_t *
576 {
593 
594  return (NULL);
595 }
596 
597 /* *INDENT-OFF* */
599 {
600  .runs_before = VLIB_INITS ("ip_main_init"),
601 };
602 /* *INDENT-ON* */
603 
604 static clib_error_t *
606  unformat_input_t * input,
607  vlib_cli_command_t * cmd)
608 {
609  dpo_vft_t *vft;
610 
611  vlib_cli_output (vm, "DPO memory");
612  vlib_cli_output (vm, "%=30s %=5s %=8s/%=9s totals",
613  "Name","Size", "in-use", "allocated");
614 
615  vec_foreach(vft, dpo_vfts)
616  {
617  if (NULL != vft->dv_mem_show)
618  vft->dv_mem_show();
619  }
620 
621  return (NULL);
622 }
623 
624 /* *INDENT-OFF* */
625 /*?
626  * The '<em>sh dpo memory </em>' command displays the memory usage for each
627  * data-plane object type.
628  *
629  * @cliexpar
630  * @cliexstart{show dpo memory}
631  * DPO memory
632  * Name Size in-use /allocated totals
633  * load-balance 64 12 / 12 768/768
634  * Adjacency 256 1 / 1 256/256
635  * Receive 24 5 / 5 120/120
636  * Lookup 12 0 / 0 0/0
637  * Classify 12 0 / 0 0/0
638  * MPLS label 24 0 / 0 0/0
639  * @cliexend
640 ?*/
641 VLIB_CLI_COMMAND (show_fib_memory, static) = {
642  .path = "show dpo memory",
643  .function = dpo_memory_show,
644  .short_help = "show dpo memory",
645 };
646 /* *INDENT-ON* */
void dpo_unlock(dpo_id_t *dpo)
Release a reference counting lock on the DPO.
Definition: dpo.c:373
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:507
void dpo_stack_from_node(u32 child_node_index, dpo_id_t *dpo, const dpo_id_t *parent)
Stack one DPO object on another, and thus establish a child parent relationship.
Definition: dpo.c:531
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:406
static const char * dpo_type_names[]
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.c:51
A virtual function table regisitered for a DPO type.
Definition: dpo.h:401
u8 * format_dpo_type(u8 *s, va_list *args)
format a DPO type
Definition: dpo.c:138
int dpo_is_adj(const dpo_id_t *dpo)
Return TRUE is the DPO is any type of adjacency.
Definition: dpo.c:278
static dpo_type_t dpo_dynamic
The DPO type value that can be assigned to the next dynamic type registration.
Definition: dpo.c:93
static int dpo_id_is_valid(const dpo_id_t *dpoi)
Return true if the DPO object is valid, i.e.
Definition: dpo.h:209
unsigned long u64
Definition: types.h:89
dpo_get_urpf_t dv_get_urpf
Get uRPF interface.
Definition: dpo.h:429
void l3_proxy_dpo_module_init(void)
Definition: l3_proxy_dpo.c:172
Multicast Adjacency.
Definition: adj.h:82
Definitions for all things IP (v4|v6) unicast and multicast lookup related.
dpo_proto_t dpoi_proto
the data-path protocol of the type.
Definition: dpo.h:178
u32 index
Definition: node.h:282
IP unicast adjacency.
Definition: adj.h:227
void dpo_copy(dpo_id_t *dst, const dpo_id_t *src)
atomic copy a data-plane object.
Definition: dpo.c:262
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:41
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:590
vl_api_address_t src
Definition: gre.api:54
#define DPO_PROTOS
Definition: dpo.h:73
u32 dpo_get_urpf(const dpo_id_t *dpo)
Get a uRPF interface for the DPO.
Definition: dpo.c:382
static const char * dpo_proto_names[]
Definition: dpo.c:52
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
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
#define vlib_worker_thread_barrier_sync(X)
Definition: threads.h:204
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:459
void dpo_register(dpo_type_t type, const dpo_vft_t *vft, const char *const *const *nodes)
For a given DPO type Register:
Definition: dpo.c:322
enum dpo_type_t_ dpo_type_t
Common types of data-path objects New types can be dynamically added using dpo_register_new_type() ...
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
dpo_proto_t vnet_link_to_dpo_proto(vnet_link_t linkt)
Definition: dpo.c:96
static u32 dpo_get_next_node(dpo_type_t child_type, dpo_proto_t child_proto, const dpo_id_t *parent_dpo)
Definition: dpo.c:394
void load_balance_module_init(void)
Definition: load_balance.c:955
#define DPO_TYPES
Definition: dpo.h:133
void receive_dpo_module_init(void)
Definition: receive_dpo.c:173
void dpo_mk_interpose(const dpo_id_t *original, const dpo_id_t *parent, dpo_id_t *clone)
Make an interpose DPO from an original.
Definition: dpo.c:353
unsigned int u32
Definition: types.h:88
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
dpo_type_t dpo_register_new_type(const dpo_vft_t *vft, const char *const *const *nodes)
Create and register a new DPO type.
Definition: dpo.c:342
static u32 * dpo_default_get_next_node(const dpo_id_t *dpo)
Definition: dpo.c:287
static u32 **** dpo_edges
Vector of edge indicies from parent DPO nodes to child.
Definition: dpo.c:87
dpo_get_next_node_t dv_get_next_node
A function to get the next VLIB node given an instance of the DPO.
Definition: dpo.h:425
vl_api_fib_path_type_t type
Definition: fib_types.api:123
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:170
void ip_null_dpo_module_init(void)
Definition: ip_null_dpo.c:411
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
void interface_rx_dpo_module_init(void)
Definition: dpo.h:128
vl_api_ip_proto_t proto
Definition: acl_types.api:50
dpo_type_t dpoi_type
the type
Definition: dpo.h:174
static const char *const *const ** dpo_nodes
vector of graph node names associated with each DPO type and protocol.
Definition: dpo.c:71
struct _unformat_input_t unformat_input_t
void classify_dpo_module_init(void)
Definition: classify_dpo.c:128
static void dpo_default_mk_interpose(const dpo_id_t *original, const dpo_id_t *parent, dpo_id_t *clone)
A default variant of the make interpose function that just returns the original.
Definition: dpo.c:314
This packet matches an "interface route" and packets need to be passed to ARP to find rewrite string ...
Definition: adj.h:68
void dvr_dpo_module_init(void)
Definition: dvr_dpo.c:258
void dpo_lock(dpo_id_t *dpo)
Take a reference counting lock on the DPO.
Definition: dpo.c:364
void lookup_dpo_module_init(void)
Definition: lookup_dpo.c:1498
vl_api_address_t dst
Definition: gre.api:55
vlib_main_t * vm
Definition: in2out_ed.c:1599
This packet matches an "incomplete adjacency" and packets need to be passed to ARP to find rewrite st...
Definition: adj.h:63
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
Multicast Midchain Adjacency.
Definition: adj.h:89
void dpo_set(dpo_id_t *dpo, dpo_type_t type, dpo_proto_t proto, index_t index)
Set/create a DPO ID The DPO will be locked.
Definition: dpo.c:186
void mpls_disp_dpo_module_init(void)
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1599
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:152
This packets follow a mid-chain adjacency.
Definition: adj.h:76
void mpls_label_dpo_module_init(void)
static clib_error_t * dpo_module_init(vlib_main_t *vm)
Definition: dpo.c:575
#define ASSERT(truth)
static dpo_vft_t * dpo_vfts
Vector of virtual function tables for the DPO types.
Definition: dpo.c:59
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:689
vnet_link_t dpo_proto_to_link(dpo_proto_t dp)
format a DPO protocol
Definition: dpo.c:118
void interface_tx_dpo_module_init(void)
void punt_dpo_module_init(void)
Definition: punt_dpo.c:97
enum vnet_link_t_ vnet_link_t
Link Type: A description of the protocol of packets on the link.
A non-zero value first so we can spot unitialisation errors.
Definition: dpo.h:95
uword vlib_node_get_next(vlib_main_t *vm, uword node_index, uword next_node_index)
Definition: node.c:178
int dpo_cmp(const dpo_id_t *dpo1, const dpo_id_t *dpo2)
Compare two Data-path objects.
Definition: dpo.c:249
void ip6_ll_dpo_module_init(void)
Definition: ip6_ll_dpo.c:192
u8 * format_dpo_id(u8 *s, va_list *args)
Format a DPO_id_t oject.
Definition: dpo.c:148
dpo_mem_show_t dv_mem_show
A show memory usage function.
Definition: dpo.h:418
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
static clib_error_t * dpo_memory_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: dpo.c:605
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:186
format_function_t * dv_format
A format function.
Definition: dpo.h:414
ip_lookup_next_t lookup_next_index
Next hop after ip4-lookup.
Definition: adj.h:329
dpo_lock_fn_t dv_unlock
A reference counting unlock function.
Definition: dpo.h:410
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:197
u8 * format_dpo_proto(u8 *s, va_list *args)
format a DPO protocol
Definition: dpo.c:178
void pw_cw_dpo_module_init(void)
Definition: pw_cw.c:310
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1540
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:232
#define vec_foreach(var, vec)
Vector iterator.
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:182
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:554
void drop_dpo_module_init(void)
Definition: drop_dpo.c:115
static void dpo_stack_i(u32 edge, dpo_id_t *dpo, const dpo_id_t *parent)
Stack one DPO object on another, and thus establish a child parent relationship.
Definition: dpo.c:486
void replicate_module_init(void)
#define VLIB_INITS(...)
Definition: init.h:344
u32 dpo_get_next_node_by_type_and_proto(dpo_type_t child_type, dpo_proto_t child_proto, dpo_type_t parent_type, dpo_proto_t parent_proto)
return already stacked up next node index for a given child_type/child_proto and parent_type/patent_p...
Definition: dpo.c:472
dpo_mk_interpose_t dv_mk_interpose
Signal on an interposed child that the parent has changed.
Definition: dpo.h:433
void dpo_stack(dpo_type_t child_type, dpo_proto_t child_proto, dpo_id_t *dpo, const dpo_id_t *parent)
Stack one DPO object on another, and thus establish a child-parent relationship.
Definition: dpo.c:516