FD.io VPP  v21.01.1
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 = {
266  .as_u64 = dst->as_u64
267  };
268 
269  /*
270  * the destination is written in a single u64 write - hence atomically w.r.t
271  * any packets inflight.
272  */
273  dst->as_u64 = src->as_u64;
274 
275  dpo_lock(dst);
276  dpo_unlock(&tmp);
277 }
278 
279 int
280 dpo_is_adj (const dpo_id_t *dpo)
281 {
282  return ((dpo->dpoi_type == DPO_ADJACENCY) ||
284  (dpo->dpoi_type == DPO_ADJACENCY_GLEAN) ||
285  (dpo->dpoi_type == DPO_ADJACENCY_MCAST) ||
287  (dpo->dpoi_type == DPO_ADJACENCY_MIDCHAIN) ||
288  (dpo->dpoi_type == DPO_ADJACENCY_GLEAN));
289 }
290 
291 static u32 *
293 {
294  u32 *node_indices = NULL;
295  const char *node_name;
296  u32 ii = 0;
297 
298  node_name = dpo_nodes[dpo->dpoi_type][dpo->dpoi_proto][ii];
299  while (NULL != node_name)
300  {
301  vlib_node_t *node;
302 
303  node = vlib_get_node_by_name(vlib_get_main(), (u8*) node_name);
304  ASSERT(NULL != node);
305  vec_add1(node_indices, node->index);
306 
307  ++ii;
308  node_name = dpo_nodes[dpo->dpoi_type][dpo->dpoi_proto][ii];
309  }
310 
311  return (node_indices);
312 }
313 
314 /**
315  * A default variant of the make interpose function that just returns
316  * the original
317  */
318 static void
320  const dpo_id_t *parent,
321  dpo_id_t *clone)
322 {
323  dpo_copy(clone, original);
324 }
325 
326 void
328  const dpo_vft_t *vft,
329  const char * const * const * nodes)
330 {
331  vec_validate(dpo_vfts, type);
332  dpo_vfts[type] = *vft;
333  if (NULL == dpo_vfts[type].dv_get_next_node)
334  {
336  }
337  if (NULL == dpo_vfts[type].dv_mk_interpose)
338  {
340  }
341 
342  vec_validate(dpo_nodes, type);
343  dpo_nodes[type] = nodes;
344 }
345 
348  const char * const * const * nodes)
349 {
351 
352  dpo_register(type, vft, nodes);
353 
354  return (type);
355 }
356 
357 void
358 dpo_mk_interpose (const dpo_id_t *original,
359  const dpo_id_t *parent,
360  dpo_id_t *clone)
361 {
362  if (!dpo_id_is_valid(original))
363  return;
364 
365  dpo_vfts[original->dpoi_type].dv_mk_interpose(original, parent, clone);
366 }
367 
368 void
370 {
371  if (!dpo_id_is_valid(dpo))
372  return;
373 
374  dpo_vfts[dpo->dpoi_type].dv_lock(dpo);
375 }
376 
377 void
379 {
380  if (!dpo_id_is_valid(dpo))
381  return;
382 
383  dpo_vfts[dpo->dpoi_type].dv_unlock(dpo);
384 }
385 
386 u32
388 {
389  if (dpo_id_is_valid(dpo) &&
390  (NULL != dpo_vfts[dpo->dpoi_type].dv_get_urpf))
391  {
392  return (dpo_vfts[dpo->dpoi_type].dv_get_urpf(dpo));
393  }
394 
395  return (~0);
396 }
397 
398 static u32
400  dpo_proto_t child_proto,
401  const dpo_id_t *parent_dpo)
402 {
403  dpo_proto_t parent_proto;
404  dpo_type_t parent_type;
405 
406  parent_type = parent_dpo->dpoi_type;
407  parent_proto = parent_dpo->dpoi_proto;
408 
409  vec_validate(dpo_edges, child_type);
410  vec_validate(dpo_edges[child_type], child_proto);
411  vec_validate(dpo_edges[child_type][child_proto], parent_type);
413  dpo_edges[child_type][child_proto][parent_type],
414  parent_proto, ~0);
415 
416  /*
417  * if the edge index has not yet been created for this node to node transition
418  */
419  if (~0 == dpo_edges[child_type][child_proto][parent_type][parent_proto])
420  {
421  vlib_node_t *child_node;
422  u32 *parent_indices;
423  vlib_main_t *vm;
424  u32 edge, *pi, cc;
425 
426  vm = vlib_get_main();
427 
428  ASSERT(NULL != dpo_vfts[parent_type].dv_get_next_node);
429  ASSERT(NULL != dpo_nodes[child_type]);
430  ASSERT(NULL != dpo_nodes[child_type][child_proto]);
431 
432  cc = 0;
433  parent_indices = dpo_vfts[parent_type].dv_get_next_node(parent_dpo);
434 
436 
437  /*
438  * create a graph arc from each of the child's registered node types,
439  * to each of the parent's.
440  */
441  while (NULL != dpo_nodes[child_type][child_proto][cc])
442  {
443  child_node =
445  (u8*) dpo_nodes[child_type][child_proto][cc]);
446 
447  vec_foreach(pi, parent_indices)
448  {
449  edge = vlib_node_add_next(vm, child_node->index, *pi);
450 
451  if (~0 == dpo_edges[child_type][child_proto][parent_type][parent_proto])
452  {
453  dpo_edges[child_type][child_proto][parent_type][parent_proto] = edge;
454  }
455  else
456  {
457  ASSERT(dpo_edges[child_type][child_proto][parent_type][parent_proto] == edge);
458  }
459  }
460  cc++;
461  }
462 
464  vec_free(parent_indices);
465  }
466 
467  return (dpo_edges[child_type][child_proto][parent_type][parent_proto]);
468 }
469 
470 /**
471  * @brief return already stacked up next node index for a given
472  * child_type/child_proto and parent_type/patent_proto.
473  * The VLIB graph arc used is taken from the parent and child types
474  * passed.
475  */
476 u32
478  dpo_proto_t child_proto,
479  dpo_type_t parent_type,
480  dpo_proto_t parent_proto)
481 {
482  return (dpo_edges[child_type][child_proto][parent_type][parent_proto]);
483 }
484 
485 /**
486  * @brief Stack one DPO object on another, and thus establish a child parent
487  * relationship. The VLIB graph arc used is taken from the parent and child types
488  * passed.
489  */
490 static void
492  dpo_id_t *dpo,
493  const dpo_id_t *parent)
494 {
495  /*
496  * in order to get an atomic update of the parent we create a temporary,
497  * from a copy of the child, and add the next_node. then we copy to the parent
498  */
499  dpo_id_t tmp = DPO_INVALID;
500  dpo_copy(&tmp, parent);
501 
502  /*
503  * get the edge index for the parent to child VLIB graph transition
504  */
505  tmp.dpoi_next_node = edge;
506 
507  /*
508  * this update is atomic.
509  */
510  dpo_copy(dpo, &tmp);
511 
512  dpo_reset(&tmp);
513 }
514 
515 /**
516  * @brief Stack one DPO object on another, and thus establish a child-parent
517  * relationship. The VLIB graph arc used is taken from the parent and child types
518  * passed.
519  */
520 void
521 dpo_stack (dpo_type_t child_type,
522  dpo_proto_t child_proto,
523  dpo_id_t *dpo,
524  const dpo_id_t *parent)
525 {
526  dpo_stack_i(dpo_get_next_node(child_type, child_proto, parent), dpo, parent);
527 }
528 
529 /**
530  * @brief Stack one DPO object on another, and thus establish a child parent
531  * relationship. A new VLIB graph arc is created from the child node passed
532  * to the nodes registered by the parent. The VLIB infra will ensure this arc
533  * is added only once.
534  */
535 void
536 dpo_stack_from_node (u32 child_node_index,
537  dpo_id_t *dpo,
538  const dpo_id_t *parent)
539 {
540  dpo_type_t parent_type;
541  u32 *parent_indices;
542  vlib_main_t *vm;
543  u32 edge, *pi;
544 
545  edge = 0;
546  parent_type = parent->dpoi_type;
547  vm = vlib_get_main();
548 
549  ASSERT(NULL != dpo_vfts[parent_type].dv_get_next_node);
550  parent_indices = dpo_vfts[parent_type].dv_get_next_node(parent);
551  ASSERT(parent_indices);
552 
553  /*
554  * This loop is purposefully written with the worker thread lock in the
555  * inner loop because;
556  * 1) the likelihood that the edge does not exist is smaller
557  * 2) the likelihood there is more than one node is even smaller
558  * so we are optimising for not need to take the lock
559  */
560  vec_foreach(pi, parent_indices)
561  {
562  edge = vlib_node_get_next(vm, child_node_index, *pi);
563 
564  if (~0 == edge)
565  {
567 
568  edge = vlib_node_add_next(vm, child_node_index, *pi);
569 
571  }
572  }
573  dpo_stack_i(edge, dpo, parent);
574 
575  /* should free this local vector to avoid memory leak */
576  vec_free(parent_indices);
577 }
578 
579 static clib_error_t *
581 {
598 
599  return (NULL);
600 }
601 
602 /* *INDENT-OFF* */
604 {
605  .runs_before = VLIB_INITS ("ip_main_init"),
606 };
607 /* *INDENT-ON* */
608 
609 static clib_error_t *
611  unformat_input_t * input,
612  vlib_cli_command_t * cmd)
613 {
614  dpo_vft_t *vft;
615 
616  vlib_cli_output (vm, "DPO memory");
617  vlib_cli_output (vm, "%=30s %=5s %=8s/%=9s totals",
618  "Name","Size", "in-use", "allocated");
619 
620  vec_foreach(vft, dpo_vfts)
621  {
622  if (NULL != vft->dv_mem_show)
623  vft->dv_mem_show();
624  }
625 
626  return (NULL);
627 }
628 
629 /* *INDENT-OFF* */
630 /*?
631  * The '<em>sh dpo memory </em>' command displays the memory usage for each
632  * data-plane object type.
633  *
634  * @cliexpar
635  * @cliexstart{show dpo memory}
636  * DPO memory
637  * Name Size in-use /allocated totals
638  * load-balance 64 12 / 12 768/768
639  * Adjacency 256 1 / 1 256/256
640  * Receive 24 5 / 5 120/120
641  * Lookup 12 0 / 0 0/0
642  * Classify 12 0 / 0 0/0
643  * MPLS label 24 0 / 0 0/0
644  * @cliexend
645 ?*/
646 VLIB_CLI_COMMAND (show_fib_memory, static) = {
647  .path = "show dpo memory",
648  .function = dpo_memory_show,
649  .short_help = "show dpo memory",
650 };
651 /* *INDENT-ON* */
void dpo_unlock(dpo_id_t *dpo)
Release a reference counting lock on the DPO.
Definition: dpo.c:378
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
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:536
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:411
u64 as_u64
Definition: dpo.h:190
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:406
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:280
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:214
dpo_get_urpf_t dv_get_urpf
Get uRPF interface.
Definition: dpo.h:434
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:180
u32 index
Definition: node.h:280
IP unicast adjacency.
Definition: adj.h:235
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:592
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:387
static const char * dpo_proto_names[]
Definition: dpo.c:52
vlib_main_t * vm
Definition: in2out_ed.c:1580
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1173
unsigned char u8
Definition: types.h:56
#define vlib_worker_thread_barrier_sync(X)
Definition: threads.h:205
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:467
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:327
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:399
void load_balance_module_init(void)
Definition: load_balance.c:980
description fragment has unexpected format
Definition: map.api:433
#define DPO_TYPES
Definition: dpo.h:133
void receive_dpo_module_init(void)
Definition: receive_dpo.c:178
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:358
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:347
static u32 * dpo_default_get_next_node(const dpo_id_t *dpo)
Definition: dpo.c:292
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:430
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:51
dpo_type_t dpoi_type
the type
Definition: dpo.h:176
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:133
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:319
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:259
void dpo_lock(dpo_id_t *dpo)
Take a reference counting lock on the DPO.
Definition: dpo.c:369
void lookup_dpo_module_init(void)
Definition: lookup_dpo.c:1502
vl_api_address_t dst
Definition: gre.api:55
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:1580
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
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:580
#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:696
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:151
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:423
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:610
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:188
format_function_t * dv_format
A format function.
Definition: dpo.h:419
ip_lookup_next_t lookup_next_index
Next hop after ip4-lookup.
Definition: adj.h:337
dpo_lock_fn_t dv_unlock
A reference counting unlock function.
Definition: dpo.h:415
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:202
u32 index
Definition: flow_types.api:221
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:1561
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:184
#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:556
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:491
void replicate_module_init(void)
#define VLIB_INITS(...)
Definition: init.h:357
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:477
dpo_mk_interpose_t dv_mk_interpose
Signal on an interposed child that the parent has changed.
Definition: dpo.h:438
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:521