FD.io VPP  v18.01-8-g0eacf49
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 #include <vnet/dpo/drop_dpo.h>
20 
21 /*
22  * pool of all MPLS Label DPOs
23  */
25 
26 static mpls_label_dpo_t *
28 {
29  mpls_label_dpo_t *mld;
30 
31  pool_get_aligned(mpls_label_dpo_pool, mld, CLIB_CACHE_LINE_BYTES);
32  memset(mld, 0, sizeof(*mld));
33 
34  dpo_reset(&mld->mld_dpo);
35 
36  return (mld);
37 }
38 
39 static index_t
41 {
42  return (mld - mpls_label_dpo_pool);
43 }
44 
45 index_t
47  mpls_eos_bit_t eos,
48  u8 ttl,
49  u8 exp,
50  dpo_proto_t payload_proto,
51  const dpo_id_t *dpo)
52 {
53  mpls_label_dpo_t *mld;
54  u32 ii;
55 
56  mld = mpls_label_dpo_alloc();
57 
58  if (MPLS_LABEL_DPO_MAX_N_LABELS < vec_len(label_stack))
59  {
60  clib_warning("Label stack size exceeded");
62  mld->mld_payload_proto,
63  &mld->mld_dpo,
65  return (mpls_label_dpo_get_index(mld));
66  }
67 
68  mld->mld_n_labels = vec_len(label_stack);
69  mld->mld_n_hdr_bytes = mld->mld_n_labels * sizeof(mld->mld_hdr[0]);
70  mld->mld_payload_proto = payload_proto;
71 
72  /*
73  * construct label rewrite headers for each value value passed.
74  * get the header in network byte order since we will paint it
75  * on a packet in the data-plane
76  */
77 
78  for (ii = 0; ii < mld->mld_n_labels-1; ii++)
79  {
80  vnet_mpls_uc_set_label(&mld->mld_hdr[ii].label_exp_s_ttl, label_stack[ii]);
84  mld->mld_hdr[ii].label_exp_s_ttl =
85  clib_host_to_net_u32(mld->mld_hdr[ii].label_exp_s_ttl);
86  }
87 
88  /*
89  * the inner most label
90  */
91  ii = mld->mld_n_labels-1;
92 
93  vnet_mpls_uc_set_label(&mld->mld_hdr[ii].label_exp_s_ttl, label_stack[ii]);
97  mld->mld_hdr[ii].label_exp_s_ttl =
98  clib_host_to_net_u32(mld->mld_hdr[ii].label_exp_s_ttl);
99 
100  /*
101  * stack this label objct on its parent.
102  */
104  mld->mld_payload_proto,
105  &mld->mld_dpo,
106  dpo);
107 
108  return (mpls_label_dpo_get_index(mld));
109 }
110 
111 u8*
112 format_mpls_label_dpo (u8 *s, va_list *args)
113 {
114  index_t index = va_arg (*args, index_t);
115  u32 indent = va_arg (*args, u32);
117  mpls_label_dpo_t *mld;
118  u32 ii;
119 
120  s = format(s, "mpls-label:[%d]:", index);
121 
122  if (pool_is_free_index(mpls_label_dpo_pool, index))
123  {
124  /*
125  * the packet trace can be printed after the DPO has been deleted
126  */
127  return (s);
128  }
129 
130  mld = mpls_label_dpo_get(index);
131 
132  for (ii = 0; ii < mld->mld_n_labels; ii++)
133  {
134  hdr.label_exp_s_ttl =
135  clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
136  s = format(s, "%U", format_mpls_header, hdr);
137  }
138 
139  s = format(s, "\n%U", format_white_space, indent);
140  s = format(s, "%U", format_dpo_id, &mld->mld_dpo, indent+2);
141 
142  return (s);
143 }
144 
145 static void
147 {
148  mpls_label_dpo_t *mld;
149 
150  mld = mpls_label_dpo_get(dpo->dpoi_index);
151 
152  mld->mld_locks++;
153 }
154 
155 static void
157 {
158  mpls_label_dpo_t *mld;
159 
160  mld = mpls_label_dpo_get(dpo->dpoi_index);
161 
162  mld->mld_locks--;
163 
164  if (0 == mld->mld_locks)
165  {
166  dpo_reset(&mld->mld_dpo);
167  pool_put(mpls_label_dpo_pool, mld);
168  }
169 }
170 
171 /**
172  * @brief A struct to hold tracing information for the MPLS label imposition
173  * node.
174  */
176 {
177  /**
178  * The MPLS header imposed
179  */
182 
185  mpls_label_dpo_t *mld0,
186  u8 ttl0)
187 {
188  mpls_unicast_header_t *hdr0;
189 
190  vlib_buffer_advance(b0, -(mld0->mld_n_hdr_bytes));
191 
192  hdr0 = vlib_buffer_get_current(b0);
193 
194  if (1 == mld0->mld_n_labels)
195  {
196  /* optimise for the common case of one label */
197  *hdr0 = mld0->mld_hdr[0];
198  }
199  else
200  {
201  clib_memcpy(hdr0, mld0->mld_hdr, mld0->mld_n_hdr_bytes);
202  hdr0 = hdr0 + (mld0->mld_n_labels - 1);
203  }
204  /* fixup the TTL for the inner most label */
205  ((char*)hdr0)[3] = ttl0;
206 
207  return (hdr0);
208 }
209 
212  vlib_node_runtime_t * node,
213  vlib_frame_t * from_frame,
214  u8 payload_is_ip4,
215  u8 payload_is_ip6,
216  u8 payload_is_ethernet)
217 {
218  u32 n_left_from, next_index, * from, * to_next;
219 
220  from = vlib_frame_vector_args (from_frame);
221  n_left_from = from_frame->n_vectors;
222 
223  next_index = node->cached_next_index;
224 
225  while (n_left_from > 0)
226  {
227  u32 n_left_to_next;
228 
229  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
230 
231  while (n_left_from >= 8 && n_left_to_next >= 4)
232  {
233  u32 bi0, mldi0, bi1, mldi1, bi2, mldi2, bi3, mldi3;
234  mpls_unicast_header_t *hdr0, *hdr1, *hdr2, *hdr3;
235  mpls_label_dpo_t *mld0, *mld1, *mld2, *mld3;
236  vlib_buffer_t * b0, *b1, * b2, *b3;
237  u32 next0, next1, next2, next3;
238  u8 ttl0, ttl1,ttl2, ttl3 ;
239 
240  bi0 = to_next[0] = from[0];
241  bi1 = to_next[1] = from[1];
242  bi2 = to_next[2] = from[2];
243  bi3 = to_next[3] = from[3];
244 
245  /* Prefetch next iteration. */
246  {
247  vlib_buffer_t * p2, * p3, *p4, *p5;
248 
249  p2 = vlib_get_buffer (vm, from[2]);
250  p3 = vlib_get_buffer (vm, from[3]);
251  p4 = vlib_get_buffer (vm, from[4]);
252  p5 = vlib_get_buffer (vm, from[5]);
253 
254  vlib_prefetch_buffer_header (p2, STORE);
255  vlib_prefetch_buffer_header (p3, STORE);
256  vlib_prefetch_buffer_header (p4, STORE);
257  vlib_prefetch_buffer_header (p5, STORE);
258 
259  CLIB_PREFETCH (p2->data, sizeof (hdr0[0]), STORE);
260  CLIB_PREFETCH (p3->data, sizeof (hdr0[0]), STORE);
261  CLIB_PREFETCH (p4->data, sizeof (hdr0[0]), STORE);
262  CLIB_PREFETCH (p5->data, sizeof (hdr0[0]), STORE);
263  }
264 
265  from += 4;
266  to_next += 4;
267  n_left_from -= 4;
268  n_left_to_next -= 4;
269 
270  b0 = vlib_get_buffer (vm, bi0);
271  b1 = vlib_get_buffer (vm, bi1);
272  b2 = vlib_get_buffer (vm, bi2);
273  b3 = vlib_get_buffer (vm, bi3);
274 
275  /* dst lookup was done by ip4 lookup */
276  mldi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
277  mldi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
278  mldi2 = vnet_buffer(b2)->ip.adj_index[VLIB_TX];
279  mldi3 = vnet_buffer(b3)->ip.adj_index[VLIB_TX];
280  mld0 = mpls_label_dpo_get(mldi0);
281  mld1 = mpls_label_dpo_get(mldi1);
282  mld2 = mpls_label_dpo_get(mldi2);
283  mld3 = mpls_label_dpo_get(mldi3);
284 
285  if (payload_is_ip4)
286  {
287  /*
288  * decrement the TTL on ingress to the LSP
289  */
294  u32 checksum0;
295  u32 checksum1;
296  u32 checksum2;
297  u32 checksum3;
298 
299  checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
300  checksum1 = ip1->checksum + clib_host_to_net_u16 (0x0100);
301  checksum2 = ip2->checksum + clib_host_to_net_u16 (0x0100);
302  checksum3 = ip3->checksum + clib_host_to_net_u16 (0x0100);
303 
304  checksum0 += checksum0 >= 0xffff;
305  checksum1 += checksum1 >= 0xffff;
306  checksum2 += checksum2 >= 0xffff;
307  checksum3 += checksum3 >= 0xffff;
308 
309  ip0->checksum = checksum0;
310  ip1->checksum = checksum1;
311  ip2->checksum = checksum2;
312  ip3->checksum = checksum3;
313 
314  ip0->ttl -= 1;
315  ip1->ttl -= 1;
316  ip2->ttl -= 1;
317  ip3->ttl -= 1;
318 
319  ttl1 = ip1->ttl;
320  ttl0 = ip0->ttl;
321  ttl3 = ip3->ttl;
322  ttl2 = ip2->ttl;
323  }
324  else if (payload_is_ip6)
325  {
326  /*
327  * decrement the TTL on ingress to the LSP
328  */
333 
334  ip0->hop_limit -= 1;
335  ip1->hop_limit -= 1;
336  ip2->hop_limit -= 1;
337  ip3->hop_limit -= 1;
338 
339  ttl0 = ip0->hop_limit;
340  ttl1 = ip1->hop_limit;
341  ttl2 = ip2->hop_limit;
342  ttl3 = ip3->hop_limit;
343  }
344  else if (payload_is_ethernet)
345  {
346  /*
347  * nothing to chang ein the ethernet header
348  */
349  ttl0 = ttl1 = ttl2 = ttl3 = 255;
350  }
351  else
352  {
353  /*
354  * else, the packet to be encapped is an MPLS packet
355  */
356  if (PREDICT_TRUE(vnet_buffer(b0)->mpls.first))
357  {
358  /*
359  * The first label to be imposed on the packet. this is a label swap.
360  * in which case we stashed the TTL and EXP bits in the
361  * packet in the lookup node
362  */
363  ASSERT(0 != vnet_buffer (b0)->mpls.ttl);
364 
365  ttl0 = vnet_buffer(b0)->mpls.ttl - 1;
366  }
367  else
368  {
369  /*
370  * not the first label. implying we are recusring down a chain of
371  * output labels.
372  * Each layer is considered a new LSP - hence the TTL is reset.
373  */
374  ttl0 = 255;
375  }
376  if (PREDICT_TRUE(vnet_buffer(b1)->mpls.first))
377  {
378  ASSERT(1 != vnet_buffer (b1)->mpls.ttl);
379  ttl1 = vnet_buffer(b1)->mpls.ttl - 1;
380  }
381  else
382  {
383  ttl1 = 255;
384  }
385  if (PREDICT_TRUE(vnet_buffer(b2)->mpls.first))
386  {
387  ASSERT(1 != vnet_buffer (b2)->mpls.ttl);
388 
389  ttl2 = vnet_buffer(b2)->mpls.ttl - 1;
390  }
391  else
392  {
393  ttl2 = 255;
394  }
395  if (PREDICT_TRUE(vnet_buffer(b3)->mpls.first))
396  {
397  ASSERT(1 != vnet_buffer (b3)->mpls.ttl);
398  ttl3 = vnet_buffer(b3)->mpls.ttl - 1;
399  }
400  else
401  {
402  ttl3 = 255;
403  }
404  }
405  vnet_buffer(b0)->mpls.first = 0;
406  vnet_buffer(b1)->mpls.first = 0;
407  vnet_buffer(b2)->mpls.first = 0;
408  vnet_buffer(b3)->mpls.first = 0;
409 
410  /* Paint the MPLS header */
411  hdr0 = mpls_label_paint(b0, mld0, ttl0);
412  hdr1 = mpls_label_paint(b1, mld1, ttl1);
413  hdr2 = mpls_label_paint(b2, mld2, ttl2);
414  hdr3 = mpls_label_paint(b3, mld3, ttl3);
415 
416  next0 = mld0->mld_dpo.dpoi_next_node;
417  next1 = mld1->mld_dpo.dpoi_next_node;
418  next2 = mld2->mld_dpo.dpoi_next_node;
419  next3 = mld3->mld_dpo.dpoi_next_node;
420  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mld0->mld_dpo.dpoi_index;
421  vnet_buffer(b1)->ip.adj_index[VLIB_TX] = mld1->mld_dpo.dpoi_index;
422  vnet_buffer(b2)->ip.adj_index[VLIB_TX] = mld2->mld_dpo.dpoi_index;
423  vnet_buffer(b3)->ip.adj_index[VLIB_TX] = mld3->mld_dpo.dpoi_index;
424 
426  {
428  vlib_add_trace (vm, node, b0, sizeof (*tr));
429  tr->hdr = *hdr0;
430  }
432  {
434  vlib_add_trace (vm, node, b1, sizeof (*tr));
435  tr->hdr = *hdr1;
436  }
438  {
440  vlib_add_trace (vm, node, b2, sizeof (*tr));
441  tr->hdr = *hdr2;
442  }
444  {
446  vlib_add_trace (vm, node, b3, sizeof (*tr));
447  tr->hdr = *hdr3;
448  }
449 
450  vlib_validate_buffer_enqueue_x4(vm, node, next_index, to_next,
451  n_left_to_next,
452  bi0, bi1, bi2, bi3,
453  next0, next1, next2, next3);
454  }
455 
456  while (n_left_from > 0 && n_left_to_next > 0)
457  {
458  mpls_unicast_header_t *hdr0;
459  mpls_label_dpo_t *mld0;
460  vlib_buffer_t * b0;
461  u32 bi0, mldi0;
462  u32 next0;
463  u8 ttl;
464 
465  bi0 = from[0];
466  to_next[0] = bi0;
467  from += 1;
468  to_next += 1;
469  n_left_from -= 1;
470  n_left_to_next -= 1;
471 
472  b0 = vlib_get_buffer (vm, bi0);
473 
474  /* dst lookup was done by ip4 lookup */
475  mldi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
476  mld0 = mpls_label_dpo_get(mldi0);
477 
478  if (payload_is_ip4)
479  {
480  /*
481  * decrement the TTL on ingress to the LSP
482  */
484  u32 checksum0;
485 
486  checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
487  checksum0 += checksum0 >= 0xffff;
488 
489  ip0->checksum = checksum0;
490  ip0->ttl -= 1;
491  ttl = ip0->ttl;
492  }
493  else if (payload_is_ip6)
494  {
495  /*
496  * decrement the TTL on ingress to the LSP
497  */
499 
500  ip0->hop_limit -= 1;
501  ttl = ip0->hop_limit;
502  }
503  else
504  {
505  /*
506  * else, the packet to be encapped is an MPLS packet
507  */
508  if (vnet_buffer(b0)->mpls.first)
509  {
510  /*
511  * The first label to be imposed on the packet. this is a label swap.
512  * in which case we stashed the TTL and EXP bits in the
513  * packet in the lookup node
514  */
515  ASSERT(0 != vnet_buffer (b0)->mpls.ttl);
516 
517  ttl = vnet_buffer(b0)->mpls.ttl - 1;
518  }
519  else
520  {
521  /*
522  * not the first label. implying we are recusring down a chain of
523  * output labels.
524  * Each layer is considered a new LSP - hence the TTL is reset.
525  */
526  ttl = 255;
527  }
528  }
529  vnet_buffer(b0)->mpls.first = 0;
530 
531  /* Paint the MPLS header */
532  vlib_buffer_advance(b0, -(mld0->mld_n_hdr_bytes));
533  hdr0 = vlib_buffer_get_current(b0);
534  clib_memcpy(hdr0, mld0->mld_hdr, mld0->mld_n_hdr_bytes);
535 
536  /* fixup the TTL for the inner most label */
537  hdr0 = hdr0 + (mld0->mld_n_labels - 1);
538  ((char*)hdr0)[3] = ttl;
539 
540  next0 = mld0->mld_dpo.dpoi_next_node;
541  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mld0->mld_dpo.dpoi_index;
542 
544  {
546  vlib_add_trace (vm, node, b0, sizeof (*tr));
547  tr->hdr = *hdr0;
548  }
549 
550  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
551  n_left_to_next, bi0, next0);
552  }
553  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
554  }
555  return from_frame->n_vectors;
556 }
557 
558 static u8 *
560 {
561  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
562  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
565  u32 indent;
566 
567  t = va_arg (*args, mpls_label_imposition_trace_t *);
568  indent = format_get_indent (s);
569  hdr.label_exp_s_ttl = clib_net_to_host_u32(t->hdr.label_exp_s_ttl);
570 
571  s = format (s, "%Umpls-header:%U",
572  format_white_space, indent,
573  format_mpls_header, hdr);
574  return (s);
575 }
576 
577 static uword
579  vlib_node_runtime_t * node,
580  vlib_frame_t * frame)
581 {
582  return (mpls_label_imposition_inline(vm, node, frame, 0, 0, 0));
583 }
584 
586  .function = mpls_label_imposition,
587  .name = "mpls-label-imposition",
588  .vector_size = sizeof (u32),
589 
590  .format_trace = format_mpls_label_imposition_trace,
591  .n_next_nodes = 1,
592  .next_nodes = {
593  [0] = "mpls-drop",
594  }
595 };
598 
599 static uword
600 ip4_mpls_label_imposition (vlib_main_t * vm,
601  vlib_node_runtime_t * node,
602  vlib_frame_t * frame)
603 {
604  return (mpls_label_imposition_inline(vm, node, frame, 1, 0, 0));
605 }
606 
608  .function = ip4_mpls_label_imposition,
609  .name = "ip4-mpls-label-imposition",
610  .vector_size = sizeof (u32),
611 
612  .format_trace = format_mpls_label_imposition_trace,
613  .n_next_nodes = 1,
614  .next_nodes = {
615  [0] = "ip4-drop",
616  }
617 };
619  ip4_mpls_label_imposition)
620 
621 static uword
622 ip6_mpls_label_imposition (vlib_main_t * vm,
623  vlib_node_runtime_t * node,
624  vlib_frame_t * frame)
625 {
626  return (mpls_label_imposition_inline(vm, node, frame, 0, 1, 0));
627 }
628 
630  .function = ip6_mpls_label_imposition,
631  .name = "ip6-mpls-label-imposition",
632  .vector_size = sizeof (u32),
633 
634  .format_trace = format_mpls_label_imposition_trace,
635  .n_next_nodes = 1,
636  .next_nodes = {
637  [0] = "ip6-drop",
638  }
639 };
641  ip6_mpls_label_imposition)
642 
643 static uword
644 ethernet_mpls_label_imposition (vlib_main_t * vm,
645  vlib_node_runtime_t * node,
646  vlib_frame_t * frame)
647 {
648  return (mpls_label_imposition_inline(vm, node, frame, 0, 0, 1));
649 }
650 
652  .function = ethernet_mpls_label_imposition,
653  .name = "ethernet-mpls-label-imposition",
654  .vector_size = sizeof (u32),
655 
656  .format_trace = format_mpls_label_imposition_trace,
657  .n_next_nodes = 1,
658  .next_nodes = {
659  [0] = "error-drop",
660  }
661 };
663  ethernet_mpls_label_imposition)
664 
665 static void
666 mpls_label_dpo_mem_show (void)
667 {
668  fib_show_memory_usage("MPLS label",
669  pool_elts(mpls_label_dpo_pool),
670  pool_len(mpls_label_dpo_pool),
671  sizeof(mpls_label_dpo_t));
672 }
673 
674 const static dpo_vft_t mld_vft = {
676  .dv_unlock = mpls_label_dpo_unlock,
677  .dv_format = format_mpls_label_dpo,
678  .dv_mem_show = mpls_label_dpo_mem_show,
679 };
680 
681 const static char* const mpls_label_imp_ip4_nodes[] =
682 {
683  "ip4-mpls-label-imposition",
684  NULL,
685 };
686 const static char* const mpls_label_imp_ip6_nodes[] =
687 {
688  "ip6-mpls-label-imposition",
689  NULL,
690 };
691 const static char* const mpls_label_imp_mpls_nodes[] =
692 {
693  "mpls-label-imposition",
694  NULL,
695 };
696 const static char* const mpls_label_imp_ethernet_nodes[] =
697 {
698  "ethernet-mpls-label-imposition",
699  NULL,
700 };
701 
702 const static char* const * const mpls_label_imp_nodes[DPO_PROTO_NUM] =
703 {
708 };
709 
710 
711 void
713 {
715 }
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:382
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:377
static const char *const mpls_label_imp_mpls_nodes[]
format_function_t format_mpls_header
Definition: mpls.h:70
mpls_unicast_header_t hdr
The MPLS header imposed.
static const char *const mpls_label_imp_ethernet_nodes[]
#define PREDICT_TRUE(x)
Definition: clib.h:106
#define NULL
Definition: clib.h:55
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
static u32 format_get_indent(u8 *s)
Definition: format.h:72
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:140
const dpo_id_t * drop_dpo_get(dpo_proto_t proto)
Definition: drop_dpo.c:25
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:306
#define MPLS_LABEL_DPO_MAX_N_LABELS
Maximum number of labels in one DPO.
#define always_inline
Definition: clib.h:92
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:171
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
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:166
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:195
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:271
#define PREDICT_FALSE(x)
Definition: clib.h:105
#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
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P (general version).
Definition: pool.h:188
u16 n_vectors
Definition: node.h:344
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
vlib_main_t * vm
Definition: buffer.c:283
u16 mld_n_hdr_bytes
Cached amount of header bytes to paint.
vlib_node_registration_t ethernet_mpls_label_imposition_node
(constructor) VLIB_REGISTER_NODE (ethernet_mpls_label_imposition_node)
u16 mld_n_labels
Size of the label stack.
#define clib_warning(format, args...)
Definition: error.h:59
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:93
static mpls_label_dpo_t * mpls_label_dpo_get(index_t index)
#define clib_memcpy(a, b, c)
Definition: string.h:75
vlib_node_registration_t mpls_label_imposition_node
(constructor) VLIB_REGISTER_NODE (mpls_label_imposition_node)
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:268
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:454
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:456
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:208
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:146
mpls_unicast_header_t mld_hdr[MPLS_LABEL_DPO_MAX_N_LABELS]
The MPLS label header to impose.
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:70
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:182
#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:267
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:326
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
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:159
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:228
u16 mld_locks
Number of locks/users of the label.
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:178
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
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:75
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 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, u8 payload_is_ethernet)
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:470
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:128