FD.io VPP  v17.07.01-10-g3be13f0
Vector Packet Processing
mpls_label_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/ip/ip.h>
18 #include <vnet/mpls/mpls.h>
19 
20 /*
21  * pool of all MPLS Label DPOs
22  */
24 
25 static mpls_label_dpo_t *
27 {
28  mpls_label_dpo_t *mld;
29 
30  pool_get_aligned(mpls_label_dpo_pool, mld, CLIB_CACHE_LINE_BYTES);
31  memset(mld, 0, sizeof(*mld));
32 
33  dpo_reset(&mld->mld_dpo);
34 
35  return (mld);
36 }
37 
38 static index_t
40 {
41  return (mld - mpls_label_dpo_pool);
42 }
43 
44 index_t
46  mpls_eos_bit_t eos,
47  u8 ttl,
48  u8 exp,
49  dpo_proto_t payload_proto,
50  const dpo_id_t *dpo)
51 {
52  mpls_label_dpo_t *mld;
53  u32 ii;
54 
55  mld = mpls_label_dpo_alloc();
56  mld->mld_n_labels = vec_len(label_stack);
57  mld->mld_n_hdr_bytes = mld->mld_n_labels * sizeof(mld->mld_hdr[0]);
58  mld->mld_payload_proto = payload_proto;
59 
60  /*
61  * construct label rewrite headers for each value value passed.
62  * get the header in network byte order since we will paint it
63  * on a packet in the data-plane
64  */
65 
66  for (ii = 0; ii < mld->mld_n_labels-1; ii++)
67  {
68  vnet_mpls_uc_set_label(&mld->mld_hdr[ii].label_exp_s_ttl, label_stack[ii]);
72  mld->mld_hdr[ii].label_exp_s_ttl =
73  clib_host_to_net_u32(mld->mld_hdr[ii].label_exp_s_ttl);
74  }
75 
76  /*
77  * the inner most label
78  */
79  ii = mld->mld_n_labels-1;
80 
81  vnet_mpls_uc_set_label(&mld->mld_hdr[ii].label_exp_s_ttl, label_stack[ii]);
85  mld->mld_hdr[ii].label_exp_s_ttl =
86  clib_host_to_net_u32(mld->mld_hdr[ii].label_exp_s_ttl);
87 
88  /*
89  * stack this label objct on its parent.
90  */
92  mld->mld_payload_proto,
93  &mld->mld_dpo,
94  dpo);
95 
96  return (mpls_label_dpo_get_index(mld));
97 }
98 
99 u8*
100 format_mpls_label_dpo (u8 *s, va_list *args)
101 {
102  index_t index = va_arg (*args, index_t);
103  u32 indent = va_arg (*args, u32);
105  mpls_label_dpo_t *mld;
106  u32 ii;
107 
108  mld = mpls_label_dpo_get(index);
109 
110  s = format(s, "mpls-label:[%d]:", index);
111 
112  for (ii = 0; ii < mld->mld_n_labels; ii++)
113  {
114  hdr.label_exp_s_ttl =
115  clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
116  s = format(s, "%U", format_mpls_header, hdr);
117  }
118 
119  s = format(s, "\n%U", format_white_space, indent);
120  s = format(s, "%U", format_dpo_id, &mld->mld_dpo, indent+2);
121 
122  return (s);
123 }
124 
125 static void
127 {
128  mpls_label_dpo_t *mld;
129 
130  mld = mpls_label_dpo_get(dpo->dpoi_index);
131 
132  mld->mld_locks++;
133 }
134 
135 static void
137 {
138  mpls_label_dpo_t *mld;
139 
140  mld = mpls_label_dpo_get(dpo->dpoi_index);
141 
142  mld->mld_locks--;
143 
144  if (0 == mld->mld_locks)
145  {
146  dpo_reset(&mld->mld_dpo);
147  pool_put(mpls_label_dpo_pool, mld);
148  }
149 }
150 
151 /**
152  * @brief A struct to hold tracing information for the MPLS label imposition
153  * node.
154  */
156 {
157  /**
158  * The MPLS header imposed
159  */
162 
165  mpls_label_dpo_t *mld0,
166  u8 ttl0)
167 {
168  mpls_unicast_header_t *hdr0;
169 
170  vlib_buffer_advance(b0, -(mld0->mld_n_hdr_bytes));
171 
172  hdr0 = vlib_buffer_get_current(b0);
173 
174  if (1 == mld0->mld_n_labels)
175  {
176  /* optimise for the common case of one label */
177  *hdr0 = mld0->mld_hdr[0];
178  }
179  else
180  {
181  clib_memcpy(hdr0, mld0->mld_hdr, mld0->mld_n_hdr_bytes);
182  hdr0 = hdr0 + (mld0->mld_n_labels - 1);
183  }
184  /* fixup the TTL for the inner most label */
185  ((char*)hdr0)[3] = ttl0;
186 
187  return (hdr0);
188 }
189 
192  vlib_node_runtime_t * node,
193  vlib_frame_t * from_frame,
194  u8 payload_is_ip4,
195  u8 payload_is_ip6)
196 {
197  u32 n_left_from, next_index, * from, * to_next;
198 
199  from = vlib_frame_vector_args (from_frame);
200  n_left_from = from_frame->n_vectors;
201 
202  next_index = node->cached_next_index;
203 
204  while (n_left_from > 0)
205  {
206  u32 n_left_to_next;
207 
208  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
209 
210  while (n_left_from >= 8 && n_left_to_next >= 4)
211  {
212  u32 bi0, mldi0, bi1, mldi1, bi2, mldi2, bi3, mldi3;
213  mpls_unicast_header_t *hdr0, *hdr1, *hdr2, *hdr3;
214  mpls_label_dpo_t *mld0, *mld1, *mld2, *mld3;
215  vlib_buffer_t * b0, *b1, * b2, *b3;
216  u32 next0, next1, next2, next3;
217  u8 ttl0, ttl1,ttl2, ttl3 ;
218 
219  bi0 = to_next[0] = from[0];
220  bi1 = to_next[1] = from[1];
221  bi2 = to_next[2] = from[2];
222  bi3 = to_next[3] = from[3];
223 
224  /* Prefetch next iteration. */
225  {
226  vlib_buffer_t * p2, * p3, *p4, *p5;
227 
228  p2 = vlib_get_buffer (vm, from[2]);
229  p3 = vlib_get_buffer (vm, from[3]);
230  p4 = vlib_get_buffer (vm, from[4]);
231  p5 = vlib_get_buffer (vm, from[5]);
232 
233  vlib_prefetch_buffer_header (p2, STORE);
234  vlib_prefetch_buffer_header (p3, STORE);
235  vlib_prefetch_buffer_header (p4, STORE);
236  vlib_prefetch_buffer_header (p5, STORE);
237 
238  CLIB_PREFETCH (p2->data, sizeof (hdr0[0]), STORE);
239  CLIB_PREFETCH (p3->data, sizeof (hdr0[0]), STORE);
240  CLIB_PREFETCH (p4->data, sizeof (hdr0[0]), STORE);
241  CLIB_PREFETCH (p5->data, sizeof (hdr0[0]), STORE);
242  }
243 
244  from += 4;
245  to_next += 4;
246  n_left_from -= 4;
247  n_left_to_next -= 4;
248 
249  b0 = vlib_get_buffer (vm, bi0);
250  b1 = vlib_get_buffer (vm, bi1);
251  b2 = vlib_get_buffer (vm, bi2);
252  b3 = vlib_get_buffer (vm, bi3);
253 
254  /* dst lookup was done by ip4 lookup */
255  mldi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
256  mldi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
257  mldi2 = vnet_buffer(b2)->ip.adj_index[VLIB_TX];
258  mldi3 = vnet_buffer(b3)->ip.adj_index[VLIB_TX];
259  mld0 = mpls_label_dpo_get(mldi0);
260  mld1 = mpls_label_dpo_get(mldi1);
261  mld2 = mpls_label_dpo_get(mldi2);
262  mld3 = mpls_label_dpo_get(mldi3);
263 
264  if (payload_is_ip4)
265  {
266  /*
267  * decrement the TTL on ingress to the LSP
268  */
273  u32 checksum0;
274  u32 checksum1;
275  u32 checksum2;
276  u32 checksum3;
277 
278  checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
279  checksum1 = ip1->checksum + clib_host_to_net_u16 (0x0100);
280  checksum2 = ip2->checksum + clib_host_to_net_u16 (0x0100);
281  checksum3 = ip3->checksum + clib_host_to_net_u16 (0x0100);
282 
283  checksum0 += checksum0 >= 0xffff;
284  checksum1 += checksum1 >= 0xffff;
285  checksum2 += checksum2 >= 0xffff;
286  checksum3 += checksum3 >= 0xffff;
287 
288  ip0->checksum = checksum0;
289  ip1->checksum = checksum1;
290  ip2->checksum = checksum2;
291  ip3->checksum = checksum3;
292 
293  ip0->ttl -= 1;
294  ip1->ttl -= 1;
295  ip2->ttl -= 1;
296  ip3->ttl -= 1;
297 
298  ttl1 = ip1->ttl;
299  ttl0 = ip0->ttl;
300  ttl3 = ip3->ttl;
301  ttl2 = ip2->ttl;
302  }
303  else if (payload_is_ip6)
304  {
305  /*
306  * decrement the TTL on ingress to the LSP
307  */
312 
313  ip0->hop_limit -= 1;
314  ip1->hop_limit -= 1;
315  ip2->hop_limit -= 1;
316  ip3->hop_limit -= 1;
317 
318  ttl0 = ip0->hop_limit;
319  ttl1 = ip1->hop_limit;
320  ttl2 = ip2->hop_limit;
321  ttl3 = ip3->hop_limit;
322  }
323  else
324  {
325  /*
326  * else, the packet to be encapped is an MPLS packet
327  */
328  if (PREDICT_TRUE(vnet_buffer(b0)->mpls.first))
329  {
330  /*
331  * The first label to be imposed on the packet. this is a label swap.
332  * in which case we stashed the TTL and EXP bits in the
333  * packet in the lookup node
334  */
335  ASSERT(0 != vnet_buffer (b0)->mpls.ttl);
336 
337  ttl0 = vnet_buffer(b0)->mpls.ttl - 1;
338  }
339  else
340  {
341  /*
342  * not the first label. implying we are recusring down a chain of
343  * output labels.
344  * Each layer is considered a new LSP - hence the TTL is reset.
345  */
346  ttl0 = 255;
347  }
348  if (PREDICT_TRUE(vnet_buffer(b1)->mpls.first))
349  {
350  ASSERT(1 != vnet_buffer (b1)->mpls.ttl);
351  ttl1 = vnet_buffer(b1)->mpls.ttl - 1;
352  }
353  else
354  {
355  ttl1 = 255;
356  }
357  if (PREDICT_TRUE(vnet_buffer(b2)->mpls.first))
358  {
359  ASSERT(1 != vnet_buffer (b2)->mpls.ttl);
360 
361  ttl2 = vnet_buffer(b2)->mpls.ttl - 1;
362  }
363  else
364  {
365  ttl2 = 255;
366  }
367  if (PREDICT_TRUE(vnet_buffer(b3)->mpls.first))
368  {
369  ASSERT(1 != vnet_buffer (b3)->mpls.ttl);
370  ttl3 = vnet_buffer(b3)->mpls.ttl - 1;
371  }
372  else
373  {
374  ttl3 = 255;
375  }
376  }
377  vnet_buffer(b0)->mpls.first = 0;
378  vnet_buffer(b1)->mpls.first = 0;
379  vnet_buffer(b2)->mpls.first = 0;
380  vnet_buffer(b3)->mpls.first = 0;
381 
382  /* Paint the MPLS header */
383  hdr0 = mpls_label_paint(b0, mld0, ttl0);
384  hdr1 = mpls_label_paint(b1, mld1, ttl1);
385  hdr2 = mpls_label_paint(b2, mld2, ttl2);
386  hdr3 = mpls_label_paint(b3, mld3, ttl3);
387 
388  next0 = mld0->mld_dpo.dpoi_next_node;
389  next1 = mld1->mld_dpo.dpoi_next_node;
390  next2 = mld2->mld_dpo.dpoi_next_node;
391  next3 = mld3->mld_dpo.dpoi_next_node;
392  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mld0->mld_dpo.dpoi_index;
393  vnet_buffer(b1)->ip.adj_index[VLIB_TX] = mld1->mld_dpo.dpoi_index;
394  vnet_buffer(b2)->ip.adj_index[VLIB_TX] = mld2->mld_dpo.dpoi_index;
395  vnet_buffer(b3)->ip.adj_index[VLIB_TX] = mld3->mld_dpo.dpoi_index;
396 
398  {
400  vlib_add_trace (vm, node, b0, sizeof (*tr));
401  tr->hdr = *hdr0;
402  }
404  {
406  vlib_add_trace (vm, node, b1, sizeof (*tr));
407  tr->hdr = *hdr1;
408  }
410  {
412  vlib_add_trace (vm, node, b2, sizeof (*tr));
413  tr->hdr = *hdr2;
414  }
416  {
418  vlib_add_trace (vm, node, b3, sizeof (*tr));
419  tr->hdr = *hdr3;
420  }
421 
422  vlib_validate_buffer_enqueue_x4(vm, node, next_index, to_next,
423  n_left_to_next,
424  bi0, bi1, bi2, bi3,
425  next0, next1, next2, next3);
426  }
427 
428  while (n_left_from > 0 && n_left_to_next > 0)
429  {
430  mpls_unicast_header_t *hdr0;
431  mpls_label_dpo_t *mld0;
432  vlib_buffer_t * b0;
433  u32 bi0, mldi0;
434  u32 next0;
435  u8 ttl;
436 
437  bi0 = from[0];
438  to_next[0] = bi0;
439  from += 1;
440  to_next += 1;
441  n_left_from -= 1;
442  n_left_to_next -= 1;
443 
444  b0 = vlib_get_buffer (vm, bi0);
445 
446  /* dst lookup was done by ip4 lookup */
447  mldi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
448  mld0 = mpls_label_dpo_get(mldi0);
449 
450  if (payload_is_ip4)
451  {
452  /*
453  * decrement the TTL on ingress to the LSP
454  */
456  u32 checksum0;
457 
458  checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
459  checksum0 += checksum0 >= 0xffff;
460 
461  ip0->checksum = checksum0;
462  ip0->ttl -= 1;
463  ttl = ip0->ttl;
464  }
465  else if (payload_is_ip6)
466  {
467  /*
468  * decrement the TTL on ingress to the LSP
469  */
471 
472  ip0->hop_limit -= 1;
473  ttl = ip0->hop_limit;
474  }
475  else
476  {
477  /*
478  * else, the packet to be encapped is an MPLS packet
479  */
480  if (vnet_buffer(b0)->mpls.first)
481  {
482  /*
483  * The first label to be imposed on the packet. this is a label swap.
484  * in which case we stashed the TTL and EXP bits in the
485  * packet in the lookup node
486  */
487  ASSERT(0 != vnet_buffer (b0)->mpls.ttl);
488 
489  ttl = vnet_buffer(b0)->mpls.ttl - 1;
490  }
491  else
492  {
493  /*
494  * not the first label. implying we are recusring down a chain of
495  * output labels.
496  * Each layer is considered a new LSP - hence the TTL is reset.
497  */
498  ttl = 255;
499  }
500  }
501  vnet_buffer(b0)->mpls.first = 0;
502 
503  /* Paint the MPLS header */
504  vlib_buffer_advance(b0, -(mld0->mld_n_hdr_bytes));
505  hdr0 = vlib_buffer_get_current(b0);
506  clib_memcpy(hdr0, mld0->mld_hdr, mld0->mld_n_hdr_bytes);
507 
508  /* fixup the TTL for the inner most label */
509  hdr0 = hdr0 + (mld0->mld_n_labels - 1);
510  ((char*)hdr0)[3] = ttl;
511 
512  next0 = mld0->mld_dpo.dpoi_next_node;
513  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mld0->mld_dpo.dpoi_index;
514 
516  {
518  vlib_add_trace (vm, node, b0, sizeof (*tr));
519  tr->hdr = *hdr0;
520  }
521 
522  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
523  n_left_to_next, bi0, next0);
524  }
525  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
526  }
527  return from_frame->n_vectors;
528 }
529 
530 static u8 *
532 {
533  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
534  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
537  uword indent;
538 
539  t = va_arg (*args, mpls_label_imposition_trace_t *);
540  indent = format_get_indent (s);
541  hdr.label_exp_s_ttl = clib_net_to_host_u32(t->hdr.label_exp_s_ttl);
542 
543  s = format (s, "%Umpls-header:%U",
544  format_white_space, indent,
545  format_mpls_header, hdr);
546  return (s);
547 }
548 
549 static uword
551  vlib_node_runtime_t * node,
552  vlib_frame_t * frame)
553 {
554  return (mpls_label_imposition_inline(vm, node, frame, 0, 0));
555 }
556 
558  .function = mpls_label_imposition,
559  .name = "mpls-label-imposition",
560  .vector_size = sizeof (u32),
561 
562  .format_trace = format_mpls_label_imposition_trace,
563  .n_next_nodes = 1,
564  .next_nodes = {
565  [0] = "mpls-drop",
566  }
567 };
570 
571 static uword
572 ip4_mpls_label_imposition (vlib_main_t * vm,
573  vlib_node_runtime_t * node,
574  vlib_frame_t * frame)
575 {
576  return (mpls_label_imposition_inline(vm, node, frame, 1, 0));
577 }
578 
580  .function = ip4_mpls_label_imposition,
581  .name = "ip4-mpls-label-imposition",
582  .vector_size = sizeof (u32),
583 
584  .format_trace = format_mpls_label_imposition_trace,
585  .n_next_nodes = 1,
586  .next_nodes = {
587  [0] = "ip4-drop",
588  }
589 };
591  ip4_mpls_label_imposition)
592 
593 static uword
594 ip6_mpls_label_imposition (vlib_main_t * vm,
595  vlib_node_runtime_t * node,
596  vlib_frame_t * frame)
597 {
598  return (mpls_label_imposition_inline(vm, node, frame, 0, 1));
599 }
600 
602  .function = ip6_mpls_label_imposition,
603  .name = "ip6-mpls-label-imposition",
604  .vector_size = sizeof (u32),
605 
606  .format_trace = format_mpls_label_imposition_trace,
607  .n_next_nodes = 1,
608  .next_nodes = {
609  [0] = "ip6-drop",
610  }
611 };
613  ip6_mpls_label_imposition)
614 
615 static void
616 mpls_label_dpo_mem_show (void)
617 {
618  fib_show_memory_usage("MPLS label",
619  pool_elts(mpls_label_dpo_pool),
620  pool_len(mpls_label_dpo_pool),
621  sizeof(mpls_label_dpo_t));
622 }
623 
624 const static dpo_vft_t mld_vft = {
626  .dv_unlock = mpls_label_dpo_unlock,
627  .dv_format = format_mpls_label_dpo,
628  .dv_mem_show = mpls_label_dpo_mem_show,
629 };
630 
631 const static char* const mpls_label_imp_ip4_nodes[] =
632 {
633  "ip4-mpls-label-imposition",
634  NULL,
635 };
636 const static char* const mpls_label_imp_ip6_nodes[] =
637 {
638  "ip6-mpls-label-imposition",
639  NULL,
640 };
641 const static char* const mpls_label_imp_mpls_nodes[] =
642 {
643  "mpls-label-imposition",
644  NULL,
645 };
646 const static char* const * const mpls_label_imp_nodes[DPO_PROTO_NUM] =
647 {
651 };
652 
653 
654 void
656 {
658 }
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:341
static const char *const mpls_label_imp_ip6_nodes[]
VLIB_NODE_FUNCTION_MULTIARCH(mpls_label_imposition_node, mpls_label_imposition)
#define CLIB_UNUSED(x)
Definition: clib.h:79
A virtual function table regisitered for a DPO type.
Definition: dpo.h:336
static const char *const mpls_label_imp_mpls_nodes[]
format_function_t format_mpls_header
Definition: mpls.h:72
mpls_unicast_header_t hdr
The MPLS header imposed.
#define PREDICT_TRUE(x)
Definition: clib.h:98
#define NULL
Definition: clib.h:55
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:459
u32 mpls_label_t
A label value only, i.e.
Definition: packet.h:24
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
#define vlib_validate_buffer_enqueue_x4(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, bi2, bi3, next0, next1, next2, next3)
Finish enqueueing four buffers forward in the graph.
Definition: buffer_node.h:138
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
u8 * format_mpls_label_dpo(u8 *s, va_list *args)
#define pool_len(p)
Number of elements in pool vector.
Definition: pool.h:121
static uword mpls_label_imposition_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame, u8 payload_is_ip4, u8 payload_is_ip6)
index_t mpls_label_dpo_create(mpls_label_t *label_stack, mpls_eos_bit_t eos, u8 ttl, u8 exp, dpo_proto_t payload_proto, const dpo_id_t *dpo)
Create an MPLS label object.
static index_t mpls_label_dpo_get_index(mpls_label_dpo_t *mld)
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:260
#define always_inline
Definition: clib.h:84
static uword format_get_indent(u8 *s)
Definition: format.h:72
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:164
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:221
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
static void vnet_mpls_uc_set_label(mpls_label_t *label_exp_s_ttl, u32 value)
Definition: packet.h:97
dpo_proto_t mld_payload_proto
The protocol of the payload/packets that are being encapped.
static void vnet_mpls_uc_set_exp(mpls_label_t *label_exp_s_ttl, u32 exp)
Definition: packet.h:104
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:152
static mpls_unicast_header_t * mpls_label_paint(vlib_buffer_t *b0, mpls_label_dpo_t *mld0, u8 ttl0)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:188
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:241
#define PREDICT_FALSE(x)
Definition: clib.h:97
#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:216
#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:366
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P (general version).
Definition: pool.h:169
u16 n_vectors
Definition: node.h:345
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
u16 mld_n_hdr_bytes
Cached amount of header bytes to paint.
u16 mld_n_labels
Size of the label stack.
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:85
static mpls_label_dpo_t * mpls_label_dpo_get(index_t index)
#define clib_memcpy(a, b, c)
Definition: string.h:69
vlib_node_registration_t mpls_label_imposition_node
(constructor) VLIB_REGISTER_NODE (mpls_label_imposition_node)
void mpls_label_dpo_module_init(void)
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:460
static void mpls_label_dpo_lock(dpo_id_t *dpo)
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
dpo_id_t mld_dpo
Next DPO in the graph.
struct mpls_label_imposition_trace_t_ mpls_label_imposition_trace_t
A struct to hold tracing information for the MPLS label imposition node.
vlib_node_registration_t ip6_mpls_label_imposition_node
(constructor) VLIB_REGISTER_NODE (ip6_mpls_label_imposition_node)
mpls_label_t label_exp_s_ttl
Definition: packet.h:31
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:201
static void vnet_mpls_uc_set_s(mpls_label_t *label_exp_s_ttl, u32 eos)
Definition: packet.h:111
u8 * format_dpo_id(u8 *s, va_list *args)
Format a DPO_id_t oject
Definition: dpo.c:123
u64 uword
Definition: types.h:112
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
vlib_node_registration_t ip4_mpls_label_imposition_node
(constructor) VLIB_REGISTER_NODE (ip4_mpls_label_imposition_node)
Definition: defs.h:47
#define DPO_PROTO_NUM
Definition: dpo.h:73
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:168
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:269
static void vnet_mpls_uc_set_ttl(mpls_label_t *label_exp_s_ttl, u32 ttl)
Definition: packet.h:118
#define vnet_buffer(b)
Definition: buffer.h:304
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:144
static const char *const *const mpls_label_imp_nodes[DPO_PROTO_NUM]
static u8 * format_mpls_label_imposition_trace(u8 *s, va_list *args)
u8 data[0]
Packet data.
Definition: buffer.h:152
mpls_label_dpo_t * mpls_label_dpo_pool
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:205
u16 mld_locks
Number of locks/users of the label.
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:164
mpls_unicast_header_t mld_hdr[8]
The MPLS label header to impose.
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:74
static mpls_label_dpo_t * mpls_label_dpo_alloc(void)
A struct to hold tracing information for the MPLS label imposition node.
static void mpls_label_dpo_unlock(dpo_id_t *dpo)
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
A representation of an MPLS label for imposition in the data-path.
static const char *const mpls_label_imp_ip4_nodes[]
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:416
enum mpls_eos_bit_t_ mpls_eos_bit_t
static uword mpls_label_imposition(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109