FD.io VPP  v21.01.1
Vector Packet Processing
dvr_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 #include <vnet/dpo/dvr_dpo.h>
17 #include <vnet/fib/fib_node.h>
18 #include <vnet/ip/ip.h>
19 #include <vnet/ethernet/ethernet.h>
20 #include <vnet/l2/l2_input.h>
21 
22 #ifndef CLIB_MARCH_VARIANT
24 
25 /**
26  * The 'DB' of DVR DPOs.
27  * There is one per-interface per-L3 proto, so this is a per-interface vector
28  */
30 
31 static dvr_dpo_t *
33 {
34  dvr_dpo_t *dd;
35 
36  pool_get(dvr_dpo_pool, dd);
37 
38  return (dd);
39 }
40 
41 static inline dvr_dpo_t *
43 {
44  ASSERT(DPO_DVR == dpo->dpoi_type);
45 
46  return (dvr_dpo_get(dpo->dpoi_index));
47 }
48 
49 static inline index_t
51 {
52  return (dd - dvr_dpo_pool);
53 }
54 
55 static void
57 {
58  dvr_dpo_t *dd;
59 
60  dd = dvr_dpo_get_from_dpo(dpo);
61  dd->dd_locks++;
62 }
63 
64 static void
66 {
67  dvr_dpo_t *dd;
68 
69  dd = dvr_dpo_get_from_dpo(dpo);
70  dd->dd_locks--;
71 
72  if (0 == dd->dd_locks)
73  {
74  if (DPO_PROTO_IP4 == dd->dd_proto)
75  {
76  vnet_feature_enable_disable ("ip4-output", "ip4-dvr-reinject",
77  dd->dd_sw_if_index, 0, 0, 0);
78  }
79  else
80  {
81  vnet_feature_enable_disable ("ip6-output", "ip6-dvr-reinject",
82  dd->dd_sw_if_index, 0, 0, 0);
83  }
84 
86  pool_put(dvr_dpo_pool, dd);
87  }
88 }
89 
90 void
92  dpo_proto_t dproto,
93  dpo_id_t *dpo)
94 {
95  l2_input_config_t *config;
96  dvr_dpo_t *dd;
97 
99  sw_if_index,
100  INDEX_INVALID);
101 
102  if (INDEX_INVALID == dvr_dpo_db[dproto][sw_if_index])
103  {
104  dd = dvr_dpo_alloc();
105 
107  dd->dd_proto = dproto;
108 
110 
111  config = l2input_intf_config (sw_if_index);
112 
113  if (l2_input_is_bridge(config) ||
114  l2_input_is_xconnect(config))
115  {
117  }
118  else
119  {
121  }
122 
123  /*
124  * enable the reinject into L2 path feature on the interface
125  */
126  if (DPO_PROTO_IP4 == dproto)
127  vnet_feature_enable_disable ("ip4-output", "ip4-dvr-reinject",
128  dd->dd_sw_if_index, 1, 0, 0);
129  else if (DPO_PROTO_IP6 == dproto)
130  vnet_feature_enable_disable ("ip6-output", "ip6-dvr-reinject",
131  dd->dd_sw_if_index, 1, 0, 0);
132  else
133  ASSERT(0);
134  }
135  else
136  {
137  dd = dvr_dpo_get(dvr_dpo_db[dproto][sw_if_index]);
138  }
139 
140  dpo_set(dpo, DPO_DVR, dproto, dvr_dpo_get_index(dd));
141 }
142 #endif /* CLIB_MARCH_VARIANT */
143 
144 
145 static clib_error_t *
148  u32 flags)
149 {
150  /*
151  */
152  return (NULL);
153 }
154 
157 
158 /**
159  * @brief Registered callback for HW interface state changes
160  */
161 static clib_error_t *
163  u32 hw_if_index,
164  u32 flags)
165 {
166  return (NULL);
167 }
168 
171 
172 static clib_error_t *
175  u32 is_add)
176 {
177  return (NULL);
178 }
179 
182 
183 #ifndef CLIB_MARCH_VARIANT
184 static u8*
185 format_dvr_reinject (u8* s, va_list *ap)
186 {
187  dvr_dpo_reinject_t ddr = va_arg(*ap, int);
188 
189  switch (ddr)
190  {
191  case DVR_REINJECT_L2:
192  s = format (s, "l2");
193  break;
194  case DVR_REINJECT_L3:
195  s = format (s, "l3");
196  break;
197  }
198  return (s);
199 }
200 
201 static u8*
202 format_dvr_dpo (u8* s, va_list *ap)
203 {
204  index_t index = va_arg(*ap, index_t);
205  CLIB_UNUSED(u32 indent) = va_arg(*ap, u32);
206  vnet_main_t * vnm = vnet_get_main();
207  dvr_dpo_t *dd = dvr_dpo_get(index);
208 
209  return (format(s, "%U-dvr-%U-dpo %U",
212  vnm,
215 }
216 
217 static void
219 {
220  fib_show_memory_usage("DVR",
221  pool_elts(dvr_dpo_pool),
222  pool_len(dvr_dpo_pool),
223  sizeof(dvr_dpo_t));
224 }
225 
226 
227 const static dpo_vft_t dvr_dpo_vft = {
229  .dv_unlock = dvr_dpo_unlock,
230  .dv_format = format_dvr_dpo,
231  .dv_mem_show = dvr_dpo_mem_show,
232 };
233 
234 /**
235  * @brief The per-protocol VLIB graph nodes that are assigned to a glean
236  * object.
237  *
238  * this means that these graph nodes are ones from which a glean is the
239  * parent object in the DPO-graph.
240  */
241 const static char* const dvr_dpo_ip4_nodes[] =
242 {
243  "ip4-dvr-dpo",
244  NULL,
245 };
246 const static char* const dvr_dpo_ip6_nodes[] =
247 {
248  "ip6-dvr-dpo",
249  NULL,
250 };
251 
252 const static char* const * const dvr_dpo_nodes[DPO_PROTO_NUM] =
253 {
256 };
257 
258 void
260 {
262  &dvr_dpo_vft,
263  dvr_dpo_nodes);
264 }
265 #endif /* CLIB_MARCH_VARIANT */
266 
267 /**
268  * @brief Interface DPO trace data
269  */
270 typedef struct dvr_dpo_trace_t_
271 {
274 
278  vlib_frame_t * from_frame,
279  u8 is_ip6)
280 {
281  u32 n_left_from, next_index, * from, * to_next;
282  ip_lookup_main_t *lm = (is_ip6?
285 
286  from = vlib_frame_vector_args (from_frame);
287  n_left_from = from_frame->n_vectors;
288 
289  next_index = node->cached_next_index;
290 
291  while (n_left_from > 0)
292  {
293  u32 n_left_to_next;
294 
295  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
296 
297  while (n_left_from >= 4 && n_left_to_next > 2)
298  {
299  const dvr_dpo_t *dd0, *dd1;
300  u32 bi0, ddi0, bi1, ddi1;
301  vlib_buffer_t *b0, *b1;
302  u32 next0, next1;
303  u8 len0, len1;
304 
305  bi0 = from[0];
306  to_next[0] = bi0;
307  bi1 = from[1];
308  to_next[1] = bi1;
309  from += 2;
310  to_next += 2;
311  n_left_from -= 2;
312  n_left_to_next -= 2;
313  next0 = next1 = 0;
314 
315  b0 = vlib_get_buffer (vm, bi0);
316  b1 = vlib_get_buffer (vm, bi1);
317 
318  ddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
319  ddi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
320  dd0 = dvr_dpo_get(ddi0);
321  dd1 = dvr_dpo_get(ddi1);
322 
323  vnet_buffer(b0)->sw_if_index[VLIB_TX] = dd0->dd_sw_if_index;
324  vnet_buffer(b1)->sw_if_index[VLIB_TX] = dd1->dd_sw_if_index;
325 
326  len0 = ((u8*)vlib_buffer_get_current(b0) -
328  len1 = ((u8*)vlib_buffer_get_current(b1) -
330  vnet_buffer(b0)->l2.l2_len =
331  vnet_buffer(b0)->ip.save_rewrite_length =
332  len0;
333  vnet_buffer(b1)->l2.l2_len =
334  vnet_buffer(b1)->ip.save_rewrite_length =
335  len1;
336 
337  b0->flags |= VNET_BUFFER_F_IS_DVR;
338  b1->flags |= VNET_BUFFER_F_IS_DVR;
339 
340  vlib_buffer_advance(b0, -len0);
341  vlib_buffer_advance(b1, -len1);
342 
344  dd0->dd_sw_if_index, &next0, b0);
346  dd1->dd_sw_if_index, &next1, b1);
347 
348  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
349  {
350  dvr_dpo_trace_t *tr0;
351 
352  tr0 = vlib_add_trace (vm, node, b0, sizeof (*tr0));
353  tr0->sw_if_index = dd0->dd_sw_if_index;
354  }
355  if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
356  {
357  dvr_dpo_trace_t *tr1;
358 
359  tr1 = vlib_add_trace (vm, node, b1, sizeof (*tr1));
360  tr1->sw_if_index = dd1->dd_sw_if_index;
361  }
362 
363  vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
364  n_left_to_next, bi0, bi1,
365  next0, next1);
366  }
367 
368  while (n_left_from > 0 && n_left_to_next > 0)
369  {
370  const dvr_dpo_t * dd0;
371  vlib_buffer_t * b0;
372  u32 bi0, ddi0;
373  u32 next0;
374  u8 len0;
375 
376  bi0 = from[0];
377  to_next[0] = bi0;
378  from += 1;
379  to_next += 1;
380  n_left_from -= 1;
381  n_left_to_next -= 1;
382  next0 = 0;
383 
384  b0 = vlib_get_buffer (vm, bi0);
385 
386  ddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
387  dd0 = dvr_dpo_get(ddi0);
388 
389  vnet_buffer(b0)->sw_if_index[VLIB_TX] = dd0->dd_sw_if_index;
390 
391  /*
392  * take that, rewind it back...
393  */
394  len0 = ((u8*)vlib_buffer_get_current(b0) -
396  vnet_buffer(b0)->l2.l2_len =
397  vnet_buffer(b0)->ip.save_rewrite_length =
398  len0;
399  b0->flags |= VNET_BUFFER_F_IS_DVR;
400  vlib_buffer_advance(b0, -len0);
401 
402  /*
403  * start processing the ipX output features
404  */
406  dd0->dd_sw_if_index, &next0, b0);
407 
408  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
409  {
410  dvr_dpo_trace_t *tr;
411 
412  tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
413  tr->sw_if_index = dd0->dd_sw_if_index;
414  }
415 
416  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
417  n_left_to_next, bi0,
418  next0);
419  }
420  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
421  }
422  return from_frame->n_vectors;
423 }
424 
425 static u8 *
426 format_dvr_dpo_trace (u8 * s, va_list * args)
427 {
428  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
429  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
430  dvr_dpo_trace_t * t = va_arg (*args, dvr_dpo_trace_t *);
431  u32 indent = format_get_indent (s);
432  s = format (s, "%U sw_if_index:%d",
433  format_white_space, indent,
434  t->sw_if_index);
435  return s;
436 }
437 
440  vlib_frame_t * from_frame)
441 {
442  return (dvr_dpo_inline(vm, node, from_frame, 0));
443 }
444 
447  vlib_frame_t * from_frame)
448 {
449  return (dvr_dpo_inline(vm, node, from_frame, 1));
450 }
451 
453  .name = "ip4-dvr-dpo",
454  .vector_size = sizeof (u32),
455  .format_trace = format_dvr_dpo_trace,
456  .sibling_of = "ip4-rewrite",
457 };
459  .name = "ip6-dvr-dpo",
460  .vector_size = sizeof (u32),
461  .format_trace = format_dvr_dpo_trace,
462  .sibling_of = "ip6-rewrite",
463 };
464 
466 {
470 
474  vlib_frame_t * from_frame)
475 {
476  u32 n_left_from, next_index, * from, * to_next;
477 
478  from = vlib_frame_vector_args (from_frame);
479  n_left_from = from_frame->n_vectors;
480 
481  next_index = node->cached_next_index;
482 
483  while (n_left_from > 0)
484  {
485  u32 n_left_to_next;
486 
487  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
488 
489  while (n_left_from >= 4 && n_left_to_next > 2)
490  {
491  dvr_reinject_next_t next0, next1;
492  const dvr_dpo_t *dd0, *dd1;
493  u32 bi0, bi1, ddi0, ddi1;
494  vlib_buffer_t *b0, *b1;
495 
496  bi0 = from[0];
497  to_next[0] = bi0;
498  bi1 = from[1];
499  to_next[1] = bi1;
500  from += 2;
501  to_next += 2;
502  n_left_from -= 2;
503  n_left_to_next -= 2;
504 
505  b0 = vlib_get_buffer (vm, bi0);
506  b1 = vlib_get_buffer (vm, bi1);
507 
508  if (b0->flags & VNET_BUFFER_F_IS_DVR)
509  {
510  ddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
511  dd0 = dvr_dpo_get(ddi0);
512  next0 = (dd0->dd_reinject == DVR_REINJECT_L2 ?
515  }
516  else
517  vnet_feature_next( &next0, b0);
518 
519  if (b1->flags & VNET_BUFFER_F_IS_DVR)
520  {
521  ddi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
522  dd1 = dvr_dpo_get(ddi1);
523  next1 = (dd1->dd_reinject == DVR_REINJECT_L2 ?
526  }
527  else
528  vnet_feature_next( &next1, b1);
529 
530  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
531  {
532  dvr_dpo_trace_t *tr0;
533 
534  tr0 = vlib_add_trace (vm, node, b0, sizeof (*tr0));
535  tr0->sw_if_index = vnet_buffer(b0)->sw_if_index[VLIB_TX];
536  }
537  if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
538  {
539  dvr_dpo_trace_t *tr1;
540 
541  tr1 = vlib_add_trace (vm, node, b1, sizeof (*tr1));
542  tr1->sw_if_index = vnet_buffer(b1)->sw_if_index[VLIB_TX];
543  }
544 
545  vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
546  n_left_to_next, bi0, bi1,
547  next0, next1);
548  }
549 
550  while (n_left_from > 0 && n_left_to_next > 0)
551  {
552  dvr_reinject_next_t next0;
553  const dvr_dpo_t *dd0;
554  vlib_buffer_t * b0;
555  u32 bi0, ddi0;
556 
557  bi0 = from[0];
558  to_next[0] = bi0;
559  from += 1;
560  to_next += 1;
561  n_left_from -= 1;
562  n_left_to_next -= 1;
563 
564  b0 = vlib_get_buffer (vm, bi0);
565 
566  if (b0->flags & VNET_BUFFER_F_IS_DVR)
567  {
568  ddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
569  dd0 = dvr_dpo_get(ddi0);
570  next0 = (dd0->dd_reinject == DVR_REINJECT_L2 ?
573  }
574  else
575  vnet_feature_next( &next0, b0);
576 
577  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
578  {
579  dvr_dpo_trace_t *tr;
580 
581  tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
582  tr->sw_if_index = vnet_buffer(b0)->sw_if_index[VLIB_TX];
583  }
584 
585  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
586  n_left_to_next, bi0, next0);
587  }
588  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
589  }
590  return from_frame->n_vectors;
591 }
592 
595  vlib_frame_t * from_frame)
596 {
597  return (dvr_reinject_inline(vm, node, from_frame));
598 }
599 
602  vlib_frame_t * from_frame)
603 {
604  return (dvr_reinject_inline(vm, node, from_frame));
605 }
606 
608  .name = "ip4-dvr-reinject",
609  .vector_size = sizeof (u32),
610  .format_trace = format_dvr_dpo_trace,
611 
612  .n_next_nodes = 1,
613  .next_nodes = {
614  [DVR_REINJECT_NEXT_L2] = "l2-output",
615  [DVR_REINJECT_NEXT_L3] = "interface-output",
616  },
617 };
618 
620  .name = "ip6-dvr-reinject",
621  .vector_size = sizeof (u32),
622  .format_trace = format_dvr_dpo_trace,
623 
624  .n_next_nodes = 1,
625  .next_nodes = {
626  [DVR_REINJECT_NEXT_L2] = "l2-output",
627  [DVR_REINJECT_NEXT_L3] = "interface-output",
628  },
629 };
630 
631 VNET_FEATURE_INIT (ip4_dvr_reinject_feat_node, static) =
632 {
633  .arc_name = "ip4-output",
634  .node_name = "ip4-dvr-reinject",
635  .runs_after = VNET_FEATURES ("nat44-in2out-output",
636  "acl-plugin-out-ip4-fa"),
637 };
638 VNET_FEATURE_INIT (ip6_dvr_reinject_feat_node, static) =
639 {
640  .arc_name = "ip6-output",
641  .node_name = "ip6-dvr-reinject",
642  .runs_after = VNET_FEATURES ("acl-plugin-out-ip6-fa"),
643 };
644 
static clib_error_t * dvr_dpo_interface_delete(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
Definition: dvr_dpo.c:173
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:411
vlib_node_registration_t ip6_dvr_dpo_node
(constructor) VLIB_REGISTER_NODE (ip6_dvr_dpo_node)
Definition: dvr_dpo.c:458
static clib_error_t * dvr_dpo_hw_interface_state_change(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Registered callback for HW interface state changes.
Definition: dvr_dpo.c:162
#define CLIB_UNUSED(x)
Definition: clib.h:87
A virtual function table regisitered for a DPO type.
Definition: dpo.h:406
static uword dvr_reinject_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: dvr_dpo.c:472
static u8 * format_dvr_dpo_trace(u8 *s, va_list *args)
Definition: dvr_dpo.c:426
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
Interface DPO trace data.
Definition: dvr_dpo.c:270
l2_input_config_t * l2input_intf_config(u32 sw_if_index)
Get a pointer to the config for the given interface.
Definition: l2_input.c:167
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
static u32 format_get_indent(u8 *s)
Definition: format.h:72
ip_lookup_main_t lookup_main
Definition: ip4.h:109
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
VNET_SW_INTERFACE_ADD_DEL_FUNCTION(dvr_dpo_interface_delete)
vlib_main_t * vm
Definition: in2out_ed.c:1580
#define VLIB_NODE_FN(node)
Definition: node.h:203
static dvr_dpo_t * dvr_dpo_get(index_t index)
Definition: dvr_dpo.h:77
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:251
u16 dd_locks
number of locks.
Definition: dvr_dpo.h:59
unsigned char u8
Definition: types.h:56
#define pool_len(p)
Number of elements in pool vector.
Definition: pool.h:139
static clib_error_t * dvr_dpo_interface_state_change(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
Definition: dvr_dpo.c:146
VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION(dvr_dpo_hw_interface_state_change)
u8 output_feature_arc_index
Definition: lookup.h:145
static index_t * dvr_dpo_db[DPO_PROTO_NUM]
The &#39;DB&#39; of DVR DPOs.
Definition: dvr_dpo.c:29
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
vlib_node_registration_t ip6_dvr_reinject_node
(constructor) VLIB_REGISTER_NODE (ip6_dvr_reinject_node)
Definition: dvr_dpo.c:619
enum dvr_dpo_reinject_t_ dvr_dpo_reinject_t
Control how the reinject is performed.
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
enum dvr_reinject_next_t_ dvr_reinject_next_t
description fragment has unexpected format
Definition: map.api:433
static index_t dvr_dpo_get_index(dvr_dpo_t *dd)
Definition: dvr_dpo.c:50
void fib_show_memory_usage(const char *name, u32 in_use_elts, u32 allocd_elts, size_t size_elt)
Show the memory usage for a type.
Definition: fib_node.c:220
unsigned int u32
Definition: types.h:88
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(dvr_dpo_interface_state_change)
bool is_ip6
Definition: ip.api:43
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
format_function_t format_vnet_sw_interface_name
static ethernet_header_t * ethernet_buffer_get_header(vlib_buffer_t *b)
Definition: ethernet.h:419
dpo_type_t dpoi_type
the type
Definition: dpo.h:176
struct dvr_dpo_trace_t_ dvr_dpo_trace_t
Interface DPO trace data.
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:233
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:301
VNET_FEATURE_INIT(ip4_dvr_reinject_feat_node, static)
#define PREDICT_FALSE(x)
Definition: clib.h:121
#define always_inline
Definition: ipsec.h:28
void dvr_dpo_module_init(void)
Definition: dvr_dpo.c:259
ip6_main_t ip6_main
Definition: ip6_forward.c:2785
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
Definition: buffer_node.h:70
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:224
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:391
void dvr_dpo_add_or_lock(u32 sw_if_index, dpo_proto_t dproto, dpo_id_t *dpo)
Definition: dvr_dpo.c:91
static void dvr_dpo_lock(dpo_id_t *dpo)
Definition: dvr_dpo.c:56
dpo_proto_t dd_proto
The protocol of packets using this DPO.
Definition: dvr_dpo.h:49
static void dvr_dpo_unlock(dpo_id_t *dpo)
Definition: dvr_dpo.c:65
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:170
u16 n_vectors
Definition: node.h:397
u32 dd_sw_if_index
The Software interface index that the packets will output on.
Definition: dvr_dpo.h:44
static_always_inline void vnet_feature_next(u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:322
static const char *const dvr_dpo_ip6_nodes[]
Definition: dvr_dpo.c:246
static dvr_dpo_t * dvr_dpo_get_from_dpo(const dpo_id_t *dpo)
Definition: dvr_dpo.c:42
vlib_node_registration_t ip4_dvr_reinject_node
(constructor) VLIB_REGISTER_NODE (ip4_dvr_reinject_node)
Definition: dvr_dpo.c:607
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:483
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
static bool l2_input_is_bridge(const l2_input_config_t *input)
Definition: l2_input.h:234
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1580
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:511
#define ASSERT(truth)
ip_lookup_main_t lookup_main
Definition: ip6.h:112
static bool l2_input_is_xconnect(const l2_input_config_t *input)
Definition: l2_input.h:240
static const char *const dvr_dpo_ip4_nodes[]
The per-protocol VLIB graph nodes that are assigned to a glean object.
Definition: dvr_dpo.c:241
static u8 * format_dvr_dpo(u8 *s, va_list *ap)
Definition: dvr_dpo.c:202
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:252
dvr_dpo_reinject_t dd_reinject
Control for how the re-inject is performed.
Definition: dvr_dpo.h:54
#define VNET_FEATURES(...)
Definition: feature.h:470
static u8 * format_dvr_reinject(u8 *s, va_list *ap)
Definition: dvr_dpo.c:185
Definition: defs.h:47
#define DPO_PROTO_NUM
Definition: dpo.h:70
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:188
#define INDEX_INVALID
Invalid index - used when no index is known blazoned capitals INVALID speak volumes where ~0 does not...
Definition: dpo.h:47
VLIB buffer representation.
Definition: buffer.h:102
The DVR DPO.
Definition: dvr_dpo.h:39
u64 uword
Definition: types.h:112
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:297
u32 index
Definition: flow_types.api:221
u8 * format_dpo_proto(u8 *s, va_list *args)
format a DPO protocol
Definition: dpo.c:178
vlib_node_registration_t ip4_dvr_dpo_node
(constructor) VLIB_REGISTER_NODE (ip4_dvr_dpo_node)
Definition: dvr_dpo.c:452
static const char *const *const dvr_dpo_nodes[DPO_PROTO_NUM]
Definition: dvr_dpo.c:252
#define vnet_buffer(b)
Definition: buffer.h:417
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1105
Definition: dpo.h:119
dvr_dpo_t * dvr_dpo_pool
pool of all interface DPOs
Definition: dvr_dpo.c:23
dvr_reinject_next_t_
Definition: dvr_dpo.c:465
static void dvr_dpo_mem_show(void)
Definition: dvr_dpo.c:218
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:634
static uword dvr_dpo_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame, u8 is_ip6)
Definition: dvr_dpo.c:276
#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
static dvr_dpo_t * dvr_dpo_alloc(void)
Definition: dvr_dpo.c:32
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
int vnet_feature_enable_disable(const char *arc_name, const char *node_name, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
Definition: feature.c:303
static_always_inline void vnet_feature_arc_start(u8 arc, u32 sw_if_index, u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:302
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127