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