FD.io VPP  v18.10-34-gcce845e
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 
21 /**
22  * The 'DB' of DVR DPOs.
23  * There is one per-interface per-L3 proto, so this is a per-interface vector
24  */
26 
27 static dvr_dpo_t *
29 {
30  dvr_dpo_t *dd;
31 
33 
34  return (dd);
35 }
36 
37 static inline dvr_dpo_t *
39 {
40  ASSERT(DPO_DVR == dpo->dpoi_type);
41 
42  return (dvr_dpo_get(dpo->dpoi_index));
43 }
44 
45 static inline index_t
47 {
48  return (dd - dvr_dpo_pool);
49 }
50 
51 static void
53 {
54  dvr_dpo_t *dd;
55 
56  dd = dvr_dpo_get_from_dpo(dpo);
57  dd->dd_locks++;
58 }
59 
60 static void
62 {
63  dvr_dpo_t *dd;
64 
65  dd = dvr_dpo_get_from_dpo(dpo);
66  dd->dd_locks--;
67 
68  if (0 == dd->dd_locks)
69  {
70  if (DPO_PROTO_IP4 == dd->dd_proto)
71  {
72  vnet_feature_enable_disable ("ip4-output", "ip4-dvr-reinject",
73  dd->dd_sw_if_index, 0, 0, 0);
74  }
75  else
76  {
77  vnet_feature_enable_disable ("ip6-output", "ip6-dvr-reinject",
78  dd->dd_sw_if_index, 0, 0, 0);
79  }
80 
83  }
84 }
85 
86 void
88  dpo_proto_t dproto,
89  dpo_id_t *dpo)
90 {
91  dvr_dpo_t *dd;
92 
94  sw_if_index,
96 
97  if (INDEX_INVALID == dvr_dpo_db[dproto][sw_if_index])
98  {
99  dd = dvr_dpo_alloc();
100 
102  dd->dd_proto = dproto;
103 
105 
106  /*
107  * enable the reinject into L2 path feature on the interface
108  */
109  if (DPO_PROTO_IP4 == dproto)
110  vnet_feature_enable_disable ("ip4-output", "ip4-dvr-reinject",
111  dd->dd_sw_if_index, 1, 0, 0);
112  else if (DPO_PROTO_IP6 == dproto)
113  vnet_feature_enable_disable ("ip6-output", "ip6-dvr-reinject",
114  dd->dd_sw_if_index, 1, 0, 0);
115  else
116  ASSERT(0);
117  }
118  else
119  {
120  dd = dvr_dpo_get(dvr_dpo_db[dproto][sw_if_index]);
121  }
122 
123  dpo_set(dpo, DPO_DVR, dproto, dvr_dpo_get_index(dd));
124 }
125 
126 
127 static clib_error_t *
130  u32 flags)
131 {
132  /*
133  */
134  return (NULL);
135 }
136 
139 
140 /**
141  * @brief Registered callback for HW interface state changes
142  */
143 static clib_error_t *
145  u32 hw_if_index,
146  u32 flags)
147 {
148  return (NULL);
149 }
150 
153 
154 static clib_error_t *
157  u32 is_add)
158 {
159  return (NULL);
160 }
161 
164 
165 u8*
166 format_dvr_dpo (u8* s, va_list *ap)
167 {
168  index_t index = va_arg(*ap, index_t);
169  CLIB_UNUSED(u32 indent) = va_arg(*ap, u32);
170  vnet_main_t * vnm = vnet_get_main();
171  dvr_dpo_t *dd = dvr_dpo_get(index);
172 
173  return (format(s, "dvr-%U-dpo",
175  vnm,
177 }
178 
179 static void
181 {
182  fib_show_memory_usage("DVR",
185  sizeof(dvr_dpo_t));
186 }
187 
188 
189 const static dpo_vft_t dvr_dpo_vft = {
191  .dv_unlock = dvr_dpo_unlock,
192  .dv_format = format_dvr_dpo,
193  .dv_mem_show = dvr_dpo_mem_show,
194 };
195 
196 /**
197  * @brief The per-protocol VLIB graph nodes that are assigned to a glean
198  * object.
199  *
200  * this means that these graph nodes are ones from which a glean is the
201  * parent object in the DPO-graph.
202  */
203 const static char* const dvr_dpo_ip4_nodes[] =
204 {
205  "ip4-dvr-dpo",
206  NULL,
207 };
208 const static char* const dvr_dpo_ip6_nodes[] =
209 {
210  "ip6-dvr-dpo",
211  NULL,
212 };
213 
214 const static char* const * const dvr_dpo_nodes[DPO_PROTO_NUM] =
215 {
218 };
219 
220 void
222 {
224  &dvr_dpo_vft,
225  dvr_dpo_nodes);
226 }
227 
228 /**
229  * @brief Interface DPO trace data
230  */
231 typedef struct dvr_dpo_trace_t_
232 {
235 
238  vlib_node_runtime_t * node,
239  vlib_frame_t * from_frame,
240  u8 is_ip6)
241 {
242  u32 n_left_from, next_index, * from, * to_next;
243  ip_lookup_main_t *lm = (is_ip6?
246 
247  from = vlib_frame_vector_args (from_frame);
248  n_left_from = from_frame->n_vectors;
249 
250  next_index = node->cached_next_index;
251 
252  while (n_left_from > 0)
253  {
254  u32 n_left_to_next;
255 
256  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
257 
258  while (n_left_from >= 4 && n_left_to_next > 2)
259  {
260  const dvr_dpo_t *dd0, *dd1;
261  u32 bi0, ddi0, bi1, ddi1;
262  vlib_buffer_t *b0, *b1;
263  u32 next0, next1;
264  u8 len0, len1;
265 
266  bi0 = from[0];
267  to_next[0] = bi0;
268  bi1 = from[1];
269  to_next[1] = bi1;
270  from += 2;
271  to_next += 2;
272  n_left_from -= 2;
273  n_left_to_next -= 2;
274  next0 = next1 = 0;
275 
276  b0 = vlib_get_buffer (vm, bi0);
277  b1 = vlib_get_buffer (vm, bi1);
278 
279  ddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
280  ddi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
281  dd0 = dvr_dpo_get(ddi0);
282  dd1 = dvr_dpo_get(ddi1);
283 
284  vnet_buffer(b0)->sw_if_index[VLIB_TX] = dd0->dd_sw_if_index;
285  vnet_buffer(b1)->sw_if_index[VLIB_TX] = dd1->dd_sw_if_index;
286 
287  len0 = ((u8*)vlib_buffer_get_current(b0) -
289  len1 = ((u8*)vlib_buffer_get_current(b1) -
291  vnet_buffer(b0)->l2.l2_len =
292  vnet_buffer(b0)->ip.save_rewrite_length =
293  len0;
294  vnet_buffer(b1)->l2.l2_len =
295  vnet_buffer(b1)->ip.save_rewrite_length =
296  len1;
297  b0->flags |= VNET_BUFFER_F_IS_DVR;
298  b1->flags |= VNET_BUFFER_F_IS_DVR;
299 
300  vlib_buffer_advance(b0, -len0);
301  vlib_buffer_advance(b1, -len1);
302 
304  dd0->dd_sw_if_index, &next0, b0);
306  dd1->dd_sw_if_index, &next1, b1);
307 
308  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
309  {
310  dvr_dpo_trace_t *tr0;
311 
312  tr0 = vlib_add_trace (vm, node, b0, sizeof (*tr0));
313  tr0->sw_if_index = dd0->dd_sw_if_index;
314  }
315  if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
316  {
317  dvr_dpo_trace_t *tr1;
318 
319  tr1 = vlib_add_trace (vm, node, b1, sizeof (*tr1));
320  tr1->sw_if_index = dd1->dd_sw_if_index;
321  }
322 
323  vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
324  n_left_to_next, bi0, bi1,
325  next0, next1);
326  }
327 
328  while (n_left_from > 0 && n_left_to_next > 0)
329  {
330  const dvr_dpo_t * dd0;
331  vlib_buffer_t * b0;
332  u32 bi0, ddi0;
333  u32 next0;
334  u8 len0;
335 
336  bi0 = from[0];
337  to_next[0] = bi0;
338  from += 1;
339  to_next += 1;
340  n_left_from -= 1;
341  n_left_to_next -= 1;
342  next0 = 0;
343 
344  b0 = vlib_get_buffer (vm, bi0);
345 
346  ddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
347  dd0 = dvr_dpo_get(ddi0);
348 
349  vnet_buffer(b0)->sw_if_index[VLIB_TX] = dd0->dd_sw_if_index;
350 
351  /*
352  * take that, rewind it back...
353  */
354  len0 = ((u8*)vlib_buffer_get_current(b0) -
356  vnet_buffer(b0)->l2.l2_len =
357  vnet_buffer(b0)->ip.save_rewrite_length =
358  len0;
359  b0->flags |= VNET_BUFFER_F_IS_DVR;
360  vlib_buffer_advance(b0, -len0);
361 
362  /*
363  * start processing the ipX output features
364  */
366  dd0->dd_sw_if_index, &next0, b0);
367 
368  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
369  {
370  dvr_dpo_trace_t *tr;
371 
372  tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
373  tr->sw_if_index = dd0->dd_sw_if_index;
374  }
375 
376  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
377  n_left_to_next, bi0,
378  next0);
379  }
380  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
381  }
382  return from_frame->n_vectors;
383 }
384 
385 static u8 *
386 format_dvr_dpo_trace (u8 * s, va_list * args)
387 {
388  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
389  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
390  dvr_dpo_trace_t * t = va_arg (*args, dvr_dpo_trace_t *);
391  u32 indent = format_get_indent (s);
392  s = format (s, "%U sw_if_index:%d",
393  format_white_space, indent,
394  t->sw_if_index);
395  return s;
396 }
397 
398 static uword
400  vlib_node_runtime_t * node,
401  vlib_frame_t * from_frame)
402 {
403  return (dvr_dpo_inline(vm, node, from_frame, 0));
404 }
405 
406 static uword
408  vlib_node_runtime_t * node,
409  vlib_frame_t * from_frame)
410 {
411  return (dvr_dpo_inline(vm, node, from_frame, 1));
412 }
413 
415  .function = ip4_dvr_dpo,
416  .name = "ip4-dvr-dpo",
417  .vector_size = sizeof (u32),
418  .format_trace = format_dvr_dpo_trace,
419  .sibling_of = "ip4-rewrite",
420 };
422  .function = ip6_dvr_dpo,
423  .name = "ip6-dvr-dpo",
424  .vector_size = sizeof (u32),
425  .format_trace = format_dvr_dpo_trace,
426  .sibling_of = "ip6-rewrite",
427 };
428 
431 
433 {
436 
439  vlib_node_runtime_t * node,
440  vlib_frame_t * from_frame)
441 {
442  u32 n_left_from, next_index, * from, * to_next;
443 
444  from = vlib_frame_vector_args (from_frame);
445  n_left_from = from_frame->n_vectors;
446 
447  next_index = node->cached_next_index;
448 
449  while (n_left_from > 0)
450  {
451  u32 n_left_to_next;
452 
453  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
454 
455  while (n_left_from >= 4 && n_left_to_next > 2)
456  {
457  dvr_reinject_next_t next0, next1;
458  vlib_buffer_t *b0, *b1;
459  u32 bi0, bi1;
460 
461  bi0 = from[0];
462  to_next[0] = bi0;
463  bi1 = from[1];
464  to_next[1] = bi1;
465  from += 2;
466  to_next += 2;
467  n_left_from -= 2;
468  n_left_to_next -= 2;
469 
470  b0 = vlib_get_buffer (vm, bi0);
471  b1 = vlib_get_buffer (vm, bi1);
472 
473  if (b0->flags & VNET_BUFFER_F_IS_DVR)
474  next0 = DVR_REINJECT_OUTPUT;
475  else
476  vnet_feature_next( &next0, b0);
477 
478  if (b1->flags & VNET_BUFFER_F_IS_DVR)
479  next1 = DVR_REINJECT_OUTPUT;
480  else
481  vnet_feature_next( &next1, b1);
482 
483  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
484  {
485  dvr_dpo_trace_t *tr0;
486 
487  tr0 = vlib_add_trace (vm, node, b0, sizeof (*tr0));
488  tr0->sw_if_index = vnet_buffer(b0)->sw_if_index[VLIB_TX];
489  }
490  if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
491  {
492  dvr_dpo_trace_t *tr1;
493 
494  tr1 = vlib_add_trace (vm, node, b1, sizeof (*tr1));
495  tr1->sw_if_index = vnet_buffer(b1)->sw_if_index[VLIB_TX];
496  }
497 
498  vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
499  n_left_to_next, bi0, bi1,
500  next0, next1);
501  }
502 
503  while (n_left_from > 0 && n_left_to_next > 0)
504  {
505  dvr_reinject_next_t next0;
506  vlib_buffer_t * b0;
507  u32 bi0;
508 
509  bi0 = from[0];
510  to_next[0] = bi0;
511  from += 1;
512  to_next += 1;
513  n_left_from -= 1;
514  n_left_to_next -= 1;
515 
516  b0 = vlib_get_buffer (vm, bi0);
517 
518  if (b0->flags & VNET_BUFFER_F_IS_DVR)
519  next0 = DVR_REINJECT_OUTPUT;
520  else
521  vnet_feature_next( &next0, b0);
522 
523  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
524  {
525  dvr_dpo_trace_t *tr;
526 
527  tr = vlib_add_trace (vm, node, b0, sizeof (*tr));
528  tr->sw_if_index = vnet_buffer(b0)->sw_if_index[VLIB_TX];
529  }
530 
531  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
532  n_left_to_next, bi0, next0);
533  }
534  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
535  }
536  return from_frame->n_vectors;
537 }
538 
539 static uword
541  vlib_node_runtime_t * node,
542  vlib_frame_t * from_frame)
543 {
544  return (dvr_reinject_inline(vm, node, from_frame));
545 }
546 
547 static uword
549  vlib_node_runtime_t * node,
550  vlib_frame_t * from_frame)
551 {
552  return (dvr_reinject_inline(vm, node, from_frame));
553 }
554 
556  .function = ip4_dvr_reinject,
557  .name = "ip4-dvr-reinject",
558  .vector_size = sizeof (u32),
559  .format_trace = format_dvr_dpo_trace,
560 
561  .n_next_nodes = 1,
562  .next_nodes = {
563  [DVR_REINJECT_OUTPUT] = "l2-output",
564  },
565 };
566 
568  .function = ip6_dvr_reinject,
569  .name = "ip6-dvr-reinject",
570  .vector_size = sizeof (u32),
571  .format_trace = format_dvr_dpo_trace,
572 
573  .n_next_nodes = 1,
574  .next_nodes = {
575  [DVR_REINJECT_OUTPUT] = "l2-output",
576  },
577 };
578 
579 VNET_FEATURE_INIT (ip4_dvr_reinject_feat_node, static) =
580 {
581  .arc_name = "ip4-output",
582  .node_name = "ip4-dvr-reinject",
583  .runs_after = VNET_FEATURES ("nat44-in2out-output",
584  "acl-plugin-out-ip4-fa"),
585 };
586 VNET_FEATURE_INIT (ip6_dvr_reinject_feat_node, static) =
587 {
588  .arc_name = "ip6-output",
589  .node_name = "ip6-dvr-reinject",
590  .runs_after = VNET_FEATURES ("acl-plugin-out-ip6-fa"),
591 };
592 
static clib_error_t * dvr_dpo_interface_delete(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
Definition: dvr_dpo.c:155
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:404
vlib_node_registration_t ip6_dvr_dpo_node
(constructor) VLIB_REGISTER_NODE (ip6_dvr_dpo_node)
Definition: dvr_dpo.c:421
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:144
#define CLIB_UNUSED(x)
Definition: clib.h:81
A virtual function table regisitered for a DPO type.
Definition: dpo.h:399
static uword dvr_reinject_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: dvr_dpo.c:438
static u8 * format_dvr_dpo_trace(u8 *s, va_list *args)
Definition: dvr_dpo.c:386
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
Interface DPO trace data.
Definition: dvr_dpo.c:231
u8 * format_dvr_dpo(u8 *s, va_list *ap)
Definition: dvr_dpo.c:166
#define NULL
Definition: clib.h:57
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:98
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:419
static dvr_dpo_t * dvr_dpo_get(index_t index)
Definition: dvr_dpo.h:60
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:228
u16 dd_locks
number of locks.
Definition: dvr_dpo.h:45
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:128
VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION(dvr_dpo_hw_interface_state_change)
u8 output_feature_arc_index
Definition: lookup.h:138
static index_t * dvr_dpo_db[DPO_PROTO_NUM]
The &#39;DB&#39; of DVR DPOs.
Definition: dvr_dpo.c:25
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:321
vlib_node_registration_t ip6_dvr_reinject_node
(constructor) VLIB_REGISTER_NODE (ip6_dvr_reinject_node)
Definition: dvr_dpo.c:567
u32 sw_if_index
Definition: vxlan_gbp.api:39
#define always_inline
Definition: clib.h:94
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
enum dvr_reinject_next_t_ dvr_reinject_next_t
static index_t dvr_dpo_get_index(dvr_dpo_t *dd)
Definition: dvr_dpo.c:46
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)
#define VLIB_NODE_FUNCTION_MULTIARCH(node, fn)
Definition: node.h:209
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:168
format_function_t format_vnet_sw_interface_name
static ethernet_header_t * ethernet_buffer_get_header(vlib_buffer_t *b)
Definition: ethernet.h:394
dpo_type_t dpoi_type
the type
Definition: dpo.h:172
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:205
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:274
VNET_FEATURE_INIT(ip4_dvr_reinject_feat_node, static)
#define PREDICT_FALSE(x)
Definition: clib.h:107
void dvr_dpo_module_init(void)
Definition: dvr_dpo.c:221
static uword ip4_dvr_dpo(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: dvr_dpo.c:399
#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:364
void dvr_dpo_add_or_lock(u32 sw_if_index, dpo_proto_t dproto, dpo_id_t *dpo)
Definition: dvr_dpo.c:87
static void dvr_dpo_lock(dpo_id_t *dpo)
Definition: dvr_dpo.c:52
u32 flags
Definition: vhost_user.h:115
dpo_proto_t dd_proto
The protocol of packets using this DPO.
Definition: dvr_dpo.h:40
static void dvr_dpo_unlock(dpo_id_t *dpo)
Definition: dvr_dpo.c:61
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:155
u16 n_vectors
Definition: node.h:401
vlib_main_t * vm
Definition: buffer.c:294
u32 dd_sw_if_index
The Software interface index that the packets will output on.
Definition: dvr_dpo.h:35
static_always_inline void vnet_feature_next(u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:246
static const char *const dvr_dpo_ip6_nodes[]
Definition: dvr_dpo.c:208
static dvr_dpo_t * dvr_dpo_get_from_dpo(const dpo_id_t *dpo)
Definition: dvr_dpo.c:38
vlib_node_registration_t ip4_dvr_reinject_node
(constructor) VLIB_REGISTER_NODE (ip4_dvr_reinject_node)
Definition: dvr_dpo.c:555
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:455
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:185
dvr_dpo_t * dvr_dpo_pool
pool of all interface DPOs
Definition: dvr_dpo.h:57
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:2590
ip_lookup_main_t lookup_main
Definition: ip6.h:161
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:203
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:218
#define VNET_FEATURES(...)
Definition: feature.h:386
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:57
Definition: defs.h:47
#define DPO_PROTO_NUM
Definition: dpo.h:70
static uword ip6_dvr_reinject(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: dvr_dpo.c:548
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:184
#define INDEX_INVALID
Invalid index - used when no index is known blazoned capitals INVALID speak volumes where ~0 does not...
Definition: dpo.h:47
static uword ip4_dvr_reinject(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: dvr_dpo.c:540
The DVR DPO.
Definition: dvr_dpo.h:30
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:267
static uword ip6_dvr_dpo(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: dvr_dpo.c:407
vlib_node_registration_t ip4_dvr_dpo_node
(constructor) VLIB_REGISTER_NODE (ip4_dvr_dpo_node)
Definition: dvr_dpo.c:414
static const char *const *const dvr_dpo_nodes[DPO_PROTO_NUM]
Definition: dvr_dpo.c:214
#define vnet_buffer(b)
Definition: buffer.h:344
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:900
Definition: dpo.h:119
dvr_reinject_next_t_
Definition: dvr_dpo.c:432
static void dvr_dpo_mem_show(void)
Definition: dvr_dpo.c:180
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:237
#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
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:116
static dvr_dpo_t * dvr_dpo_alloc(void)
Definition: dvr_dpo.c:28
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:58
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:233
static_always_inline void vnet_feature_arc_start(u8 arc, u32 sw_if_index, u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:226
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128