FD.io VPP  v19.08-27-gf4dcae4
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 (config->bridge || config->xconnect)
114  {
116  }
117  else
118  {
120  }
121 
122  /*
123  * enable the reinject into L2 path feature on the interface
124  */
125  if (DPO_PROTO_IP4 == dproto)
126  vnet_feature_enable_disable ("ip4-output", "ip4-dvr-reinject",
127  dd->dd_sw_if_index, 1, 0, 0);
128  else if (DPO_PROTO_IP6 == dproto)
129  vnet_feature_enable_disable ("ip6-output", "ip6-dvr-reinject",
130  dd->dd_sw_if_index, 1, 0, 0);
131  else
132  ASSERT(0);
133  }
134  else
135  {
136  dd = dvr_dpo_get(dvr_dpo_db[dproto][sw_if_index]);
137  }
138 
139  dpo_set(dpo, DPO_DVR, dproto, dvr_dpo_get_index(dd));
140 }
141 #endif /* CLIB_MARCH_VARIANT */
142 
143 
144 static clib_error_t *
147  u32 flags)
148 {
149  /*
150  */
151  return (NULL);
152 }
153 
156 
157 /**
158  * @brief Registered callback for HW interface state changes
159  */
160 static clib_error_t *
162  u32 hw_if_index,
163  u32 flags)
164 {
165  return (NULL);
166 }
167 
170 
171 static clib_error_t *
174  u32 is_add)
175 {
176  return (NULL);
177 }
178 
181 
182 #ifndef CLIB_MARCH_VARIANT
183 static u8*
184 format_dvr_reinject (u8* s, va_list *ap)
185 {
186  dvr_dpo_reinject_t ddr = va_arg(*ap, int);
187 
188  switch (ddr)
189  {
190  case DVR_REINJECT_L2:
191  s = format (s, "l2");
192  break;
193  case DVR_REINJECT_L3:
194  s = format (s, "l3");
195  break;
196  }
197  return (s);
198 }
199 
200 static u8*
201 format_dvr_dpo (u8* s, va_list *ap)
202 {
203  index_t index = va_arg(*ap, index_t);
204  CLIB_UNUSED(u32 indent) = va_arg(*ap, u32);
205  vnet_main_t * vnm = vnet_get_main();
206  dvr_dpo_t *dd = dvr_dpo_get(index);
207 
208  return (format(s, "%U-dvr-%U-dpo %U",
211  vnm,
214 }
215 
216 static void
218 {
219  fib_show_memory_usage("DVR",
220  pool_elts(dvr_dpo_pool),
221  pool_len(dvr_dpo_pool),
222  sizeof(dvr_dpo_t));
223 }
224 
225 
226 const static dpo_vft_t dvr_dpo_vft = {
228  .dv_unlock = dvr_dpo_unlock,
229  .dv_format = format_dvr_dpo,
230  .dv_mem_show = dvr_dpo_mem_show,
231 };
232 
233 /**
234  * @brief The per-protocol VLIB graph nodes that are assigned to a glean
235  * object.
236  *
237  * this means that these graph nodes are ones from which a glean is the
238  * parent object in the DPO-graph.
239  */
240 const static char* const dvr_dpo_ip4_nodes[] =
241 {
242  "ip4-dvr-dpo",
243  NULL,
244 };
245 const static char* const dvr_dpo_ip6_nodes[] =
246 {
247  "ip6-dvr-dpo",
248  NULL,
249 };
250 
251 const static char* const * const dvr_dpo_nodes[DPO_PROTO_NUM] =
252 {
255 };
256 
257 void
259 {
261  &dvr_dpo_vft,
262  dvr_dpo_nodes);
263 }
264 #endif /* CLIB_MARCH_VARIANT */
265 
266 /**
267  * @brief Interface DPO trace data
268  */
269 typedef struct dvr_dpo_trace_t_
270 {
273 
276  vlib_node_runtime_t * node,
277  vlib_frame_t * from_frame,
278  u8 is_ip6)
279 {
280  u32 n_left_from, next_index, * from, * to_next;
281  ip_lookup_main_t *lm = (is_ip6?
284 
285  from = vlib_frame_vector_args (from_frame);
286  n_left_from = from_frame->n_vectors;
287 
288  next_index = node->cached_next_index;
289 
290  while (n_left_from > 0)
291  {
292  u32 n_left_to_next;
293 
294  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
295 
296  while (n_left_from >= 4 && n_left_to_next > 2)
297  {
298  const dvr_dpo_t *dd0, *dd1;
299  u32 bi0, ddi0, bi1, ddi1;
300  vlib_buffer_t *b0, *b1;
301  u32 next0, next1;
302  u8 len0, len1;
303 
304  bi0 = from[0];
305  to_next[0] = bi0;
306  bi1 = from[1];
307  to_next[1] = bi1;
308  from += 2;
309  to_next += 2;
310  n_left_from -= 2;
311  n_left_to_next -= 2;
312  next0 = next1 = 0;
313 
314  b0 = vlib_get_buffer (vm, bi0);
315  b1 = vlib_get_buffer (vm, bi1);
316 
317  ddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
318  ddi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
319  dd0 = dvr_dpo_get(ddi0);
320  dd1 = dvr_dpo_get(ddi1);
321 
322  vnet_buffer(b0)->sw_if_index[VLIB_TX] = dd0->dd_sw_if_index;
323  vnet_buffer(b1)->sw_if_index[VLIB_TX] = dd1->dd_sw_if_index;
324 
325  len0 = ((u8*)vlib_buffer_get_current(b0) -
327  len1 = ((u8*)vlib_buffer_get_current(b1) -
329  vnet_buffer(b0)->l2.l2_len =
330  vnet_buffer(b0)->ip.save_rewrite_length =
331  len0;
332  vnet_buffer(b1)->l2.l2_len =
333  vnet_buffer(b1)->ip.save_rewrite_length =
334  len1;
335 
336  b0->flags |= VNET_BUFFER_F_IS_DVR;
337  b1->flags |= VNET_BUFFER_F_IS_DVR;
338 
339  vlib_buffer_advance(b0, -len0);
340  vlib_buffer_advance(b1, -len1);
341 
343  dd0->dd_sw_if_index, &next0, b0);
345  dd1->dd_sw_if_index, &next1, b1);
346 
347  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
348  {
349  dvr_dpo_trace_t *tr0;
350 
351  tr0 = vlib_add_trace (vm, node, b0, sizeof (*tr0));
352  tr0->sw_if_index = dd0->dd_sw_if_index;
353  }
354  if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
355  {
356  dvr_dpo_trace_t *tr1;
357 
358  tr1 = vlib_add_trace (vm, node, b1, sizeof (*tr1));
359  tr1->sw_if_index = dd1->dd_sw_if_index;
360  }
361 
362  vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
363  n_left_to_next, bi0, bi1,
364  next0, next1);
365  }
366 
367  while (n_left_from > 0 && n_left_to_next > 0)
368  {
369  const dvr_dpo_t * dd0;
370  vlib_buffer_t * b0;
371  u32 bi0, ddi0;
372  u32 next0;
373  u8 len0;
374 
375  bi0 = from[0];
376  to_next[0] = bi0;
377  from += 1;
378  to_next += 1;
379  n_left_from -= 1;
380  n_left_to_next -= 1;
381  next0 = 0;
382 
383  b0 = vlib_get_buffer (vm, bi0);
384 
385  ddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
386  dd0 = dvr_dpo_get(ddi0);
387 
388  vnet_buffer(b0)->sw_if_index[VLIB_TX] = dd0->dd_sw_if_index;
389 
390  /*
391  * take that, rewind it back...
392  */
393  len0 = ((u8*)vlib_buffer_get_current(b0) -
395  vnet_buffer(b0)->l2.l2_len =
396  vnet_buffer(b0)->ip.save_rewrite_length =
397  len0;
398  b0->flags |= VNET_BUFFER_F_IS_DVR;
399  vlib_buffer_advance(b0, -len0);
400 
401  /*
402  * start processing the ipX output features
403  */
405  dd0->dd_sw_if_index, &next0, b0);
406 
407  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
408  {
409  dvr_dpo_trace_t *tr;
410 
411  tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
412  tr->sw_if_index = dd0->dd_sw_if_index;
413  }
414 
415  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
416  n_left_to_next, bi0,
417  next0);
418  }
419  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
420  }
421  return from_frame->n_vectors;
422 }
423 
424 static u8 *
425 format_dvr_dpo_trace (u8 * s, va_list * args)
426 {
427  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
428  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
429  dvr_dpo_trace_t * t = va_arg (*args, dvr_dpo_trace_t *);
430  u32 indent = format_get_indent (s);
431  s = format (s, "%U sw_if_index:%d",
432  format_white_space, indent,
433  t->sw_if_index);
434  return s;
435 }
436 
438  vlib_node_runtime_t * node,
439  vlib_frame_t * from_frame)
440 {
441  return (dvr_dpo_inline(vm, node, from_frame, 0));
442 }
443 
445  vlib_node_runtime_t * node,
446  vlib_frame_t * from_frame)
447 {
448  return (dvr_dpo_inline(vm, node, from_frame, 1));
449 }
450 
452  .name = "ip4-dvr-dpo",
453  .vector_size = sizeof (u32),
454  .format_trace = format_dvr_dpo_trace,
455  .sibling_of = "ip4-rewrite",
456 };
458  .name = "ip6-dvr-dpo",
459  .vector_size = sizeof (u32),
460  .format_trace = format_dvr_dpo_trace,
461  .sibling_of = "ip6-rewrite",
462 };
463 
465 {
469 
472  vlib_node_runtime_t * node,
473  vlib_frame_t * from_frame)
474 {
475  u32 n_left_from, next_index, * from, * to_next;
476 
477  from = vlib_frame_vector_args (from_frame);
478  n_left_from = from_frame->n_vectors;
479 
480  next_index = node->cached_next_index;
481 
482  while (n_left_from > 0)
483  {
484  u32 n_left_to_next;
485 
486  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
487 
488  while (n_left_from >= 4 && n_left_to_next > 2)
489  {
490  dvr_reinject_next_t next0, next1;
491  const dvr_dpo_t *dd0, *dd1;
492  u32 bi0, bi1, ddi0, ddi1;
493  vlib_buffer_t *b0, *b1;
494 
495  bi0 = from[0];
496  to_next[0] = bi0;
497  bi1 = from[1];
498  to_next[1] = bi1;
499  from += 2;
500  to_next += 2;
501  n_left_from -= 2;
502  n_left_to_next -= 2;
503 
504  b0 = vlib_get_buffer (vm, bi0);
505  b1 = vlib_get_buffer (vm, bi1);
506 
507  if (b0->flags & VNET_BUFFER_F_IS_DVR)
508  {
509  ddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
510  dd0 = dvr_dpo_get(ddi0);
511  next0 = (dd0->dd_reinject == DVR_REINJECT_L2 ?
514  }
515  else
516  vnet_feature_next( &next0, b0);
517 
518  if (b1->flags & VNET_BUFFER_F_IS_DVR)
519  {
520  ddi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
521  dd1 = dvr_dpo_get(ddi1);
522  next1 = (dd1->dd_reinject == DVR_REINJECT_L2 ?
525  }
526  else
527  vnet_feature_next( &next1, b1);
528 
529  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
530  {
531  dvr_dpo_trace_t *tr0;
532 
533  tr0 = vlib_add_trace (vm, node, b0, sizeof (*tr0));
534  tr0->sw_if_index = vnet_buffer(b0)->sw_if_index[VLIB_TX];
535  }
536  if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
537  {
538  dvr_dpo_trace_t *tr1;
539 
540  tr1 = vlib_add_trace (vm, node, b1, sizeof (*tr1));
541  tr1->sw_if_index = vnet_buffer(b1)->sw_if_index[VLIB_TX];
542  }
543 
544  vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
545  n_left_to_next, bi0, bi1,
546  next0, next1);
547  }
548 
549  while (n_left_from > 0 && n_left_to_next > 0)
550  {
551  dvr_reinject_next_t next0;
552  const dvr_dpo_t *dd0;
553  vlib_buffer_t * b0;
554  u32 bi0, ddi0;
555 
556  bi0 = from[0];
557  to_next[0] = bi0;
558  from += 1;
559  to_next += 1;
560  n_left_from -= 1;
561  n_left_to_next -= 1;
562 
563  b0 = vlib_get_buffer (vm, bi0);
564 
565  if (b0->flags & VNET_BUFFER_F_IS_DVR)
566  {
567  ddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
568  dd0 = dvr_dpo_get(ddi0);
569  next0 = (dd0->dd_reinject == DVR_REINJECT_L2 ?
572  }
573  else
574  vnet_feature_next( &next0, b0);
575 
576  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
577  {
578  dvr_dpo_trace_t *tr;
579 
580  tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
581  tr->sw_if_index = vnet_buffer(b0)->sw_if_index[VLIB_TX];
582  }
583 
584  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
585  n_left_to_next, bi0, next0);
586  }
587  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
588  }
589  return from_frame->n_vectors;
590 }
591 
593  vlib_node_runtime_t * node,
594  vlib_frame_t * from_frame)
595 {
596  return (dvr_reinject_inline(vm, node, from_frame));
597 }
598 
600  vlib_node_runtime_t * node,
601  vlib_frame_t * from_frame)
602 {
603  return (dvr_reinject_inline(vm, node, from_frame));
604 }
605 
607  .name = "ip4-dvr-reinject",
608  .vector_size = sizeof (u32),
609  .format_trace = format_dvr_dpo_trace,
610 
611  .n_next_nodes = 1,
612  .next_nodes = {
613  [DVR_REINJECT_NEXT_L2] = "l2-output",
614  [DVR_REINJECT_NEXT_L3] = "interface-output",
615  },
616 };
617 
619  .name = "ip6-dvr-reinject",
620  .vector_size = sizeof (u32),
621  .format_trace = format_dvr_dpo_trace,
622 
623  .n_next_nodes = 1,
624  .next_nodes = {
625  [DVR_REINJECT_NEXT_L2] = "l2-output",
626  [DVR_REINJECT_NEXT_L3] = "interface-output",
627  },
628 };
629 
630 VNET_FEATURE_INIT (ip4_dvr_reinject_feat_node, static) =
631 {
632  .arc_name = "ip4-output",
633  .node_name = "ip4-dvr-reinject",
634  .runs_after = VNET_FEATURES ("nat44-in2out-output",
635  "acl-plugin-out-ip4-fa"),
636 };
637 VNET_FEATURE_INIT (ip6_dvr_reinject_feat_node, static) =
638 {
639  .arc_name = "ip6-output",
640  .node_name = "ip6-dvr-reinject",
641  .runs_after = VNET_FEATURES ("acl-plugin-out-ip6-fa"),
642 };
643 
static clib_error_t * dvr_dpo_interface_delete(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
Definition: dvr_dpo.c:172
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:406
vlib_node_registration_t ip6_dvr_dpo_node
(constructor) VLIB_REGISTER_NODE (ip6_dvr_dpo_node)
Definition: dvr_dpo.c:457
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:161
u32 flags
Definition: vhost_user.h:141
#define CLIB_UNUSED(x)
Definition: clib.h:82
A virtual function table regisitered for a DPO type.
Definition: dpo.h:401
static uword dvr_reinject_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: dvr_dpo.c:471
static u8 * format_dvr_dpo_trace(u8 *s, va_list *args)
Definition: dvr_dpo.c:425
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
Interface DPO trace data.
Definition: dvr_dpo.c:269
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:528
#define NULL
Definition: clib.h:58
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:107
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)
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
#define VLIB_NODE_FN(node)
Definition: node.h:201
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:236
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:140
static clib_error_t * dvr_dpo_interface_state_change(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
Definition: dvr_dpo.c:145
VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION(dvr_dpo_hw_interface_state_change)
u8 output_feature_arc_index
Definition: lookup.h:140
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:322
vlib_node_registration_t ip6_dvr_reinject_node
(constructor) VLIB_REGISTER_NODE (ip6_dvr_reinject_node)
Definition: dvr_dpo.c:618
enum dvr_dpo_reinject_t_ dvr_dpo_reinject_t
Control how the reinject is performed.
vl_api_interface_index_t sw_if_index
Definition: gre.api:50
#define always_inline
Definition: clib.h:98
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
enum dvr_reinject_next_t_ dvr_reinject_next_t
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)
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:376
dpo_type_t dpoi_type
the type
Definition: dpo.h:174
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:229
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:286
VNET_FEATURE_INIT(ip4_dvr_reinject_feat_node, static)
#define PREDICT_FALSE(x)
Definition: clib.h:111
void dvr_dpo_module_init(void)
Definition: dvr_dpo.c:258
#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:218
#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:338
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:169
u16 n_vectors
Definition: node.h:395
vlib_main_t * vm
Definition: buffer.c:312
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:295
static const char *const dvr_dpo_ip6_nodes[]
Definition: dvr_dpo.c:245
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:606
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:458
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
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:513
#define ASSERT(truth)
ip6_main_t ip6_main
Definition: ip6_forward.c:2671
ip_lookup_main_t lookup_main
Definition: ip6.h:179
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:240
static u8 * format_dvr_dpo(u8 *s, va_list *ap)
Definition: dvr_dpo.c:201
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:248
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:435
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
static u8 * format_dvr_reinject(u8 *s, va_list *ap)
Definition: dvr_dpo.c:184
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:186
#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:244
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:451
static const char *const *const dvr_dpo_nodes[DPO_PROTO_NUM]
Definition: dvr_dpo.c:251
#define vnet_buffer(b)
Definition: buffer.h:361
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:921
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:464
static void dvr_dpo_mem_show(void)
Definition: dvr_dpo.c:217
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:275
#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:486
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
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:274
static_always_inline void vnet_feature_arc_start(u8 arc, u32 sw_if_index, u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:275
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128