FD.io VPP  v20.05-21-gb1500e9ff
Vector Packet Processing
mpls_disposition.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/ip/ip4_input.h>
17 #include <vnet/ip/ip6_input.h>
19 #include <vnet/mpls/mpls.h>
20 
21 #ifndef CLIB_MARCH_VARIANT
22 /*
23  * pool of all MPLS Label DPOs
24  */
26 
27 static mpls_disp_dpo_t *
29 {
30  mpls_disp_dpo_t *mdd;
31 
32  pool_get_aligned(mpls_disp_dpo_pool, mdd, CLIB_CACHE_LINE_BYTES);
33  clib_memset(mdd, 0, sizeof(*mdd));
34 
35  dpo_reset(&mdd->mdd_dpo);
36 
37  return (mdd);
38 }
39 
40 static index_t
42 {
43  return (mdd - mpls_disp_dpo_pool);
44 }
45 
46 void
50  const dpo_id_t *parent,
51  dpo_id_t *dpo)
52 {
53  mpls_disp_dpo_t *mdd;
54  dpo_type_t dtype;
55 
56  mdd = mpls_disp_dpo_alloc();
57 
58  mdd->mdd_payload_proto = payload_proto;
59  mdd->mdd_rpf_id = rpf_id;
60  mdd->mdd_mode = mode;
61  dtype = (FIB_MPLS_LSP_MODE_PIPE == mode ?
64 
65  /*
66  * stack this disposition object on the parent given
67  */
68  dpo_stack(dtype,
69  mdd->mdd_payload_proto,
70  &mdd->mdd_dpo,
71  parent);
72 
73  /*
74  * set up the return DPO to refer to this object
75  */
76  dpo_set(dpo,
77  dtype,
78  payload_proto,
80 }
81 
82 u8*
83 format_mpls_disp_dpo (u8 *s, va_list *args)
84 {
85  index_t index = va_arg(*args, index_t);
86  u32 indent = va_arg(*args, u32);
87  mpls_disp_dpo_t *mdd;
88 
89  mdd = mpls_disp_dpo_get(index);
90 
91  s = format(s, "mpls-disposition:[%d]:[", index);
92 
93  if (0 != mdd->mdd_rpf_id)
94  s = format(s, "rpf-id:%d ", mdd->mdd_rpf_id);
95 
96  s = format(s, "%U, %U]",
99 
100  s = format(s, "\n%U", format_white_space, indent);
101  s = format(s, "%U", format_dpo_id, &mdd->mdd_dpo, indent+2);
102 
103  return (s);
104 }
105 
106 static void
108 {
109  mpls_disp_dpo_t *mdd;
110 
111  mdd = mpls_disp_dpo_get(dpo->dpoi_index);
112 
113  mdd->mdd_locks++;
114 }
115 
116 static void
118 {
119  mpls_disp_dpo_t *mdd;
120 
121  mdd = mpls_disp_dpo_get(dpo->dpoi_index);
122 
123  mdd->mdd_locks--;
124 
125  if (0 == mdd->mdd_locks)
126  {
127  dpo_reset(&mdd->mdd_dpo);
128  pool_put(mpls_disp_dpo_pool, mdd);
129  }
130 }
131 #endif /* CLIB_MARCH_VARIANT */
132 
133 /**
134  * @brief A struct to hold tracing information for the MPLS label disposition
135  * node.
136  */
138 {
143 
148 
152  vlib_frame_t * from_frame,
153  u8 payload_is_ip4,
154  u8 payload_is_ip6,
156 {
157  u32 n_left_from, next_index, * from, * to_next;
158  vlib_node_runtime_t *error_node;
159 
160  if (payload_is_ip4)
161  {
162  if (FIB_MPLS_LSP_MODE_PIPE == mode)
163  error_node =
165  else
166  error_node =
168  }
169  else
170  {
171  if (FIB_MPLS_LSP_MODE_PIPE == mode)
172  error_node =
174  else
175  error_node =
177  }
178  from = vlib_frame_vector_args(from_frame);
179  n_left_from = from_frame->n_vectors;
180 
181  next_index = node->cached_next_index;
182 
183  while (n_left_from > 0)
184  {
185  u32 n_left_to_next;
186 
187  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
188 
189  while (n_left_from >= 4 && n_left_to_next >= 2)
190  {
191  mpls_disp_dpo_t *mdd0, *mdd1;
192  u32 bi0, mddi0, bi1, mddi1;
193  vlib_buffer_t * b0, *b1;
194  u32 next0, next1;
195 
196  bi0 = to_next[0] = from[0];
197  bi1 = to_next[1] = from[1];
198 
199  /* Prefetch next iteration. */
200  {
201  vlib_buffer_t * p2, * p3;
202 
203  p2 = vlib_get_buffer(vm, from[2]);
204  p3 = vlib_get_buffer(vm, from[3]);
205 
206  vlib_prefetch_buffer_header(p2, STORE);
207  vlib_prefetch_buffer_header(p3, STORE);
208 
209  CLIB_PREFETCH(p2->data, sizeof(ip6_header_t), STORE);
210  CLIB_PREFETCH(p3->data, sizeof(ip6_header_t), STORE);
211  }
212 
213  from += 2;
214  to_next += 2;
215  n_left_from -= 2;
216  n_left_to_next -= 2;
217 
218  b0 = vlib_get_buffer(vm, bi0);
219  b1 = vlib_get_buffer(vm, bi1);
220 
221  /* dst lookup was done by ip4 lookup */
222  mddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
223  mddi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
224  mdd0 = mpls_disp_dpo_get(mddi0);
225  mdd1 = mpls_disp_dpo_get(mddi1);
226 
227  next0 = mdd0->mdd_dpo.dpoi_next_node;
228  next1 = mdd1->mdd_dpo.dpoi_next_node;
229 
230  if (payload_is_ip4)
231  {
232  ip4_header_t *ip0, *ip1;
233 
234  ip0 = vlib_buffer_get_current(b0);
235  ip1 = vlib_buffer_get_current(b1);
236 
237  /*
238  * IPv4 input checks on the exposed IP header
239  * including checksum
240  */
241  ip4_input_check_x2(vm, error_node,
242  b0, b1, ip0, ip1,
243  &next0, &next1, 1);
244 
245  if (FIB_MPLS_LSP_MODE_UNIFORM == mode)
246  {
247  /*
248  * Copy the TTL from the MPLS packet into the
249  * exposed IP. recalc the chksum
250  */
251  ip0->ttl = vnet_buffer(b0)->mpls.ttl;
252  ip1->ttl = vnet_buffer(b1)->mpls.ttl;
253  ip0->tos = mpls_exp_to_ip_dscp(vnet_buffer(b0)->mpls.exp);
254  ip1->tos = mpls_exp_to_ip_dscp(vnet_buffer(b1)->mpls.exp);
255 
256  ip0->checksum = ip4_header_checksum(ip0);
257  ip1->checksum = ip4_header_checksum(ip1);
258  }
259  }
260  else if (payload_is_ip6)
261  {
262  ip6_header_t *ip0, *ip1;
263 
264  ip0 = vlib_buffer_get_current(b0);
265  ip1 = vlib_buffer_get_current(b1);
266 
267  /*
268  * IPv6 input checks on the exposed IP header
269  */
270  ip6_input_check_x2(vm, error_node,
271  b0, b1, ip0, ip1,
272  &next0, &next1);
273 
274  if (FIB_MPLS_LSP_MODE_UNIFORM == mode)
275  {
276  /*
277  * Copy the TTL from the MPLS packet into the
278  * exposed IP
279  */
280  ip0->hop_limit = vnet_buffer(b0)->mpls.ttl;
281  ip1->hop_limit = vnet_buffer(b1)->mpls.ttl;
282 
284  ip0,
285  mpls_exp_to_ip_dscp(vnet_buffer(b0)->mpls.exp));
287  ip1,
288  mpls_exp_to_ip_dscp(vnet_buffer(b1)->mpls.exp));
289  }
290  }
291 
292  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mdd0->mdd_dpo.dpoi_index;
293  vnet_buffer(b1)->ip.adj_index[VLIB_TX] = mdd1->mdd_dpo.dpoi_index;
294  vnet_buffer(b0)->ip.rpf_id = mdd0->mdd_rpf_id;
295  vnet_buffer(b1)->ip.rpf_id = mdd1->mdd_rpf_id;
296 
297  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
298  {
300  vlib_add_trace(vm, node, b0, sizeof(*tr));
301 
303  tr->mddt_rpf_id = mdd0->mdd_rpf_id;
304  tr->mddt_mode = mdd0->mdd_mode;
305  }
306  if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
307  {
309  vlib_add_trace(vm, node, b1, sizeof(*tr));
311  tr->mddt_rpf_id = mdd1->mdd_rpf_id;
312  tr->mddt_mode = mdd1->mdd_mode;
313  }
314 
315  vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
316  n_left_to_next,
317  bi0, bi1, next0, next1);
318  }
319 
320  while (n_left_from > 0 && n_left_to_next > 0)
321  {
322  mpls_disp_dpo_t *mdd0;
323  vlib_buffer_t * b0;
324  u32 bi0, mddi0;
325  u32 next0;
326 
327  bi0 = from[0];
328  to_next[0] = bi0;
329  from += 1;
330  to_next += 1;
331  n_left_from -= 1;
332  n_left_to_next -= 1;
333 
334  b0 = vlib_get_buffer(vm, bi0);
335 
336  /* dst lookup was done by ip4 lookup */
337  mddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
338  mdd0 = mpls_disp_dpo_get(mddi0);
339  next0 = mdd0->mdd_dpo.dpoi_next_node;
340 
341  if (payload_is_ip4)
342  {
343  ip4_header_t *ip0;
344 
345  ip0 = vlib_buffer_get_current(b0);
346 
347  /*
348  * IPv4 input checks on the exposed IP header
349  * including checksum
350  */
351  ip4_input_check_x1(vm, error_node, b0, ip0, &next0, 1);
352 
353  if (FIB_MPLS_LSP_MODE_UNIFORM == mode)
354  {
355  /*
356  * Copy the TTL from the MPLS packet into the
357  * exposed IP. recalc the chksum
358  */
359  ip0->ttl = vnet_buffer(b0)->mpls.ttl;
360  ip0->tos = mpls_exp_to_ip_dscp(vnet_buffer(b0)->mpls.exp);
361  ip0->checksum = ip4_header_checksum(ip0);
362  }
363  }
364  else if (payload_is_ip6)
365  {
366  ip6_header_t *ip0;
367 
368  ip0 = vlib_buffer_get_current(b0);
369 
370  /*
371  * IPv6 input checks on the exposed IP header
372  */
373  ip6_input_check_x1(vm, error_node, b0, ip0, &next0);
374 
375  if (FIB_MPLS_LSP_MODE_UNIFORM == mode)
376  {
377  /*
378  * Copy the TTL from the MPLS packet into the
379  * exposed IP
380  */
381  ip0->hop_limit = vnet_buffer(b0)->mpls.ttl;
382 
384  ip0,
385  mpls_exp_to_ip_dscp(vnet_buffer(b0)->mpls.exp));
386  }
387  }
388 
389  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mdd0->mdd_dpo.dpoi_index;
390  vnet_buffer(b0)->ip.rpf_id = mdd0->mdd_rpf_id;
391 
392  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
393  {
395  vlib_add_trace(vm, node, b0, sizeof(*tr));
397  tr->mddt_rpf_id = mdd0->mdd_rpf_id;
398  tr->mddt_mode = mdd0->mdd_mode;
399  }
400 
401  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
402  n_left_to_next, bi0, next0);
403  }
404  vlib_put_next_frame(vm, node, next_index, n_left_to_next);
405  }
406  return from_frame->n_vectors;
407 }
408 
409 static u8 *
411 {
412  CLIB_UNUSED(vlib_main_t * vm) = va_arg(*args, vlib_main_t *);
413  CLIB_UNUSED(vlib_node_t * node) = va_arg(*args, vlib_node_t *);
415 
416  t = va_arg(*args, mpls_label_disposition_trace_t *);
417 
418  s = format(s, "rpf-id:%d %U, %U",
419  t->mddt_rpf_id,
422 
423  return (s);
424 }
425 
429 {
430  return (mpls_label_disposition_inline(vm, node, frame, 1, 0,
432 }
433 
435  .name = "ip4-mpls-label-disposition-pipe",
436  .vector_size = sizeof(u32),
437 
438  .format_trace = format_mpls_label_disposition_trace,
439  .sibling_of = "ip4-input",
440  .n_errors = IP4_N_ERROR,
441  .error_strings = ip4_error_strings,
442 };
443 
447 {
448  return (mpls_label_disposition_inline(vm, node, frame, 0, 1,
450 }
451 
453  .name = "ip6-mpls-label-disposition-pipe",
454  .vector_size = sizeof(u32),
455 
456  .format_trace = format_mpls_label_disposition_trace,
457  .sibling_of = "ip6-input",
458  .n_errors = IP6_N_ERROR,
459  .error_strings = ip6_error_strings,
460 };
461 
465 {
466  return (mpls_label_disposition_inline(vm, node, frame, 1, 0,
468 }
469 
471  .name = "ip4-mpls-label-disposition-uniform",
472  .vector_size = sizeof(u32),
473 
474  .format_trace = format_mpls_label_disposition_trace,
475  .sibling_of = "ip4-input",
476  .n_errors = IP4_N_ERROR,
477  .error_strings = ip4_error_strings,
478 };
479 
483 {
484  return (mpls_label_disposition_inline(vm, node, frame, 0, 1,
486 }
487 
489  .name = "ip6-mpls-label-disposition-uniform",
490  .vector_size = sizeof(u32),
491 
492  .format_trace = format_mpls_label_disposition_trace,
493  .sibling_of = "ip6-input",
494  .n_errors = IP6_N_ERROR,
495  .error_strings = ip6_error_strings,
496 };
497 
498 #ifndef CLIB_MARCH_VARIANT
499 static void
501 {
502  fib_show_memory_usage("MPLS label",
503  pool_elts(mpls_disp_dpo_pool),
504  pool_len(mpls_disp_dpo_pool),
505  sizeof(mpls_disp_dpo_t));
506 }
507 
508 const static dpo_vft_t mdd_vft = {
510  .dv_unlock = mpls_disp_dpo_unlock,
511  .dv_format = format_mpls_disp_dpo,
512  .dv_mem_show = mpls_disp_dpo_mem_show,
513 };
514 
515 const static char* const mpls_label_disp_pipe_ip4_nodes[] =
516 {
517  "ip4-mpls-label-disposition-pipe",
518  NULL,
519 };
520 const static char* const mpls_label_disp_pipe_ip6_nodes[] =
521 {
522  "ip6-mpls-label-disposition-pipe",
523  NULL,
524 };
525 const static char* const * const mpls_label_disp_pipe_nodes[DPO_PROTO_NUM] =
526 {
529 };
530 
531 const static char* const mpls_label_disp_uniform_ip4_nodes[] =
532 {
533  "ip4-mpls-label-disposition-uniform",
534  NULL,
535 };
536 const static char* const mpls_label_disp_uniform_ip6_nodes[] =
537 {
538  "ip6-mpls-label-disposition-uniform",
539  NULL,
540 };
541 const static char* const * const mpls_label_disp_uniform_nodes[DPO_PROTO_NUM] =
542 {
545 };
546 
547 
548 void
550 {
555 }
556 #endif /* CLIB_MARCH_VARIANT */
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
u16 mdd_locks
Number of locks/users of the label.
A struct to hold tracing information for the MPLS label disposition node.
void mpls_disp_dpo_create(dpo_proto_t payload_proto, fib_rpf_id_t rpf_id, fib_mpls_lsp_mode_t mode, const dpo_id_t *parent, dpo_id_t *dpo)
Create an MPLS label object.
Pipe Mode - the default.
Definition: fib_types.h:424
#define CLIB_UNUSED(x)
Definition: clib.h:86
A virtual function table regisitered for a DPO type.
Definition: dpo.h:401
static_always_inline void ip6_set_traffic_class_network_order(ip6_header_t *ip6, ip_dscp_t dscp)
Definition: ip6_packet.h:341
static void mpls_disp_dpo_lock(dpo_id_t *dpo)
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
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
char * ip4_error_strings[]
Definition: ip4_input.c:377
static const char *const *const mpls_label_disp_pipe_nodes[DPO_PROTO_NUM]
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
static const char *const mpls_label_disp_pipe_ip6_nodes[]
#define VLIB_NODE_FN(node)
Definition: node.h:202
unsigned char u8
Definition: types.h:56
#define pool_len(p)
Number of elements in pool vector.
Definition: pool.h:140
static index_t mpls_disp_dpo_get_index(mpls_disp_dpo_t *mdd)
static mpls_disp_dpo_t * mpls_disp_dpo_alloc(void)
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
enum dpo_type_t_ dpo_type_t
Common types of data-path objects New types can be dynamically added using dpo_register_new_type() ...
u8 * format_fib_mpls_lsp_mode(u8 *s, va_list *ap)
Format an LSP mode type.
Definition: fib_types.c:57
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:203
dpo_proto_t mdd_payload_proto
The protocol of the payload/packets that are being encapped.
static void ip4_input_check_x1(vlib_main_t *vm, vlib_node_runtime_t *error_node, vlib_buffer_t *p0, ip4_header_t *ip0, u32 *next0, int verify_checksum)
Definition: ip4_input.h:278
vlib_node_registration_t ip6_mpls_label_disposition_uniform_node
(constructor) VLIB_REGISTER_NODE (ip6_mpls_label_disposition_uniform_node)
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
fib_rpf_id_t mdd_rpf_id
RPF-ID (if this is an mcast disposition)
unsigned int u32
Definition: types.h:88
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
static void mpls_disp_dpo_unlock(dpo_id_t *dpo)
vlib_node_registration_t ip4_mpls_label_disposition_pipe_node
(constructor) VLIB_REGISTER_NODE (ip4_mpls_label_disposition_pipe_node)
u32 rpf_id
Definition: fib_types.api:119
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
static void mpls_disp_dpo_mem_show(void)
static uword mpls_label_disposition_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame, u8 payload_is_ip4, u8 payload_is_ip6, fib_mpls_lsp_mode_t mode)
enum fib_mpls_lsp_mode_t_ fib_mpls_lsp_mode_t
MPLS LSP mode - only valid at the head and tail.
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:302
static const char *const mpls_label_disp_pipe_ip4_nodes[]
#define PREDICT_FALSE(x)
Definition: clib.h:118
#define always_inline
Definition: ipsec.h:28
static u8 mpls_exp_to_ip_dscp(u8 exp)
When in uniform mode convert an MPLS EXP value to an IPv[46] DSCP value.
Definition: packet.h:68
#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:338
vlib_main_t * vm
Definition: in2out_ed.c:1599
vl_api_tunnel_mode_t mode
Definition: gre.api:48
static void ip6_input_check_x2(vlib_main_t *vm, vlib_node_runtime_t *error_node, vlib_buffer_t *p0, vlib_buffer_t *p1, ip6_header_t *ip0, ip6_header_t *ip1, u32 *next0, u32 *next1)
Definition: ip6_input.h:58
mpls_disp_dpo_t * mpls_disp_dpo_pool
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P with alignment A.
Definition: pool.h:246
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:399
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
static void ip6_input_check_x1(vlib_main_t *vm, vlib_node_runtime_t *error_node, vlib_buffer_t *p0, ip6_header_t *ip0, u32 *next0)
Definition: ip6_input.h:122
static vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Get node runtime by node index.
Definition: node_funcs.h:89
u8 data[]
Packet data.
Definition: buffer.h:181
struct mpls_label_disposition_trace_t_ mpls_label_disposition_trace_t
A struct to hold tracing information for the MPLS label disposition node.
u8 * format_mpls_disp_dpo(u8 *s, va_list *args)
char * ip6_error_strings[]
Definition: ip6_input.c:222
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
void mpls_disp_dpo_module_init(void)
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1599
u32 fib_rpf_id_t
An RPF-ID is numerical value that is used RPF validate.
Definition: fib_types.h:411
A representation of an MPLS label for imposition in the data-path.
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:517
ip_dscp_t tos
Definition: ip4_packet.h:141
static const char *const mpls_label_disp_uniform_ip4_nodes[]
u8 * format_dpo_id(u8 *s, va_list *args)
Format a DPO_id_t oject.
Definition: dpo.c:148
static const char *const *const mpls_label_disp_uniform_nodes[DPO_PROTO_NUM]
dpo_id_t mdd_dpo
Next DPO in the graph.
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
struct _vlib_node_registration vlib_node_registration_t
Definition: defs.h:47
static mpls_disp_dpo_t * mpls_disp_dpo_get(index_t index)
#define DPO_PROTO_NUM
Definition: dpo.h:70
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:186
static void ip4_input_check_x2(vlib_main_t *vm, vlib_node_runtime_t *error_node, vlib_buffer_t *p0, vlib_buffer_t *p1, ip4_header_t *ip0, ip4_header_t *ip1, u32 *next0, u32 *next1, int verify_checksum)
Definition: ip4_input.h:203
fib_mpls_lsp_mode_t mdd_mode
LSP mode.
VLIB buffer representation.
Definition: buffer.h:102
static const char *const mpls_label_disp_uniform_ip6_nodes[]
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
vlib_node_registration_t ip6_mpls_label_disposition_pipe_node
(constructor) VLIB_REGISTER_NODE (ip6_mpls_label_disposition_pipe_node)
u8 * format_dpo_proto(u8 *s, va_list *args)
format a DPO protocol
Definition: dpo.c:178
#define vnet_buffer(b)
Definition: buffer.h:417
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:232
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1600
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:182
vlib_node_registration_t ip4_mpls_label_disposition_uniform_node
(constructor) VLIB_REGISTER_NODE (ip4_mpls_label_disposition_uniform_node)
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
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
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:247
static u8 * format_mpls_label_disposition_trace(u8 *s, va_list *args)
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:516
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128