FD.io VPP  v21.06-1-gbb7418cf9
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 // clang-format off
22 
23 #ifndef CLIB_MARCH_VARIANT
24 /*
25  * pool of all MPLS Label DPOs
26  */
28 
29 /**
30  * Strings for the flags
31  */
33 
34 /**
35  * registered DPO types for each of the label sub-types. And there's a
36  * subtype for each of the flag combinations.
37  */
39 
40 static mpls_label_dpo_t *
42 {
43  mpls_label_dpo_t *mld;
44  vlib_main_t *vm;
45  u8 did_barrier_sync;
46 
47  dpo_pool_barrier_sync (vm, mpls_label_dpo_pool, did_barrier_sync);
48  pool_get_aligned(mpls_label_dpo_pool, mld, CLIB_CACHE_LINE_BYTES);
49  dpo_pool_barrier_release (vm, did_barrier_sync);
50 
51  clib_memset(mld, 0, sizeof(*mld));
52 
53  dpo_reset(&mld->mld_dpo);
54 
55  return (mld);
56 }
57 
58 static index_t
60 {
61  return (mld - mpls_label_dpo_pool);
62 }
63 
64 void
66  mpls_eos_bit_t eos,
67  dpo_proto_t payload_proto,
69  const dpo_id_t *parent,
70  dpo_id_t *dpo)
71 {
72  mpls_label_dpo_t *mld;
73  dpo_type_t dtype;
74  u32 ii;
75 
76  if ((DPO_PROTO_IP4 != payload_proto) &&
77  (DPO_PROTO_IP6 != payload_proto))
78  {
79  /*
80  * remove unsupported configuration
81  */
83  }
84 
85  mld = mpls_label_dpo_alloc();
86  mld->mld_flags = flags;
87  dtype = mpls_label_dpo_types[flags];
88 
89  if (MPLS_LABEL_DPO_MAX_N_LABELS < vec_len(label_stack))
90  {
91  clib_warning("Label stack size exceeded");
92  dpo_stack(dtype,
93  mld->mld_payload_proto,
94  &mld->mld_dpo,
96  }
97  else
98  {
99  mld->mld_n_labels = vec_len(label_stack);
100  mld->mld_n_hdr_bytes = mld->mld_n_labels * sizeof(mld->mld_hdr[0]);
101  mld->mld_payload_proto = payload_proto;
102 
103  /*
104  * construct label rewrite headers for each value passed.
105  * get the header in network byte order since we will paint it
106  * on a packet in the data-plane
107  */
108  for (ii = 0; ii < mld->mld_n_labels-1; ii++)
109  {
111  label_stack[ii].fml_value);
113  label_stack[ii].fml_exp);
115  MPLS_NON_EOS);
116  if (0 != label_stack[ii].fml_ttl)
117  {
119  label_stack[ii].fml_ttl);
120  }
121  else
122  {
125  }
126  mld->mld_hdr[ii].label_exp_s_ttl =
127  clib_host_to_net_u32(mld->mld_hdr[ii].label_exp_s_ttl);
128  }
129 
130  /*
131  * the inner most label
132  */
133  ii = mld->mld_n_labels-1;
134 
136  label_stack[ii].fml_value);
138  label_stack[ii].fml_exp);
140  if (0 != label_stack[ii].fml_ttl)
141  {
143  label_stack[ii].fml_ttl);
144  }
145  else
146  {
149  }
150  mld->mld_hdr[ii].label_exp_s_ttl =
151  clib_host_to_net_u32(mld->mld_hdr[ii].label_exp_s_ttl);
152 
153  /*
154  * pipe/uniform mode is only supported for the bottom of stack label
155  */
156  if (FIB_MPLS_LSP_MODE_UNIFORM == label_stack[ii].fml_mode)
157  {
159  }
160  else
161  {
163  }
164  dtype = mpls_label_dpo_types[mld->mld_flags];
165 
166  /*
167  * stack this label object on its parent.
168  */
169  dpo_stack(dtype,
170  mld->mld_payload_proto,
171  &mld->mld_dpo,
172  parent);
173  }
174 
175  dpo_set(dpo,
176  dtype,
177  mld->mld_payload_proto,
179 }
180 
181 u8*
182 format_mpls_label_dpo_flags (u8 *s, va_list *args)
183 {
184  mpls_label_dpo_flags_t flags = va_arg (*args, int);
186 
188  {
189  if ((1 << attr) & flags)
190  {
191  s = format(s, "%s,", mpls_label_dpo_attr_names[attr]);
192  }
193  }
194 
195  return (s);
196 }
197 
198 u8*
199 format_mpls_label_dpo (u8 *s, va_list *args)
200 {
201  index_t index = va_arg (*args, index_t);
202  u32 indent = va_arg (*args, u32);
204  mpls_label_dpo_t *mld;
205  u32 ii;
206 
207  if (pool_is_free_index(mpls_label_dpo_pool, index))
208  {
209  /*
210  * the packet trace can be printed after the DPO has been deleted
211  */
212  return (format(s, "mpls-label[???,%d]:", index));
213  }
214 
215  mld = mpls_label_dpo_get(index);
216  s = format(s, "mpls-label[%U@%d]:",
218  (int) mld->mld_flags, index);
219 
220  for (ii = 0; ii < mld->mld_n_labels; ii++)
221  {
222  hdr.label_exp_s_ttl =
223  clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
224  s = format(s, "%U", format_mpls_header, hdr);
225  }
226 
227  s = format(s, "\n%U", format_white_space, indent);
228  s = format(s, "%U", format_dpo_id, &mld->mld_dpo, indent+2);
229 
230  return (s);
231 }
232 
233 static void
235 {
236  mpls_label_dpo_t *mld;
237 
238  mld = mpls_label_dpo_get(dpo->dpoi_index);
239 
240  mld->mld_locks++;
241 }
242 
243 static void
245 {
246  mpls_label_dpo_t *mld;
247 
248  mld = mpls_label_dpo_get(dpo->dpoi_index);
249 
250  mld->mld_locks--;
251 
252  if (0 == mld->mld_locks)
253  {
254  dpo_reset(&mld->mld_dpo);
255  pool_put(mpls_label_dpo_pool, mld);
256  }
257 }
258 #endif /* CLIB_MARCH_VARIANT */
259 
260 /**
261  * @brief A struct to hold tracing information for the MPLS label imposition
262  * node.
263  */
265 {
266  /**
267  * The MPLS header imposed
268  */
270 
271  /**
272  * TTL imposed - only valid for uniform LSPs
273  */
275 
276  /**
277  * TTL imposed - only valid for uniform LSPs
278  */
281 
284  mpls_label_dpo_t *mld0)
285 {
286  mpls_unicast_header_t *hdr0;
287 
288  vlib_buffer_advance(b0, -(mld0->mld_n_hdr_bytes));
289 
290  hdr0 = vlib_buffer_get_current(b0);
291 
292  if (1 == mld0->mld_n_labels)
293  {
294  /* optimise for the common case of one label */
295  *hdr0 = mld0->mld_hdr[0];
296  }
297  else
298  {
299  clib_memcpy_fast(hdr0, mld0->mld_hdr, mld0->mld_n_hdr_bytes);
300  hdr0 = hdr0 + (mld0->mld_n_labels - 1);
301  }
302 
303  return (hdr0);
304 }
305 
306 /**
307  * Paint on an MPLS label and fixup the TTL
308  */
311  mpls_label_dpo_t *mld0,
312  u8 ttl0)
313 {
314  mpls_unicast_header_t *hdr0;
315 
316  hdr0 = mpls_label_paint(b0, mld0);
317 
318  /* fixup the TTL for the inner most label */
319  ((char*)hdr0)[3] = ttl0;
320 
321  return (hdr0);
322 }
323 
324 /**
325  * Paint on an MPLS label and fixup the TTL and EXP bits.
326  */
329  mpls_label_dpo_t *mld0,
330  u8 ttl0,
331  u8 exp0)
332 {
333  mpls_unicast_header_t *hdr0;
334 
335  hdr0 = mpls_label_paint_w_ttl(b0, mld0, ttl0);
336 
337  /* fixup the EXP for the inner most label */
338  ((char*)hdr0)[2] |= (exp0 << 1);
339 
340  return (hdr0);
341 }
342 
343 /**
344  * Paint on an MPLS label and fixup the TTL and EXP bits
345  * When the EXP bits are *already* bit shift to the correct place in
346  * in the 2nd byte (i.e. they were read from another label)
347  */
350  mpls_label_dpo_t *mld0,
351  u8 ttl0,
352  u8 exp0)
353 {
354  mpls_unicast_header_t *hdr0;
355 
356  hdr0 = mpls_label_paint_w_ttl(b0, mld0, ttl0);
357 
358  /* fixup the EXP for the inner most label */
359  ((char*)hdr0)[2] |= exp0;
360 
361  return (hdr0);
362 }
363 
368  const dpo_proto_t dproto,
370 {
371  u32 n_left_from, next_index, * from, * to_next;
372 
373  from = vlib_frame_vector_args (from_frame);
374  n_left_from = from_frame->n_vectors;
375 
376  next_index = node->cached_next_index;
377 
378  while (n_left_from > 0)
379  {
380  u32 n_left_to_next;
381 
382  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
383 
384  while (n_left_from >= 8 && n_left_to_next >= 4)
385  {
386  u32 bi0, mldi0, bi1, mldi1, bi2, mldi2, bi3, mldi3;
387  mpls_unicast_header_t *hdr0, *hdr1, *hdr2, *hdr3;
388  mpls_label_dpo_t *mld0, *mld1, *mld2, *mld3;
389  vlib_buffer_t * b0, *b1, * b2, *b3;
390  u32 next0, next1, next2, next3;
391  u8 ttl0, ttl1, ttl2, ttl3;
392  u8 exp0, exp1, exp2, exp3;
393 
394  bi0 = to_next[0] = from[0];
395  bi1 = to_next[1] = from[1];
396  bi2 = to_next[2] = from[2];
397  bi3 = to_next[3] = from[3];
398 
399  /* Prefetch next iteration. */
400  {
401  vlib_buffer_t * p2, * p3, *p4, *p5;
402 
403  p2 = vlib_get_buffer (vm, from[2]);
404  p3 = vlib_get_buffer (vm, from[3]);
405  p4 = vlib_get_buffer (vm, from[4]);
406  p5 = vlib_get_buffer (vm, from[5]);
407 
408  vlib_prefetch_buffer_header (p2, STORE);
409  vlib_prefetch_buffer_header (p3, STORE);
410  vlib_prefetch_buffer_header (p4, STORE);
411  vlib_prefetch_buffer_header (p5, STORE);
412 
413  CLIB_PREFETCH (p2->data, sizeof (hdr0[0]), STORE);
414  CLIB_PREFETCH (p3->data, sizeof (hdr0[0]), STORE);
415  CLIB_PREFETCH (p4->data, sizeof (hdr0[0]), STORE);
416  CLIB_PREFETCH (p5->data, sizeof (hdr0[0]), STORE);
417  }
418 
419  from += 4;
420  to_next += 4;
421  n_left_from -= 4;
422  n_left_to_next -= 4;
423 
424  b0 = vlib_get_buffer (vm, bi0);
425  b1 = vlib_get_buffer (vm, bi1);
426  b2 = vlib_get_buffer (vm, bi2);
427  b3 = vlib_get_buffer (vm, bi3);
428 
429  /* dst lookup was done by ip4 lookup */
430  mldi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
431  mldi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
432  mldi2 = vnet_buffer(b2)->ip.adj_index[VLIB_TX];
433  mldi3 = vnet_buffer(b3)->ip.adj_index[VLIB_TX];
434  mld0 = mpls_label_dpo_get(mldi0);
435  mld1 = mpls_label_dpo_get(mldi1);
436  mld2 = mpls_label_dpo_get(mldi2);
437  mld3 = mpls_label_dpo_get(mldi3);
438 
439  if (DPO_PROTO_MPLS != dproto)
440  {
441  /*
442  * These are the non-MPLS payload imposition cases
443  */
444  if (DPO_PROTO_IP4 == dproto)
445  {
450 
451  if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
452  {
453  /*
454  * decrement the TTL on ingress to the LSP
455  */
456  u32 checksum0;
457  u32 checksum1;
458  u32 checksum2;
459  u32 checksum3;
460 
461  checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
462  checksum1 = ip1->checksum + clib_host_to_net_u16 (0x0100);
463  checksum2 = ip2->checksum + clib_host_to_net_u16 (0x0100);
464  checksum3 = ip3->checksum + clib_host_to_net_u16 (0x0100);
465 
466  checksum0 += checksum0 >= 0xffff;
467  checksum1 += checksum1 >= 0xffff;
468  checksum2 += checksum2 >= 0xffff;
469  checksum3 += checksum3 >= 0xffff;
470 
471  ip0->checksum = checksum0;
472  ip1->checksum = checksum1;
473  ip2->checksum = checksum2;
474  ip3->checksum = checksum3;
475 
476  ip0->ttl -= 1;
477  ip1->ttl -= 1;
478  ip2->ttl -= 1;
479  ip3->ttl -= 1;
480  }
481 
483  {
484  ttl1 = ip1->ttl;
485  ttl0 = ip0->ttl;
486  ttl3 = ip3->ttl;
487  ttl2 = ip2->ttl;
488  /* by default copy the 3 most significant bits */
489  exp0 = ip_dscp_to_mpls_exp(ip0->tos);
490  exp1 = ip_dscp_to_mpls_exp(ip1->tos);
491  exp2 = ip_dscp_to_mpls_exp(ip2->tos);
492  exp3 = ip_dscp_to_mpls_exp(ip3->tos);
493  }
494 
495  /* save the payload proto information in mpls opaque */
496  vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP4;
497  vnet_buffer(b1)->mpls.pyld_proto = DPO_PROTO_IP4;
498  vnet_buffer(b2)->mpls.pyld_proto = DPO_PROTO_IP4;
499  vnet_buffer(b3)->mpls.pyld_proto = DPO_PROTO_IP4;
500  }
501  else if (DPO_PROTO_IP6 == dproto)
502  {
503  /*
504  * decrement the TTL on ingress to the LSP
505  */
510 
511  if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
512  {
513  ip0->hop_limit -= 1;
514  ip1->hop_limit -= 1;
515  ip2->hop_limit -= 1;
516  ip3->hop_limit -= 1;
517  }
519  {
520  ttl0 = ip0->hop_limit;
521  ttl1 = ip1->hop_limit;
522  ttl2 = ip2->hop_limit;
523  ttl3 = ip3->hop_limit;
524  /* by default copy the 3 most significant bits */
525  exp0 = ip_dscp_to_mpls_exp(
527  exp1 = ip_dscp_to_mpls_exp(
529  exp2 = ip_dscp_to_mpls_exp(
531  exp3 = ip_dscp_to_mpls_exp(
533  }
534 
535  /* save the payload proto information in mpls opaque */
536  vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP6;
537  vnet_buffer(b1)->mpls.pyld_proto = DPO_PROTO_IP6;
538  vnet_buffer(b2)->mpls.pyld_proto = DPO_PROTO_IP6;
539  vnet_buffer(b3)->mpls.pyld_proto = DPO_PROTO_IP6;
540  }
541  else
542  {
543  /*
544  * nothing to change in the ethernet header
545  */
546  ttl0 = ttl1 = ttl2 = ttl3 = MPLS_LABEL_DEFAULT_TTL;
547  exp0 = exp1 = exp2 = exp3 = MPLS_LABEL_DEFAULT_EXP;
548  }
549  /*
550  * These are the non-MPLS payload imposition cases.
551  * Based on the LSP mode either, for uniform, copy down the TTL
552  * and EXP from the payload or, for pipe mode, slap on the value
553  * requested from config
554  */
556  {
557  hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
558  hdr1 = mpls_label_paint_w_ttl_exp(b1, mld1, ttl1, exp1);
559  hdr2 = mpls_label_paint_w_ttl_exp(b2, mld2, ttl2, exp2);
560  hdr3 = mpls_label_paint_w_ttl_exp(b3, mld3, ttl3, exp3);
561  }
562  else
563  {
564  hdr0 = mpls_label_paint(b0, mld0);
565  hdr1 = mpls_label_paint(b1, mld1);
566  hdr2 = mpls_label_paint(b2, mld2);
567  hdr3 = mpls_label_paint(b3, mld3);
568  }
569  }
570  else
571  {
572  /*
573  * else, the packet to be encapped is an MPLS packet
574  * there are two cases to consider:
575  * 1 - this is an MPLS label swap at an LSP midpoint.
576  * recognisable because mpls.first = 1. In this case the
577  * TTL must be set to the current value -1.
578  * 2 - The MPLS packet is recursing (or being injected into)
579  * this LSP, in which case the pipe/uniform rules apply
580  *
581  */
582  if (PREDICT_TRUE(vnet_buffer(b0)->mpls.first))
583  {
584  /*
585  * The first label to be imposed on the packet. this is a
586  * label swap.in which case we stashed the TTL and EXP bits
587  * in the packet in the lookup node
588  */
589  ASSERT(0 != vnet_buffer (b0)->mpls.ttl);
590 
591  ttl0 = vnet_buffer(b0)->mpls.ttl - 1;
592  exp0 = vnet_buffer(b0)->mpls.exp;
593  hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
594  }
595  else
596  {
597  /*
598  * not the first label. implying we are recusring down a
599  * chain of output labels. Each layer is considered a new
600  * LSP - hence the TTL/EXP are pipe/uniform handled
601  */
603  {
604  hdr0 = vlib_buffer_get_current(b0);
605  ttl0 = ((u8*)hdr0)[3];
606  exp0 = ((u8*)hdr0)[2] & 0xe;
607  hdr0 = mpls_label_paint_w_ttl_mpls_exp(b0, mld0, ttl0, exp0);
608  }
609  else
610  {
611  hdr0 = mpls_label_paint(b0, mld0);
612  }
613  }
614  if (PREDICT_TRUE(vnet_buffer(b1)->mpls.first))
615  {
616  ASSERT(0 != vnet_buffer (b1)->mpls.ttl);
617 
618  ttl1 = vnet_buffer(b1)->mpls.ttl - 1;
619  exp1 = vnet_buffer(b1)->mpls.exp;
620  hdr1 = mpls_label_paint_w_ttl_exp(b1, mld1, ttl1, exp1);
621  }
622  else
623  {
625  {
626  hdr1 = vlib_buffer_get_current(b1);
627  ttl1 = ((u8*)hdr1)[3];
628  exp1 = ((u8*)hdr1)[2] & 0xe;
629  hdr1 = mpls_label_paint_w_ttl_mpls_exp(b1, mld1, ttl1, exp1);
630  }
631  else
632  {
633  hdr1 = mpls_label_paint(b1, mld1);
634  }
635  }
636  if (PREDICT_TRUE(vnet_buffer(b2)->mpls.first))
637  {
638  ASSERT(0 != vnet_buffer (b2)->mpls.ttl);
639 
640  ttl2 = vnet_buffer(b2)->mpls.ttl - 1;
641  exp2 = vnet_buffer(b2)->mpls.exp;
642  hdr2 = mpls_label_paint_w_ttl_exp(b2, mld2, ttl2, exp2);
643  }
644  else
645  {
647  {
648  hdr2 = vlib_buffer_get_current(b2);
649  ttl2 = ((u8*)hdr2)[3];
650  exp2 = ((u8*)hdr2)[2] & 0xe;
651  hdr2 = mpls_label_paint_w_ttl_mpls_exp(b2, mld2, ttl2, exp2);
652  }
653  else
654  {
655  hdr2 = mpls_label_paint(b2, mld2);
656  }
657  }
658  if (PREDICT_TRUE(vnet_buffer(b3)->mpls.first))
659  {
660  ASSERT(0 != vnet_buffer (b3)->mpls.ttl);
661 
662  ttl3 = vnet_buffer(b3)->mpls.ttl - 1;
663  exp3 = vnet_buffer(b3)->mpls.exp;
664  hdr3 = mpls_label_paint_w_ttl_exp(b3, mld3, ttl3, exp3);
665  }
666  else
667  {
669  {
670  hdr3 = vlib_buffer_get_current(b3);
671  ttl3 = ((u8*)hdr3)[3];
672  exp3 = ((u8*)hdr3)[2] & 0xe;
673  hdr3 = mpls_label_paint_w_ttl_mpls_exp(b3, mld3, ttl3, exp3);
674  }
675  else
676  {
677  hdr3 = mpls_label_paint(b3, mld3);
678  }
679  }
680 
681  vnet_buffer(b0)->mpls.first = 0;
682  vnet_buffer(b1)->mpls.first = 0;
683  vnet_buffer(b2)->mpls.first = 0;
684  vnet_buffer(b3)->mpls.first = 0;
685  }
686 
687  next0 = mld0->mld_dpo.dpoi_next_node;
688  next1 = mld1->mld_dpo.dpoi_next_node;
689  next2 = mld2->mld_dpo.dpoi_next_node;
690  next3 = mld3->mld_dpo.dpoi_next_node;
691 
692  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mld0->mld_dpo.dpoi_index;
693  vnet_buffer(b1)->ip.adj_index[VLIB_TX] = mld1->mld_dpo.dpoi_index;
694  vnet_buffer(b2)->ip.adj_index[VLIB_TX] = mld2->mld_dpo.dpoi_index;
695  vnet_buffer(b3)->ip.adj_index[VLIB_TX] = mld3->mld_dpo.dpoi_index;
696 
697  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
698  {
700  vlib_add_trace (vm, node, b0, sizeof (*tr));
701  tr->hdr = *hdr0;
703  {
704  tr->ttl = ttl0;
705  tr->exp = exp0;
706  }
707  else
708  {
709  tr->ttl = tr->exp = 0;
710  }
711  }
712  if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
713  {
715  vlib_add_trace (vm, node, b1, sizeof (*tr));
716  tr->hdr = *hdr1;
718  {
719  tr->ttl = ttl1;
720  tr->exp = exp1;
721  }
722  else
723  {
724  tr->ttl = tr->exp = 0;
725  }
726  }
727  if (PREDICT_FALSE(b2->flags & VLIB_BUFFER_IS_TRACED))
728  {
730  vlib_add_trace (vm, node, b2, sizeof (*tr));
731  tr->hdr = *hdr2;
733  {
734  tr->ttl = ttl2;
735  tr->exp = exp2;
736  }
737  else
738  {
739  tr->ttl = tr->exp = 0;
740  }
741  }
742  if (PREDICT_FALSE(b3->flags & VLIB_BUFFER_IS_TRACED))
743  {
745  vlib_add_trace (vm, node, b3, sizeof (*tr));
746  tr->hdr = *hdr3;
748  {
749  tr->ttl = ttl3;
750  tr->exp = exp3;
751  }
752  else
753  {
754  tr->ttl = tr->exp = 0;
755  }
756  }
757 
758  vlib_validate_buffer_enqueue_x4(vm, node, next_index, to_next,
759  n_left_to_next,
760  bi0, bi1, bi2, bi3,
761  next0, next1, next2, next3);
762  }
763 
764  while (n_left_from > 0 && n_left_to_next > 0)
765  {
766  mpls_unicast_header_t *hdr0;
767  mpls_label_dpo_t *mld0;
768  vlib_buffer_t * b0;
769  u32 bi0, mldi0;
770  u8 ttl0, exp0;
771  u32 next0;
772 
773  bi0 = from[0];
774  to_next[0] = bi0;
775  from += 1;
776  to_next += 1;
777  n_left_from -= 1;
778  n_left_to_next -= 1;
779 
780  b0 = vlib_get_buffer (vm, bi0);
781 
782  /* dst lookup was done by ip4 lookup */
783  mldi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
784  mld0 = mpls_label_dpo_get(mldi0);
785 
786  if (DPO_PROTO_MPLS != dproto)
787  {
788  if (DPO_PROTO_IP4 == dproto)
789  {
790  /*
791  * decrement the TTL on ingress to the LSP
792  */
794  if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
795  {
796  u32 checksum0;
797 
798  checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
799  checksum0 += checksum0 >= 0xffff;
800 
801  ip0->checksum = checksum0;
802  ip0->ttl -= 1;
803  }
805  {
806  ttl0 = ip0->ttl;
807  exp0 = ip_dscp_to_mpls_exp(ip0->tos);
808  }
809 
810  /* save the payload proto information in mpls opaque */
811  vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP4;
812  }
813  else if (DPO_PROTO_IP6 == dproto)
814  {
815  /*
816  * decrement the TTL on ingress to the LSP
817  */
819 
820  if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
821  {
822  ip0->hop_limit -= 1;
823  }
825  {
826  ttl0 = ip0->hop_limit;
827  exp0 = ip_dscp_to_mpls_exp(
829  }
830 
831  /* save the payload proto information in mpls opaque */
832  vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP6;
833  }
834  else
835  {
836  /*
837  * nothing to change in the ethernet header
838  */
839  ttl0 = MPLS_LABEL_DEFAULT_TTL;
840  exp0 = MPLS_LABEL_DEFAULT_EXP;
841  }
842 
843  /*
844  * These are the non-MPLS payload imposition cases.
845  * Based on the LSP mode either, for uniform, copy down the TTL
846  * from the payload or, for pipe mode, slap on the value
847  * requested from config
848  */
850  {
851  hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
852  }
853  else
854  {
855  hdr0 = mpls_label_paint(b0, mld0);
856  }
857  }
858  else
859  {
860  if (PREDICT_TRUE(vnet_buffer(b0)->mpls.first))
861  {
862  ASSERT(0 != vnet_buffer (b0)->mpls.ttl);
863 
864  ttl0 = vnet_buffer(b0)->mpls.ttl - 1;
865  exp0 = vnet_buffer(b0)->mpls.exp;
866  hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
867  }
868  else
869  {
871  {
872  hdr0 = vlib_buffer_get_current(b0);
873  ttl0 = ((u8*)hdr0)[3];
874  exp0 = ((u8*)hdr0)[2] & 0xe;
875  hdr0 = mpls_label_paint_w_ttl_mpls_exp(b0, mld0, ttl0, exp0);
876  }
877  else
878  {
879  hdr0 = mpls_label_paint(b0, mld0);
880  }
881  }
882 
883  vnet_buffer(b0)->mpls.first = 0;
884  }
885 
886  next0 = mld0->mld_dpo.dpoi_next_node;
887  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mld0->mld_dpo.dpoi_index;
888 
889  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
890  {
892  vlib_add_trace (vm, node, b0, sizeof (*tr));
893  tr->hdr = *hdr0;
895  {
896  tr->ttl = ttl0;
897  tr->exp = exp0;
898  }
899  else
900  {
901  tr->ttl = tr->exp = 0;
902  }
903  }
904 
905  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
906  n_left_to_next, bi0, next0);
907  }
908  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
909  }
910  return from_frame->n_vectors;
911 }
912 
913 static u8 *
915 {
916  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
917  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
920  u32 indent;
921 
922  t = va_arg (*args, mpls_label_imposition_trace_t *);
923  indent = format_get_indent (s);
924  hdr.label_exp_s_ttl = clib_net_to_host_u32(t->hdr.label_exp_s_ttl);
925 
926  s = format (s, "%Umpls-header:%U",
927  format_white_space, indent,
928  format_mpls_header, hdr);
929  return (s);
930 }
931 
935 {
939 }
940 
942  .name = "mpls-label-imposition-pipe",
943  .vector_size = sizeof (u32),
944 
945  .format_trace = format_mpls_label_imposition_trace,
946  .n_next_nodes = 1,
947  .next_nodes = {
948  [0] = "mpls-drop",
949  }
950 };
951 
955 {
959 }
960 
962  .name = "ip4-mpls-label-imposition-pipe",
963  .vector_size = sizeof (u32),
964 
965  .format_trace = format_mpls_label_imposition_trace,
966  .n_next_nodes = 1,
967  .next_nodes = {
968  [0] = "ip4-drop",
969  }
970 };
971 
975 {
979 }
980 
982  .name = "ip6-mpls-label-imposition-pipe",
983  .vector_size = sizeof (u32),
984 
985  .format_trace = format_mpls_label_imposition_trace,
986  .n_next_nodes = 1,
987  .next_nodes = {
988  [0] = "ip6-drop",
989  }
990 };
991 
995 {
999 }
1000 
1002  .name = "ethernet-mpls-label-imposition-pipe",
1003  .vector_size = sizeof (u32),
1004 
1005  .format_trace = format_mpls_label_imposition_trace,
1006  .n_next_nodes = 1,
1007  .next_nodes = {
1008  [0] = "error-drop",
1009  }
1010 };
1011 
1014  vlib_frame_t * frame)
1015 {
1019 }
1020 
1022  .name = "mpls-label-imposition-uniform",
1023  .vector_size = sizeof (u32),
1024 
1025  .format_trace = format_mpls_label_imposition_trace,
1026  .n_next_nodes = 1,
1027  .next_nodes = {
1028  [0] = "mpls-drop",
1029  }
1030 };
1031 
1034  vlib_frame_t * frame)
1035 {
1037  DPO_PROTO_IP4,
1039 }
1040 
1042  .name = "ip4-mpls-label-imposition-uniform",
1043  .vector_size = sizeof (u32),
1044 
1045  .format_trace = format_mpls_label_imposition_trace,
1046  .n_next_nodes = 1,
1047  .next_nodes = {
1048  [0] = "ip4-drop",
1049  }
1050 };
1051 
1054  vlib_frame_t * frame)
1055 {
1057  DPO_PROTO_IP6,
1059 }
1060 
1062  .name = "ip6-mpls-label-imposition-uniform",
1063  .vector_size = sizeof (u32),
1064 
1065  .format_trace = format_mpls_label_imposition_trace,
1066  .n_next_nodes = 1,
1067  .next_nodes = {
1068  [0] = "ip6-drop",
1069  }
1070 };
1071 
1074  vlib_frame_t * frame)
1075 {
1079 }
1080 
1082  .name = "ethernet-mpls-label-imposition-uniform",
1083  .vector_size = sizeof (u32),
1084 
1085  .format_trace = format_mpls_label_imposition_trace,
1086  .n_next_nodes = 1,
1087  .next_nodes = {
1088  [0] = "error-drop",
1089  }
1090 };
1091 
1092 
1095  vlib_frame_t * frame)
1096 {
1098  DPO_PROTO_IP4,
1100 }
1101 
1103  .name = "ip4-mpls-label-imposition-pipe-no-ip-ttl-decr",
1104  .vector_size = sizeof (u32),
1105 
1106  .format_trace = format_mpls_label_imposition_trace,
1107  .n_next_nodes = 1,
1108  .next_nodes = {
1109  [0] = "ip4-drop",
1110  }
1111 };
1112 
1115  vlib_frame_t * frame)
1116 {
1118  DPO_PROTO_IP6,
1120 }
1121 
1123  .name = "ip6-mpls-label-imposition-pipe-no-ip-ttl-decr",
1124  .vector_size = sizeof (u32),
1125 
1126  .format_trace = format_mpls_label_imposition_trace,
1127  .n_next_nodes = 1,
1128  .next_nodes = {
1129  [0] = "ip6-drop",
1130  }
1131 };
1132 
1135  vlib_frame_t * frame)
1136 {
1138  DPO_PROTO_IP4,
1141 }
1142 
1144  .name = "ip4-mpls-label-imposition-uniform-no-ip-ttl-decr",
1145  .vector_size = sizeof (u32),
1146 
1147  .format_trace = format_mpls_label_imposition_trace,
1148  .n_next_nodes = 1,
1149  .next_nodes = {
1150  [0] = "ip4-drop",
1151  }
1152 };
1153 
1156  vlib_frame_t * frame)
1157 {
1159  DPO_PROTO_IP6,
1162 }
1163 
1165  .name = "ip6-mpls-label-imposition-uniform-no-ip-ttl-decr",
1166  .vector_size = sizeof (u32),
1167 
1168  .format_trace = format_mpls_label_imposition_trace,
1169  .n_next_nodes = 1,
1170  .next_nodes = {
1171  [0] = "ip6-drop",
1172  }
1173 };
1174 
1175 
1176 #ifndef CLIB_MARCH_VARIANT
1177 static void
1179 {
1180  fib_show_memory_usage("MPLS label",
1181  pool_elts(mpls_label_dpo_pool),
1182  pool_len(mpls_label_dpo_pool),
1183  sizeof(mpls_label_dpo_t));
1184 }
1185 
1186 /**
1187  * Interpose a label DPO. used in the FIB unit tests
1188  */
1189 static void
1191  const dpo_id_t *parent,
1192  dpo_id_t *clone)
1193 {
1194  mpls_label_dpo_t *mld, *mld_clone;
1195 
1196  mld_clone = mpls_label_dpo_alloc();
1197  mld = mpls_label_dpo_get(original->dpoi_index);
1198 
1199  mld_clone->mld_locks = 0;
1200  clib_memcpy_fast(&mld_clone->mld_hdr,
1201  &mld->mld_hdr,
1202  sizeof(mld_clone->mld_hdr));
1203  mld_clone->mld_payload_proto = mld->mld_payload_proto;
1204  mld_clone->mld_n_labels = mld->mld_n_labels;
1205  mld_clone->mld_n_hdr_bytes = mld->mld_n_hdr_bytes;
1206 
1208  mld_clone->mld_payload_proto,
1209  &mld_clone->mld_dpo,
1210  parent);
1211 
1212  dpo_set(clone,
1213  mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NONE],
1214  mld_clone->mld_payload_proto,
1215  mpls_label_dpo_get_index(mld_clone));
1216 }
1217 
1218 static u16
1220 {
1221  mpls_label_dpo_t *mld;
1222 
1223  mld = mpls_label_dpo_get(dpo->dpoi_index);
1224 
1225  /* return the parent's MTU minus the amount of header
1226  * this DPO imposes */
1227  return (dpo_get_mtu (&mld->mld_dpo) - sizeof(mpls_label_t) * mld->mld_n_labels);
1228 }
1229 
1230 const static dpo_vft_t mld_vft = {
1232  .dv_unlock = mpls_label_dpo_unlock,
1233  .dv_format = format_mpls_label_dpo,
1234  .dv_mem_show = mpls_label_dpo_mem_show,
1235  .dv_mk_interpose = mpls_label_interpose,
1236  .dv_get_mtu = mpls_label_dpo_get_mtu,
1237 };
1238 
1239 const static char* const mpls_label_imp_pipe_ip4_nodes[] =
1240 {
1241  "ip4-mpls-label-imposition-pipe",
1242  NULL,
1243 };
1244 const static char* const mpls_label_imp_pipe_ip6_nodes[] =
1245 {
1246  "ip6-mpls-label-imposition-pipe",
1247  NULL,
1248 };
1249 const static char* const mpls_label_imp_pipe_mpls_nodes[] =
1250 {
1251  "mpls-label-imposition-pipe",
1252  NULL,
1253 };
1254 const static char* const mpls_label_imp_pipe_ethernet_nodes[] =
1255 {
1256  "ethernet-mpls-label-imposition-pipe",
1257  NULL,
1258 };
1259 
1260 const static char* const * const mpls_label_imp_pipe_nodes[DPO_PROTO_NUM] =
1261 {
1266 };
1267 
1268 const static char* const mpls_label_imp_uniform_ip4_nodes[] =
1269 {
1270  "ip4-mpls-label-imposition-uniform",
1271  NULL,
1272 };
1273 const static char* const mpls_label_imp_uniform_ip6_nodes[] =
1274 {
1275  "ip6-mpls-label-imposition-uniform",
1276  NULL,
1277 };
1278 const static char* const mpls_label_imp_uniform_mpls_nodes[] =
1279 {
1280  "mpls-label-imposition-uniform",
1281  NULL,
1282 };
1283 const static char* const mpls_label_imp_uniform_ethernet_nodes[] =
1284 {
1285  "ethernet-mpls-label-imposition-uniform",
1286  NULL,
1287 };
1288 
1289 const static char* const * const mpls_label_imp_uniform_nodes[DPO_PROTO_NUM] =
1290 {
1295 };
1296 
1298 {
1299  "ip4-mpls-label-imposition-pipe-no-ip-ttl-decr",
1300  NULL,
1301 };
1303 {
1304  "ip6-mpls-label-imposition-pipe-no-ip-ttl-decr",
1305  NULL,
1306 };
1307 
1308 const static char* const * const mpls_label_imp_pipe_no_ip_tll_decr_nodes[DPO_PROTO_NUM] =
1309 {
1312 };
1313 
1315 {
1316  "ip4-mpls-label-imposition-uniform-no-ip-ttl-decr",
1317  NULL,
1318 };
1320 {
1321  "ip6-mpls-label-imposition-uniform-no-ip-ttl-decr",
1322  NULL,
1323 };
1324 
1326 {
1329 };
1330 
1331 void
1333 {
1335  dpo_register_new_type(&mld_vft,
1338  dpo_register_new_type(&mld_vft,
1341  dpo_register_new_type(&mld_vft,
1345  dpo_register_new_type(&mld_vft,
1347 }
1348 
1349 dpo_type_t
1351 {
1352  return (mpls_label_dpo_types[flags]);
1353 }
1354 #endif /* CLIB_MARCH_VARIANT */
1355 
1356 // clang-format on
static const char *const mpls_label_imp_pipe_ip6_nodes[]
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:133
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:428
#define CLIB_UNUSED(x)
Definition: clib.h:90
static void vnet_mpls_uc_set_s(mpls_label_t *label_exp_s_ttl, u32 eos)
Definition: packet.h:139
A virtual function table regisitered for a DPO type.
Definition: dpo.h:423
#define MPLS_LABEL_DEFAULT_TTL
The Default TTL added to MPLS label headers when no other value is available.
Definition: packet.h:50
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
format_function_t format_mpls_header
Definition: mpls.h:72
vlib_main_t vlib_node_runtime_t vlib_frame_t * from_frame
Definition: esp_encrypt.c:1328
static const char *const mpls_label_imp_pipe_no_ip_tll_decr_ip6_nodes[]
enum mpls_eos_bit_t_ mpls_eos_bit_t
mpls_unicast_header_t hdr
The MPLS header imposed.
#define PREDICT_TRUE(x)
Definition: clib.h:125
static const char *const mpls_label_imp_pipe_no_ip_tll_decr_ip4_nodes[]
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static_always_inline ip_dscp_t ip6_traffic_class_network_order(const ip6_header_t *ip6)
Definition: ip6_packet.h:326
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
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:43
#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:140
static u32 format_get_indent(u8 *s)
Definition: format.h:72
static const char *const mpls_label_imp_pipe_ethernet_nodes[]
u8 * format_mpls_label_dpo(u8 *s, va_list *args)
vlib_node_registration_t ip4_mpls_label_imposition_uniform_no_ip_ttl_decr_node
(constructor) VLIB_REGISTER_NODE (ip4_mpls_label_imposition_uniform_no_ip_ttl_decr_node) ...
#define VLIB_NODE_FN(node)
Definition: node.h:202
static uword mpls_label_imposition_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame, const dpo_proto_t dproto, const mpls_label_dpo_flags_t flags)
#define MPLS_LABEL_DEFAULT_EXP
The Default EXP added to MPLS label headers when no other value is available.
Definition: packet.h:55
u32 mpls_label_t
A label value only, i.e.
Definition: packet.h:26
unsigned char u8
Definition: types.h:56
#define pool_len(p)
Number of elements in pool vector.
Definition: pool.h:139
vlib_node_registration_t ip4_mpls_label_imposition_pipe_no_ip_ttl_decr_node
(constructor) VLIB_REGISTER_NODE (ip4_mpls_label_imposition_pipe_no_ip_ttl_decr_node) ...
unsigned int u32
Definition: types.h:88
const dpo_id_t * drop_dpo_get(dpo_proto_t proto)
Definition: drop_dpo.c:25
static index_t mpls_label_dpo_get_index(mpls_label_dpo_t *mld)
vlib_node_registration_t ip6_mpls_label_imposition_uniform_node
(constructor) VLIB_REGISTER_NODE (ip6_mpls_label_imposition_uniform_node)
static void vnet_mpls_uc_set_exp(mpls_label_t *label_exp_s_ttl, u32 exp)
Definition: packet.h:132
enum dpo_type_t_ dpo_type_t
Common types of data-path objects New types can be dynamically added using dpo_register_new_type() ...
static const char *const mpls_label_imp_uniform_no_ip_tll_decr_ip6_nodes[]
vlib_node_registration_t ip6_mpls_label_imposition_pipe_node
(constructor) VLIB_REGISTER_NODE (ip6_mpls_label_imposition_pipe_node)
#define MPLS_LABEL_DPO_MAX_N_LABELS
Maximum number of labels in one DPO.
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
description fragment has unexpected format
Definition: map.api:433
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:231
static const char *const mpls_label_imp_uniform_mpls_nodes[]
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.
u8 exp
TTL imposed - only valid for uniform LSPs.
static const char *const mpls_label_imp_pipe_mpls_nodes[]
enum mpls_label_dpo_flags_t_ mpls_label_dpo_flags_t
static void vnet_mpls_uc_set_ttl(mpls_label_t *label_exp_s_ttl, u32 ttl)
Definition: packet.h:146
dpo_proto_t mld_payload_proto
The protocol of the payload/packets that are being encapped.
dpo_type_t dpo_register_new_type(const dpo_vft_t *vft, const char *const *const *nodes)
Create and register a new DPO type.
Definition: dpo.c:349
#define FOR_EACH_MPLS_LABEL_DPO_ATTR(_item)
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:172
static const char *const *const mpls_label_imp_uniform_nodes[DPO_PROTO_NUM]
void mpls_label_dpo_create(fib_mpls_label_t *label_stack, mpls_eos_bit_t eos, dpo_proto_t payload_proto, mpls_label_dpo_flags_t flags, const dpo_id_t *parent, dpo_id_t *dpo)
Create an MPLS label object.
unsigned short u16
Definition: types.h:57
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:305
#define PREDICT_FALSE(x)
Definition: clib.h:124
Configuration for each label value in the output-stack.
Definition: fib_types.h:455
vlib_node_registration_t ip4_mpls_label_imposition_pipe_node
(constructor) VLIB_REGISTER_NODE (ip4_mpls_label_imposition_pipe_node)
#define MPLS_LABEL_DPO_ATTR_NAMES
#define dpo_pool_barrier_release(VM, YESNO)
Release barrier sync after dpo pool expansion.
Definition: dpo.h:568
static const char *const *const mpls_label_imp_pipe_nodes[DPO_PROTO_NUM]
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
#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:395
const char * mpls_label_dpo_attr_names[]
Strings for the flags.
vlib_node_registration_t ip6_mpls_label_imposition_uniform_no_ip_ttl_decr_node
(constructor) VLIB_REGISTER_NODE (ip6_mpls_label_imposition_uniform_no_ip_ttl_decr_node) ...
static const char *const mpls_label_imp_uniform_no_ip_tll_decr_ip4_nodes[]
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P with alignment A.
Definition: pool.h:249
#define MPLS_LABEL_DPO_ATTR_MAX
vlib_node_registration_t ip6_mpls_label_imposition_pipe_no_ip_ttl_decr_node
(constructor) VLIB_REGISTER_NODE (ip6_mpls_label_imposition_pipe_no_ip_ttl_decr_node) ...
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:388
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
static const char *const mpls_label_imp_uniform_ethernet_nodes[]
u16 mld_n_hdr_bytes
Cached amount of header bytes to paint.
vlib_node_registration_t mpls_mpls_label_imposition_pipe_node
(constructor) VLIB_REGISTER_NODE (mpls_mpls_label_imposition_pipe_node)
vlib_node_registration_t mpls_mpls_label_imposition_uniform_node
(constructor) VLIB_REGISTER_NODE (mpls_mpls_label_imposition_uniform_node)
u32 index
Definition: flow_types.api:221
#define clib_warning(format, args...)
Definition: error.h:59
static mpls_label_dpo_t * mpls_label_dpo_get(index_t index)
u8 data[]
Packet data.
Definition: buffer.h:204
static const char *const mpls_label_imp_uniform_ip6_nodes[]
static void vnet_mpls_uc_set_label(mpls_label_t *label_exp_s_ttl, u32 value)
Definition: packet.h:125
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:302
mpls_label_t fml_value
The label value.
Definition: fib_types.h:460
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:188
void mpls_label_dpo_module_init(void)
static const char *const mpls_label_imp_uniform_ip4_nodes[]
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:498
u8 mld_n_labels
Size of the label stack.
static void mpls_label_dpo_lock(dpo_id_t *dpo)
#define ASSERT(truth)
static mpls_unicast_header_t * mpls_label_paint_w_ttl(vlib_buffer_t *b0, mpls_label_dpo_t *mld0, u8 ttl0)
Paint on an MPLS label and fixup the TTL.
dpo_id_t mld_dpo
Next DPO in the graph.
u8 ttl
TTL imposed - only valid for uniform LSPs.
ip_dscp_t tos
Definition: ip4_packet.h:96
#define always_inline
Definition: rdma_mlx5dv.h:23
struct mpls_label_imposition_trace_t_ mpls_label_imposition_trace_t
A struct to hold tracing information for the MPLS label imposition node.
static mpls_unicast_header_t * mpls_label_paint_w_ttl_mpls_exp(vlib_buffer_t *b0, mpls_label_dpo_t *mld0, u8 ttl0, u8 exp0)
Paint on an MPLS label and fixup the TTL and EXP bits When the EXP bits are already bit shift to the ...
mpls_label_t label_exp_s_ttl
Definition: packet.h:33
vlib_put_next_frame(vm, node, next_index, 0)
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:276
static_always_inline void * clib_memcpy_fast(void *restrict dst, const void *restrict src, size_t n)
Definition: string.h:92
nat44_ei_hairpin_src_next_t next_index
static const char *const *const mpls_label_imp_uniform_no_ip_tll_decr_nodes[DPO_PROTO_NUM]
u8 * format_dpo_id(u8 *s, va_list *args)
Format a DPO_id_t oject.
Definition: dpo.c:150
mpls_unicast_header_t mld_hdr[MPLS_LABEL_DPO_MAX_N_LABELS]
The MPLS label header to impose.
vlib_node_registration_t ethernet_mpls_label_imposition_uniform_node
(constructor) VLIB_REGISTER_NODE (ethernet_mpls_label_imposition_uniform_node)
vlib_node_registration_t ethernet_mpls_label_imposition_pipe_node
(constructor) VLIB_REGISTER_NODE (ethernet_mpls_label_imposition_pipe_node)
Definition: defs.h:47
#define DPO_PROTO_NUM
Definition: dpo.h:72
u16 dpo_get_mtu(const dpo_id_t *dpo)
Get the MTU DPO.
Definition: dpo.c:401
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:190
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vlib_node_registration_t ip4_mpls_label_imposition_uniform_node
(constructor) VLIB_REGISTER_NODE (ip4_mpls_label_imposition_uniform_node)
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
VLIB buffer representation.
Definition: buffer.h:111
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:301
static mpls_unicast_header_t * mpls_label_paint_w_ttl_exp(vlib_buffer_t *b0, mpls_label_dpo_t *mld0, u8 ttl0, u8 exp0)
Paint on an MPLS label and fixup the TTL and EXP bits.
static void mpls_label_dpo_mem_show(void)
#define dpo_pool_barrier_sync(VM, P, YESNO)
Barrier sync if a dpo pool is about to expand.
Definition: dpo.h:544
mpls_label_dpo_flags_t mld_flags
Flags.
#define vnet_buffer(b)
Definition: buffer.h:437
vl_api_fib_mpls_label_t label_stack[16]
Definition: fib_types.api:128
static u8 * format_mpls_label_imposition_trace(u8 *s, va_list *args)
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:234
u16 mld_locks
Number of locks/users of the label.
u8 fml_exp
EXP bits; valid only at imposition.
Definition: fib_types.h:475
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:628
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:186
static const char *const *const mpls_label_imp_pipe_no_ip_tll_decr_nodes[DPO_PROTO_NUM]
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
dpo_type_t mpls_label_dpo_get_type(mpls_label_dpo_flags_t flags)
enum mpls_label_dpo_attr_t_ mpls_label_dpo_attr_t
Flags present on an MPLS label sourced path-extension.
static mpls_unicast_header_t * mpls_label_paint(vlib_buffer_t *b0, mpls_label_dpo_t *mld0)
static mpls_label_dpo_t * mpls_label_dpo_alloc(void)
u8 * format_mpls_label_dpo_flags(u8 *s, va_list *args)
Format the flags variable.
static void mpls_label_interpose(const dpo_id_t *original, const dpo_id_t *parent, dpo_id_t *clone)
Interpose a label DPO.
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:111
static const char *const mpls_label_imp_pipe_ip4_nodes[]
A representation of an MPLS label for imposition in the data-path.
static dpo_type_t mpls_label_dpo_types[1<< MPLS_LABEL_DPO_ATTR_MAX]
registered DPO types for each of the label sub-types.
static u16 mpls_label_dpo_get_mtu(const dpo_id_t *dpo)
static u8 ip_dscp_to_mpls_exp(ip_dscp_t tos)
When in uniform mode convert an IPv[46] DSCP value to an MPLS EXP value.
Definition: packet.h:60
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:535
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127