FD.io VPP  v19.08.3-2-gbabecb413
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 #ifndef CLIB_MARCH_VARIANT
22 /*
23  * pool of all MPLS Label DPOs
24  */
26 
27 /**
28  * Strings for the flags
29  */
31 
32 /**
33  * registered DPO types for each of the label sub-types. And there's a
34  * subtype for each of the flag combinations.
35  */
37 
38 static mpls_label_dpo_t *
40 {
41  mpls_label_dpo_t *mld;
42  vlib_main_t *vm;
43  u8 did_barrier_sync;
44 
45  dpo_pool_barrier_sync (vm, mpls_label_dpo_pool, did_barrier_sync);
46  pool_get_aligned(mpls_label_dpo_pool, mld, CLIB_CACHE_LINE_BYTES);
47  dpo_pool_barrier_release (vm, did_barrier_sync);
48 
49  clib_memset(mld, 0, sizeof(*mld));
50 
51  dpo_reset(&mld->mld_dpo);
52 
53  return (mld);
54 }
55 
56 static index_t
58 {
59  return (mld - mpls_label_dpo_pool);
60 }
61 
62 void
64  mpls_eos_bit_t eos,
65  dpo_proto_t payload_proto,
67  const dpo_id_t *parent,
68  dpo_id_t *dpo)
69 {
70  mpls_label_dpo_t *mld;
71  dpo_type_t dtype;
72  u32 ii;
73 
74  if ((DPO_PROTO_IP4 != payload_proto) &&
75  (DPO_PROTO_IP6 != payload_proto))
76  {
77  /*
78  * remove unsupported configuration
79  */
81  }
82 
83  mld = mpls_label_dpo_alloc();
84  mld->mld_flags = flags;
85  dtype = mpls_label_dpo_types[flags];
86 
87  if (MPLS_LABEL_DPO_MAX_N_LABELS < vec_len(label_stack))
88  {
89  clib_warning("Label stack size exceeded");
90  dpo_stack(dtype,
91  mld->mld_payload_proto,
92  &mld->mld_dpo,
94  }
95  else
96  {
97  mld->mld_n_labels = vec_len(label_stack);
98  mld->mld_n_hdr_bytes = mld->mld_n_labels * sizeof(mld->mld_hdr[0]);
99  mld->mld_payload_proto = payload_proto;
100 
101  /*
102  * construct label rewrite headers for each value passed.
103  * get the header in network byte order since we will paint it
104  * on a packet in the data-plane
105  */
106  for (ii = 0; ii < mld->mld_n_labels-1; ii++)
107  {
109  label_stack[ii].fml_value);
111  label_stack[ii].fml_exp);
113  MPLS_NON_EOS);
114  if (0 != label_stack[ii].fml_ttl)
115  {
117  label_stack[ii].fml_ttl);
118  }
119  else
120  {
123  }
124  mld->mld_hdr[ii].label_exp_s_ttl =
125  clib_host_to_net_u32(mld->mld_hdr[ii].label_exp_s_ttl);
126  }
127 
128  /*
129  * the inner most label
130  */
131  ii = mld->mld_n_labels-1;
132 
134  label_stack[ii].fml_value);
136  label_stack[ii].fml_exp);
138  if (0 != label_stack[ii].fml_ttl)
139  {
141  label_stack[ii].fml_ttl);
142  }
143  else
144  {
147  }
148  mld->mld_hdr[ii].label_exp_s_ttl =
149  clib_host_to_net_u32(mld->mld_hdr[ii].label_exp_s_ttl);
150 
151  /*
152  * pipe/uniform mode is only supported for the bottom of stack label
153  */
154  if (FIB_MPLS_LSP_MODE_UNIFORM == label_stack[ii].fml_mode)
155  {
157  }
158  else
159  {
161  }
162  dtype = mpls_label_dpo_types[mld->mld_flags];
163 
164  /*
165  * stack this label object on its parent.
166  */
167  dpo_stack(dtype,
168  mld->mld_payload_proto,
169  &mld->mld_dpo,
170  parent);
171  }
172 
173  dpo_set(dpo,
174  dtype,
175  mld->mld_payload_proto,
177 }
178 
179 u8*
180 format_mpls_label_dpo_flags (u8 *s, va_list *args)
181 {
182  mpls_label_dpo_flags_t flags = va_arg (*args, int);
184 
186  {
187  if ((1 << attr) & flags)
188  {
189  s = format(s, "%s,", mpls_label_dpo_attr_names[attr]);
190  }
191  }
192 
193  return (s);
194 }
195 
196 u8*
197 format_mpls_label_dpo (u8 *s, va_list *args)
198 {
199  index_t index = va_arg (*args, index_t);
200  u32 indent = va_arg (*args, u32);
202  mpls_label_dpo_t *mld;
203  u32 ii;
204 
205  if (pool_is_free_index(mpls_label_dpo_pool, index))
206  {
207  /*
208  * the packet trace can be printed after the DPO has been deleted
209  */
210  return (format(s, "mpls-label[???,%d]:", index));
211  }
212 
213  mld = mpls_label_dpo_get(index);
214  s = format(s, "mpls-label[%U@%d]:",
216  (int) mld->mld_flags, index);
217 
218  for (ii = 0; ii < mld->mld_n_labels; ii++)
219  {
220  hdr.label_exp_s_ttl =
221  clib_net_to_host_u32(mld->mld_hdr[ii].label_exp_s_ttl);
222  s = format(s, "%U", format_mpls_header, hdr);
223  }
224 
225  s = format(s, "\n%U", format_white_space, indent);
226  s = format(s, "%U", format_dpo_id, &mld->mld_dpo, indent+2);
227 
228  return (s);
229 }
230 
231 static void
233 {
234  mpls_label_dpo_t *mld;
235 
236  mld = mpls_label_dpo_get(dpo->dpoi_index);
237 
238  mld->mld_locks++;
239 }
240 
241 static void
243 {
244  mpls_label_dpo_t *mld;
245 
246  mld = mpls_label_dpo_get(dpo->dpoi_index);
247 
248  mld->mld_locks--;
249 
250  if (0 == mld->mld_locks)
251  {
252  dpo_reset(&mld->mld_dpo);
253  pool_put(mpls_label_dpo_pool, mld);
254  }
255 }
256 #endif /* CLIB_MARCH_VARIANT */
257 
258 /**
259  * @brief A struct to hold tracing information for the MPLS label imposition
260  * node.
261  */
263 {
264  /**
265  * The MPLS header imposed
266  */
268 
269  /**
270  * TTL imposed - only valid for uniform LSPs
271  */
273 
274  /**
275  * TTL imposed - only valid for uniform LSPs
276  */
279 
282  mpls_label_dpo_t *mld0)
283 {
284  mpls_unicast_header_t *hdr0;
285 
286  vlib_buffer_advance(b0, -(mld0->mld_n_hdr_bytes));
287 
288  hdr0 = vlib_buffer_get_current(b0);
289 
290  if (1 == mld0->mld_n_labels)
291  {
292  /* optimise for the common case of one label */
293  *hdr0 = mld0->mld_hdr[0];
294  }
295  else
296  {
297  clib_memcpy_fast(hdr0, mld0->mld_hdr, mld0->mld_n_hdr_bytes);
298  hdr0 = hdr0 + (mld0->mld_n_labels - 1);
299  }
300 
301  return (hdr0);
302 }
303 
304 /**
305  * Paint on an MPLS label and fixup the TTL
306  */
309  mpls_label_dpo_t *mld0,
310  u8 ttl0)
311 {
312  mpls_unicast_header_t *hdr0;
313 
314  hdr0 = mpls_label_paint(b0, mld0);
315 
316  /* fixup the TTL for the inner most label */
317  ((char*)hdr0)[3] = ttl0;
318 
319  return (hdr0);
320 }
321 
322 /**
323  * Paint on an MPLS label and fixup the TTL and EXP bits.
324  */
327  mpls_label_dpo_t *mld0,
328  u8 ttl0,
329  u8 exp0)
330 {
331  mpls_unicast_header_t *hdr0;
332 
333  hdr0 = mpls_label_paint_w_ttl(b0, mld0, ttl0);
334 
335  /* fixup the EXP for the inner most label */
336  ((char*)hdr0)[2] |= (exp0 << 1);
337 
338  return (hdr0);
339 }
340 
341 /**
342  * Paint on an MPLS label and fixup the TTL and EXP bits
343  * When the EXP bits are *already* bit shift to the correct place in
344  * in the 2nd byte (i.e. they were read from another label)
345  */
348  mpls_label_dpo_t *mld0,
349  u8 ttl0,
350  u8 exp0)
351 {
352  mpls_unicast_header_t *hdr0;
353 
354  hdr0 = mpls_label_paint_w_ttl(b0, mld0, ttl0);
355 
356  /* fixup the EXP for the inner most label */
357  ((char*)hdr0)[2] |= exp0;
358 
359  return (hdr0);
360 }
361 
364  vlib_node_runtime_t * node,
365  vlib_frame_t * from_frame,
366  const dpo_proto_t dproto,
368 {
369  u32 n_left_from, next_index, * from, * to_next;
370 
371  from = vlib_frame_vector_args (from_frame);
372  n_left_from = from_frame->n_vectors;
373 
374  next_index = node->cached_next_index;
375 
376  while (n_left_from > 0)
377  {
378  u32 n_left_to_next;
379 
380  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
381 
382  while (n_left_from >= 8 && n_left_to_next >= 4)
383  {
384  u32 bi0, mldi0, bi1, mldi1, bi2, mldi2, bi3, mldi3;
385  mpls_unicast_header_t *hdr0, *hdr1, *hdr2, *hdr3;
386  mpls_label_dpo_t *mld0, *mld1, *mld2, *mld3;
387  vlib_buffer_t * b0, *b1, * b2, *b3;
388  u32 next0, next1, next2, next3;
389  u8 ttl0, ttl1, ttl2, ttl3;
390  u8 exp0, exp1, exp2, exp3;
391 
392  bi0 = to_next[0] = from[0];
393  bi1 = to_next[1] = from[1];
394  bi2 = to_next[2] = from[2];
395  bi3 = to_next[3] = from[3];
396 
397  /* Prefetch next iteration. */
398  {
399  vlib_buffer_t * p2, * p3, *p4, *p5;
400 
401  p2 = vlib_get_buffer (vm, from[2]);
402  p3 = vlib_get_buffer (vm, from[3]);
403  p4 = vlib_get_buffer (vm, from[4]);
404  p5 = vlib_get_buffer (vm, from[5]);
405 
406  vlib_prefetch_buffer_header (p2, STORE);
407  vlib_prefetch_buffer_header (p3, STORE);
408  vlib_prefetch_buffer_header (p4, STORE);
409  vlib_prefetch_buffer_header (p5, STORE);
410 
411  CLIB_PREFETCH (p2->data, sizeof (hdr0[0]), STORE);
412  CLIB_PREFETCH (p3->data, sizeof (hdr0[0]), STORE);
413  CLIB_PREFETCH (p4->data, sizeof (hdr0[0]), STORE);
414  CLIB_PREFETCH (p5->data, sizeof (hdr0[0]), STORE);
415  }
416 
417  from += 4;
418  to_next += 4;
419  n_left_from -= 4;
420  n_left_to_next -= 4;
421 
422  b0 = vlib_get_buffer (vm, bi0);
423  b1 = vlib_get_buffer (vm, bi1);
424  b2 = vlib_get_buffer (vm, bi2);
425  b3 = vlib_get_buffer (vm, bi3);
426 
427  /* dst lookup was done by ip4 lookup */
428  mldi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
429  mldi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
430  mldi2 = vnet_buffer(b2)->ip.adj_index[VLIB_TX];
431  mldi3 = vnet_buffer(b3)->ip.adj_index[VLIB_TX];
432  mld0 = mpls_label_dpo_get(mldi0);
433  mld1 = mpls_label_dpo_get(mldi1);
434  mld2 = mpls_label_dpo_get(mldi2);
435  mld3 = mpls_label_dpo_get(mldi3);
436 
437  if (DPO_PROTO_MPLS != dproto)
438  {
439  /*
440  * These are the non-MPLS payload imposition cases
441  */
442  if (DPO_PROTO_IP4 == dproto)
443  {
448 
449  if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
450  {
451  /*
452  * decrement the TTL on ingress to the LSP
453  */
454  u32 checksum0;
455  u32 checksum1;
456  u32 checksum2;
457  u32 checksum3;
458 
459  checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
460  checksum1 = ip1->checksum + clib_host_to_net_u16 (0x0100);
461  checksum2 = ip2->checksum + clib_host_to_net_u16 (0x0100);
462  checksum3 = ip3->checksum + clib_host_to_net_u16 (0x0100);
463 
464  checksum0 += checksum0 >= 0xffff;
465  checksum1 += checksum1 >= 0xffff;
466  checksum2 += checksum2 >= 0xffff;
467  checksum3 += checksum3 >= 0xffff;
468 
469  ip0->checksum = checksum0;
470  ip1->checksum = checksum1;
471  ip2->checksum = checksum2;
472  ip3->checksum = checksum3;
473 
474  ip0->ttl -= 1;
475  ip1->ttl -= 1;
476  ip2->ttl -= 1;
477  ip3->ttl -= 1;
478  }
479 
481  {
482  ttl1 = ip1->ttl;
483  ttl0 = ip0->ttl;
484  ttl3 = ip3->ttl;
485  ttl2 = ip2->ttl;
486  /* by default copy the 3 most significant bits */
487  exp0 = ip_dscp_to_mpls_exp(ip0->tos);
488  exp1 = ip_dscp_to_mpls_exp(ip1->tos);
489  exp2 = ip_dscp_to_mpls_exp(ip2->tos);
490  exp3 = ip_dscp_to_mpls_exp(ip3->tos);
491  }
492 
493  /* save the payload proto information in mpls opaque */
494  vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP4;
495  vnet_buffer(b1)->mpls.pyld_proto = DPO_PROTO_IP4;
496  vnet_buffer(b2)->mpls.pyld_proto = DPO_PROTO_IP4;
497  vnet_buffer(b3)->mpls.pyld_proto = DPO_PROTO_IP4;
498  }
499  else if (DPO_PROTO_IP6 == dproto)
500  {
501  /*
502  * decrement the TTL on ingress to the LSP
503  */
508 
509  if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
510  {
511  ip0->hop_limit -= 1;
512  ip1->hop_limit -= 1;
513  ip2->hop_limit -= 1;
514  ip3->hop_limit -= 1;
515  }
517  {
518  ttl0 = ip0->hop_limit;
519  ttl1 = ip1->hop_limit;
520  ttl2 = ip2->hop_limit;
521  ttl3 = ip3->hop_limit;
522  /* by default copy the 3 most significant bits */
523  exp0 = ip_dscp_to_mpls_exp(
525  exp1 = ip_dscp_to_mpls_exp(
527  exp2 = ip_dscp_to_mpls_exp(
529  exp3 = ip_dscp_to_mpls_exp(
531  }
532 
533  /* save the payload proto information in mpls opaque */
534  vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP6;
535  vnet_buffer(b1)->mpls.pyld_proto = DPO_PROTO_IP6;
536  vnet_buffer(b2)->mpls.pyld_proto = DPO_PROTO_IP6;
537  vnet_buffer(b3)->mpls.pyld_proto = DPO_PROTO_IP6;
538  }
539  else
540  {
541  /*
542  * nothing to change in the ethernet header
543  */
544  ttl0 = ttl1 = ttl2 = ttl3 = MPLS_LABEL_DEFAULT_TTL;
545  exp0 = exp1 = exp2 = exp3 = MPLS_LABEL_DEFAULT_EXP;
546  }
547  /*
548  * These are the non-MPLS payload imposition cases.
549  * Based on the LSP mode either, for uniform, copy down the TTL
550  * and EXP from the payload or, for pipe mode, slap on the value
551  * requested from config
552  */
554  {
555  hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
556  hdr1 = mpls_label_paint_w_ttl_exp(b1, mld1, ttl1, exp1);
557  hdr2 = mpls_label_paint_w_ttl_exp(b2, mld2, ttl2, exp2);
558  hdr3 = mpls_label_paint_w_ttl_exp(b3, mld3, ttl3, exp3);
559  }
560  else
561  {
562  hdr0 = mpls_label_paint(b0, mld0);
563  hdr1 = mpls_label_paint(b1, mld1);
564  hdr2 = mpls_label_paint(b2, mld2);
565  hdr3 = mpls_label_paint(b3, mld3);
566  }
567  }
568  else
569  {
570  /*
571  * else, the packet to be encapped is an MPLS packet
572  * there are two cases to consider:
573  * 1 - this is an MPLS label swap at an LSP midpoint.
574  * recognisable because mpls.first = 1. In this case the
575  * TTL must be set to the current value -1.
576  * 2 - The MPLS packet is recursing (or being injected into)
577  * this LSP, in which case the pipe/uniform rules apply
578  *
579  */
580  if (PREDICT_TRUE(vnet_buffer(b0)->mpls.first))
581  {
582  /*
583  * The first label to be imposed on the packet. this is a
584  * label swap.in which case we stashed the TTL and EXP bits
585  * in the packet in the lookup node
586  */
587  ASSERT(0 != vnet_buffer (b0)->mpls.ttl);
588 
589  ttl0 = vnet_buffer(b0)->mpls.ttl - 1;
590  exp0 = vnet_buffer(b0)->mpls.exp;
591  hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
592  }
593  else
594  {
595  /*
596  * not the first label. implying we are recusring down a
597  * chain of output labels. Each layer is considered a new
598  * LSP - hence the TTL/EXP are pipe/uniform handled
599  */
601  {
602  hdr0 = vlib_buffer_get_current(b0);
603  ttl0 = ((u8*)hdr0)[3];
604  exp0 = ((u8*)hdr0)[2] & 0xe;
605  hdr0 = mpls_label_paint_w_ttl_mpls_exp(b0, mld0, ttl0, exp0);
606  }
607  else
608  {
609  hdr0 = mpls_label_paint(b0, mld0);
610  }
611  }
612  if (PREDICT_TRUE(vnet_buffer(b1)->mpls.first))
613  {
614  ASSERT(0 != vnet_buffer (b1)->mpls.ttl);
615 
616  ttl1 = vnet_buffer(b1)->mpls.ttl - 1;
617  exp1 = vnet_buffer(b1)->mpls.exp;
618  hdr1 = mpls_label_paint_w_ttl_exp(b1, mld1, ttl1, exp1);
619  }
620  else
621  {
623  {
624  hdr1 = vlib_buffer_get_current(b1);
625  ttl1 = ((u8*)hdr1)[3];
626  exp1 = ((u8*)hdr1)[2] & 0xe;
627  hdr1 = mpls_label_paint_w_ttl_mpls_exp(b1, mld1, ttl1, exp1);
628  }
629  else
630  {
631  hdr1 = mpls_label_paint(b1, mld1);
632  }
633  }
634  if (PREDICT_TRUE(vnet_buffer(b2)->mpls.first))
635  {
636  ASSERT(0 != vnet_buffer (b2)->mpls.ttl);
637 
638  ttl2 = vnet_buffer(b2)->mpls.ttl - 1;
639  exp2 = vnet_buffer(b2)->mpls.exp;
640  hdr2 = mpls_label_paint_w_ttl_exp(b2, mld2, ttl2, exp2);
641  }
642  else
643  {
645  {
646  hdr2 = vlib_buffer_get_current(b2);
647  ttl2 = ((u8*)hdr2)[3];
648  exp2 = ((u8*)hdr2)[2] & 0xe;
649  hdr2 = mpls_label_paint_w_ttl_mpls_exp(b2, mld2, ttl2, exp2);
650  }
651  else
652  {
653  hdr2 = mpls_label_paint(b2, mld2);
654  }
655  }
656  if (PREDICT_TRUE(vnet_buffer(b3)->mpls.first))
657  {
658  ASSERT(0 != vnet_buffer (b3)->mpls.ttl);
659 
660  ttl3 = vnet_buffer(b3)->mpls.ttl - 1;
661  exp3 = vnet_buffer(b3)->mpls.exp;
662  hdr3 = mpls_label_paint_w_ttl_exp(b3, mld3, ttl3, exp3);
663  }
664  else
665  {
667  {
668  hdr3 = vlib_buffer_get_current(b3);
669  ttl3 = ((u8*)hdr3)[3];
670  exp3 = ((u8*)hdr3)[2] & 0xe;
671  hdr3 = mpls_label_paint_w_ttl_mpls_exp(b3, mld3, ttl3, exp3);
672  }
673  else
674  {
675  hdr3 = mpls_label_paint(b3, mld3);
676  }
677  }
678 
679  vnet_buffer(b0)->mpls.first = 0;
680  vnet_buffer(b1)->mpls.first = 0;
681  vnet_buffer(b2)->mpls.first = 0;
682  vnet_buffer(b3)->mpls.first = 0;
683  }
684 
685  next0 = mld0->mld_dpo.dpoi_next_node;
686  next1 = mld1->mld_dpo.dpoi_next_node;
687  next2 = mld2->mld_dpo.dpoi_next_node;
688  next3 = mld3->mld_dpo.dpoi_next_node;
689 
690  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mld0->mld_dpo.dpoi_index;
691  vnet_buffer(b1)->ip.adj_index[VLIB_TX] = mld1->mld_dpo.dpoi_index;
692  vnet_buffer(b2)->ip.adj_index[VLIB_TX] = mld2->mld_dpo.dpoi_index;
693  vnet_buffer(b3)->ip.adj_index[VLIB_TX] = mld3->mld_dpo.dpoi_index;
694 
695  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
696  {
698  vlib_add_trace (vm, node, b0, sizeof (*tr));
699  tr->hdr = *hdr0;
701  {
702  tr->ttl = ttl0;
703  tr->exp = exp0;
704  }
705  else
706  {
707  tr->ttl = tr->exp = 0;
708  }
709  }
710  if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
711  {
713  vlib_add_trace (vm, node, b1, sizeof (*tr));
714  tr->hdr = *hdr1;
716  {
717  tr->ttl = ttl1;
718  tr->exp = exp1;
719  }
720  else
721  {
722  tr->ttl = tr->exp = 0;
723  }
724  }
725  if (PREDICT_FALSE(b2->flags & VLIB_BUFFER_IS_TRACED))
726  {
728  vlib_add_trace (vm, node, b2, sizeof (*tr));
729  tr->hdr = *hdr2;
731  {
732  tr->ttl = ttl2;
733  tr->exp = exp2;
734  }
735  else
736  {
737  tr->ttl = tr->exp = 0;
738  }
739  }
740  if (PREDICT_FALSE(b3->flags & VLIB_BUFFER_IS_TRACED))
741  {
743  vlib_add_trace (vm, node, b3, sizeof (*tr));
744  tr->hdr = *hdr3;
746  {
747  tr->ttl = ttl3;
748  tr->exp = exp3;
749  }
750  else
751  {
752  tr->ttl = tr->exp = 0;
753  }
754  }
755 
756  vlib_validate_buffer_enqueue_x4(vm, node, next_index, to_next,
757  n_left_to_next,
758  bi0, bi1, bi2, bi3,
759  next0, next1, next2, next3);
760  }
761 
762  while (n_left_from > 0 && n_left_to_next > 0)
763  {
764  mpls_unicast_header_t *hdr0;
765  mpls_label_dpo_t *mld0;
766  vlib_buffer_t * b0;
767  u32 bi0, mldi0;
768  u8 ttl0, exp0;
769  u32 next0;
770 
771  bi0 = from[0];
772  to_next[0] = bi0;
773  from += 1;
774  to_next += 1;
775  n_left_from -= 1;
776  n_left_to_next -= 1;
777 
778  b0 = vlib_get_buffer (vm, bi0);
779 
780  /* dst lookup was done by ip4 lookup */
781  mldi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
782  mld0 = mpls_label_dpo_get(mldi0);
783 
784  if (DPO_PROTO_MPLS != dproto)
785  {
786  if (DPO_PROTO_IP4 == dproto)
787  {
788  /*
789  * decrement the TTL on ingress to the LSP
790  */
792  if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
793  {
794  u32 checksum0;
795 
796  checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
797  checksum0 += checksum0 >= 0xffff;
798 
799  ip0->checksum = checksum0;
800  ip0->ttl -= 1;
801  }
803  {
804  ttl0 = ip0->ttl;
805  exp0 = ip_dscp_to_mpls_exp(ip0->tos);
806  }
807 
808  /* save the payload proto information in mpls opaque */
809  vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP4;
810  }
811  else if (DPO_PROTO_IP6 == dproto)
812  {
813  /*
814  * decrement the TTL on ingress to the LSP
815  */
817 
818  if (!(MPLS_LABEL_DPO_FLAG_NO_IP_TTL_DECR & flags))
819  {
820  ip0->hop_limit -= 1;
821  }
823  {
824  ttl0 = ip0->hop_limit;
825  exp0 = ip_dscp_to_mpls_exp(
827  }
828 
829  /* save the payload proto information in mpls opaque */
830  vnet_buffer(b0)->mpls.pyld_proto = DPO_PROTO_IP6;
831  }
832  else
833  {
834  /*
835  * nothing to change in the ethernet header
836  */
837  ttl0 = MPLS_LABEL_DEFAULT_TTL;
838  exp0 = MPLS_LABEL_DEFAULT_EXP;
839  }
840 
841  /*
842  * These are the non-MPLS payload imposition cases.
843  * Based on the LSP mode either, for uniform, copy down the TTL
844  * from the payload or, for pipe mode, slap on the value
845  * requested from config
846  */
848  {
849  hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
850  }
851  else
852  {
853  hdr0 = mpls_label_paint(b0, mld0);
854  }
855  }
856  else
857  {
858  if (PREDICT_TRUE(vnet_buffer(b0)->mpls.first))
859  {
860  ASSERT(0 != vnet_buffer (b0)->mpls.ttl);
861 
862  ttl0 = vnet_buffer(b0)->mpls.ttl - 1;
863  exp0 = vnet_buffer(b0)->mpls.exp;
864  hdr0 = mpls_label_paint_w_ttl_exp(b0, mld0, ttl0, exp0);
865  }
866  else
867  {
869  {
870  hdr0 = vlib_buffer_get_current(b0);
871  ttl0 = ((u8*)hdr0)[3];
872  exp0 = ((u8*)hdr0)[2] & 0xe;
873  hdr0 = mpls_label_paint_w_ttl_mpls_exp(b0, mld0, ttl0, exp0);
874  }
875  else
876  {
877  hdr0 = mpls_label_paint(b0, mld0);
878  }
879  }
880 
881  vnet_buffer(b0)->mpls.first = 0;
882  }
883 
884  next0 = mld0->mld_dpo.dpoi_next_node;
885  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mld0->mld_dpo.dpoi_index;
886 
887  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
888  {
890  vlib_add_trace (vm, node, b0, sizeof (*tr));
891  tr->hdr = *hdr0;
893  {
894  tr->ttl = ttl0;
895  tr->exp = exp0;
896  }
897  else
898  {
899  tr->ttl = tr->exp = 0;
900  }
901  }
902 
903  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
904  n_left_to_next, bi0, next0);
905  }
906  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
907  }
908  return from_frame->n_vectors;
909 }
910 
911 static u8 *
913 {
914  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
915  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
918  u32 indent;
919 
920  t = va_arg (*args, mpls_label_imposition_trace_t *);
921  indent = format_get_indent (s);
922  hdr.label_exp_s_ttl = clib_net_to_host_u32(t->hdr.label_exp_s_ttl);
923 
924  s = format (s, "%Umpls-header:%U",
925  format_white_space, indent,
926  format_mpls_header, hdr);
927  return (s);
928 }
929 
931  vlib_node_runtime_t * node,
932  vlib_frame_t * frame)
933 {
934  return (mpls_label_imposition_inline(vm, node, frame,
937 }
938 
940  .name = "mpls-label-imposition-pipe",
941  .vector_size = sizeof (u32),
942 
943  .format_trace = format_mpls_label_imposition_trace,
944  .n_next_nodes = 1,
945  .next_nodes = {
946  [0] = "mpls-drop",
947  }
948 };
949 
951  vlib_node_runtime_t * node,
952  vlib_frame_t * frame)
953 {
954  return (mpls_label_imposition_inline(vm, node, frame,
957 }
958 
960  .name = "ip4-mpls-label-imposition-pipe",
961  .vector_size = sizeof (u32),
962 
963  .format_trace = format_mpls_label_imposition_trace,
964  .n_next_nodes = 1,
965  .next_nodes = {
966  [0] = "ip4-drop",
967  }
968 };
969 
971  vlib_node_runtime_t * node,
972  vlib_frame_t * frame)
973 {
974  return (mpls_label_imposition_inline(vm, node, frame,
977 }
978 
980  .name = "ip6-mpls-label-imposition-pipe",
981  .vector_size = sizeof (u32),
982 
983  .format_trace = format_mpls_label_imposition_trace,
984  .n_next_nodes = 1,
985  .next_nodes = {
986  [0] = "ip6-drop",
987  }
988 };
989 
991  vlib_node_runtime_t * node,
992  vlib_frame_t * frame)
993 {
994  return (mpls_label_imposition_inline(vm, node, frame,
997 }
998 
1000  .name = "ethernet-mpls-label-imposition-pipe",
1001  .vector_size = sizeof (u32),
1002 
1003  .format_trace = format_mpls_label_imposition_trace,
1004  .n_next_nodes = 1,
1005  .next_nodes = {
1006  [0] = "error-drop",
1007  }
1008 };
1009 
1011  vlib_node_runtime_t * node,
1012  vlib_frame_t * frame)
1013 {
1014  return (mpls_label_imposition_inline(vm, node, frame,
1017 }
1018 
1020  .name = "mpls-label-imposition-uniform",
1021  .vector_size = sizeof (u32),
1022 
1023  .format_trace = format_mpls_label_imposition_trace,
1024  .n_next_nodes = 1,
1025  .next_nodes = {
1026  [0] = "mpls-drop",
1027  }
1028 };
1029 
1031  vlib_node_runtime_t * node,
1032  vlib_frame_t * frame)
1033 {
1034  return (mpls_label_imposition_inline(vm, node, frame,
1035  DPO_PROTO_IP4,
1037 }
1038 
1040  .name = "ip4-mpls-label-imposition-uniform",
1041  .vector_size = sizeof (u32),
1042 
1043  .format_trace = format_mpls_label_imposition_trace,
1044  .n_next_nodes = 1,
1045  .next_nodes = {
1046  [0] = "ip4-drop",
1047  }
1048 };
1049 
1051  vlib_node_runtime_t * node,
1052  vlib_frame_t * frame)
1053 {
1054  return (mpls_label_imposition_inline(vm, node, frame,
1055  DPO_PROTO_IP6,
1057 }
1058 
1060  .name = "ip6-mpls-label-imposition-uniform",
1061  .vector_size = sizeof (u32),
1062 
1063  .format_trace = format_mpls_label_imposition_trace,
1064  .n_next_nodes = 1,
1065  .next_nodes = {
1066  [0] = "ip6-drop",
1067  }
1068 };
1069 
1071  vlib_node_runtime_t * node,
1072  vlib_frame_t * frame)
1073 {
1074  return (mpls_label_imposition_inline(vm, node, frame,
1077 }
1078 
1080  .name = "ethernet-mpls-label-imposition-uniform",
1081  .vector_size = sizeof (u32),
1082 
1083  .format_trace = format_mpls_label_imposition_trace,
1084  .n_next_nodes = 1,
1085  .next_nodes = {
1086  [0] = "error-drop",
1087  }
1088 };
1089 
1090 
1092  vlib_node_runtime_t * node,
1093  vlib_frame_t * frame)
1094 {
1095  return (mpls_label_imposition_inline(vm, node, frame,
1096  DPO_PROTO_IP4,
1098 }
1099 
1101  .name = "ip4-mpls-label-imposition-pipe-no-ip-ttl-decr",
1102  .vector_size = sizeof (u32),
1103 
1104  .format_trace = format_mpls_label_imposition_trace,
1105  .n_next_nodes = 1,
1106  .next_nodes = {
1107  [0] = "ip4-drop",
1108  }
1109 };
1110 
1112  vlib_node_runtime_t * node,
1113  vlib_frame_t * frame)
1114 {
1115  return (mpls_label_imposition_inline(vm, node, frame,
1116  DPO_PROTO_IP6,
1118 }
1119 
1121  .name = "ip6-mpls-label-imposition-pipe-no-ip-ttl-decr",
1122  .vector_size = sizeof (u32),
1123 
1124  .format_trace = format_mpls_label_imposition_trace,
1125  .n_next_nodes = 1,
1126  .next_nodes = {
1127  [0] = "ip6-drop",
1128  }
1129 };
1130 
1132  vlib_node_runtime_t * node,
1133  vlib_frame_t * frame)
1134 {
1135  return (mpls_label_imposition_inline(vm, node, frame,
1136  DPO_PROTO_IP4,
1139 }
1140 
1142  .name = "ip4-mpls-label-imposition-uniform-no-ip-ttl-decr",
1143  .vector_size = sizeof (u32),
1144 
1145  .format_trace = format_mpls_label_imposition_trace,
1146  .n_next_nodes = 1,
1147  .next_nodes = {
1148  [0] = "ip4-drop",
1149  }
1150 };
1151 
1153  vlib_node_runtime_t * node,
1154  vlib_frame_t * frame)
1155 {
1156  return (mpls_label_imposition_inline(vm, node, frame,
1157  DPO_PROTO_IP6,
1160 }
1161 
1163  .name = "ip6-mpls-label-imposition-uniform-no-ip-ttl-decr",
1164  .vector_size = sizeof (u32),
1165 
1166  .format_trace = format_mpls_label_imposition_trace,
1167  .n_next_nodes = 1,
1168  .next_nodes = {
1169  [0] = "ip6-drop",
1170  }
1171 };
1172 
1173 
1174 #ifndef CLIB_MARCH_VARIANT
1175 static void
1177 {
1178  fib_show_memory_usage("MPLS label",
1179  pool_elts(mpls_label_dpo_pool),
1180  pool_len(mpls_label_dpo_pool),
1181  sizeof(mpls_label_dpo_t));
1182 }
1183 
1184 /**
1185  * Interpose a label DPO. used in the FIB unit tests
1186  */
1187 static void
1189  const dpo_id_t *parent,
1190  dpo_id_t *clone)
1191 {
1192  mpls_label_dpo_t *mld, *mld_clone;
1193 
1194  mld_clone = mpls_label_dpo_alloc();
1195  mld = mpls_label_dpo_get(original->dpoi_index);
1196 
1197  mld_clone->mld_locks = 0;
1198  clib_memcpy_fast(&mld_clone->mld_hdr,
1199  &mld->mld_hdr,
1200  sizeof(mld_clone->mld_hdr));
1201  mld_clone->mld_payload_proto = mld->mld_payload_proto;
1202  mld_clone->mld_n_labels = mld->mld_n_labels;
1203  mld_clone->mld_n_hdr_bytes = mld->mld_n_hdr_bytes;
1204 
1206  mld_clone->mld_payload_proto,
1207  &mld_clone->mld_dpo,
1208  parent);
1209 
1210  dpo_set(clone,
1211  mpls_label_dpo_types[MPLS_LABEL_DPO_FLAG_NONE],
1212  mld_clone->mld_payload_proto,
1213  mpls_label_dpo_get_index(mld_clone));
1214 }
1215 
1216 const static dpo_vft_t mld_vft = {
1218  .dv_unlock = mpls_label_dpo_unlock,
1219  .dv_format = format_mpls_label_dpo,
1220  .dv_mem_show = mpls_label_dpo_mem_show,
1221  .dv_mk_interpose = mpls_label_interpose,
1222 };
1223 
1224 const static char* const mpls_label_imp_pipe_ip4_nodes[] =
1225 {
1226  "ip4-mpls-label-imposition-pipe",
1227  NULL,
1228 };
1229 const static char* const mpls_label_imp_pipe_ip6_nodes[] =
1230 {
1231  "ip6-mpls-label-imposition-pipe",
1232  NULL,
1233 };
1234 const static char* const mpls_label_imp_pipe_mpls_nodes[] =
1235 {
1236  "mpls-label-imposition-pipe",
1237  NULL,
1238 };
1239 const static char* const mpls_label_imp_pipe_ethernet_nodes[] =
1240 {
1241  "ethernet-mpls-label-imposition-pipe",
1242  NULL,
1243 };
1244 
1245 const static char* const * const mpls_label_imp_pipe_nodes[DPO_PROTO_NUM] =
1246 {
1251 };
1252 
1253 const static char* const mpls_label_imp_uniform_ip4_nodes[] =
1254 {
1255  "ip4-mpls-label-imposition-uniform",
1256  NULL,
1257 };
1258 const static char* const mpls_label_imp_uniform_ip6_nodes[] =
1259 {
1260  "ip6-mpls-label-imposition-uniform",
1261  NULL,
1262 };
1263 const static char* const mpls_label_imp_uniform_mpls_nodes[] =
1264 {
1265  "mpls-label-imposition-uniform",
1266  NULL,
1267 };
1268 const static char* const mpls_label_imp_uniform_ethernet_nodes[] =
1269 {
1270  "ethernet-mpls-label-imposition-uniform",
1271  NULL,
1272 };
1273 
1274 const static char* const * const mpls_label_imp_uniform_nodes[DPO_PROTO_NUM] =
1275 {
1280 };
1281 
1283 {
1284  "ip4-mpls-label-imposition-pipe-no-ip-ttl-decr",
1285  NULL,
1286 };
1288 {
1289  "ip6-mpls-label-imposition-pipe-no-ip-ttl-decr",
1290  NULL,
1291 };
1292 
1293 const static char* const * const mpls_label_imp_pipe_no_ip_tll_decr_nodes[DPO_PROTO_NUM] =
1294 {
1297 };
1298 
1300 {
1301  "ip4-mpls-label-imposition-uniform-no-ip-ttl-decr",
1302  NULL,
1303 };
1305 {
1306  "ip6-mpls-label-imposition-uniform-no-ip-ttl-decr",
1307  NULL,
1308 };
1309 
1311 {
1314 };
1315 
1316 void
1318 {
1320  dpo_register_new_type(&mld_vft,
1323  dpo_register_new_type(&mld_vft,
1326  dpo_register_new_type(&mld_vft,
1330  dpo_register_new_type(&mld_vft,
1332 }
1333 
1334 dpo_type_t
1336 {
1337  return (mpls_label_dpo_types[flags]);
1338 }
1339 #endif /* CLIB_MARCH_VARIANT */
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:124
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:406
u32 flags
Definition: vhost_user.h:141
#define CLIB_UNUSED(x)
Definition: clib.h:83
A virtual function table regisitered for a DPO type.
Definition: dpo.h:401
format_function_t format_mpls_header
Definition: mpls.h:72
static const char *const mpls_label_imp_pipe_no_ip_tll_decr_ip6_nodes[]
mpls_unicast_header_t hdr
The MPLS header imposed.
#define PREDICT_TRUE(x)
Definition: clib.h:113
static const char *const mpls_label_imp_pipe_no_ip_tll_decr_ip4_nodes[]
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
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:393
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
static const char *const mpls_label_imp_pipe_ethernet_nodes[]
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
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)
unsigned char u8
Definition: types.h:56
#define pool_len(p)
Number of elements in pool vector.
Definition: pool.h:140
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) ...
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)
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.
#define always_inline
Definition: clib.h:99
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
#define MPLS_LABEL_DEFAULT_EXP
The Default EXP added to MPLS label headers when no other value is available.
Definition: packet.h:55
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
unsigned int u32
Definition: types.h:88
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
u8 exp
TTL imposed - only valid for uniform LSPs.
static void vnet_mpls_uc_set_label(mpls_label_t *label_exp_s_ttl, u32 value)
Definition: packet.h:125
static const char *const mpls_label_imp_pipe_mpls_nodes[]
enum mpls_label_dpo_flags_t_ mpls_label_dpo_flags_t
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:342
#define FOR_EACH_MPLS_LABEL_DPO_ATTR(_item)
static void vnet_mpls_uc_set_exp(mpls_label_t *label_exp_s_ttl, u32 exp)
Definition: packet.h:132
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 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.
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:286
#define PREDICT_FALSE(x)
Definition: clib.h:112
Configuration for each label value in the output-stack.
Definition: fib_types.h:440
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:542
static const char *const *const mpls_label_imp_pipe_nodes[DPO_PROTO_NUM]
#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:338
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:230
#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:397
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
static const char *const mpls_label_imp_uniform_ethernet_nodes[]
vlib_main_t * vm
Definition: buffer.c:323
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)
#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:181
static const char *const mpls_label_imp_uniform_ip6_nodes[]
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:283
mpls_label_t fml_value
The label value.
Definition: fib_types.h:445
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:456
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_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:515
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:141
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
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:248
static const char *const *const mpls_label_imp_uniform_no_ip_tll_decr_nodes[DPO_PROTO_NUM]
static void vnet_mpls_uc_set_s(mpls_label_t *label_exp_s_ttl, u32 eos)
Definition: packet.h:139
u8 * format_dpo_id(u8 *s, va_list *args)
Format a DPO_id_t oject
Definition: dpo.c:148
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)
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 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:70
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:186
#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 buffer representation.
Definition: buffer.h:102
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
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 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
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:518
static void vnet_mpls_uc_set_ttl(mpls_label_t *label_exp_s_ttl, u32 ttl)
Definition: packet.h:146
mpls_label_dpo_flags_t mld_flags
Flags.
#define vnet_buffer(b)
Definition: buffer.h:365
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:232
u16 mld_locks
Number of locks/users of the label.
u8 fml_exp
EXP bits; valid only at imposition.
Definition: fib_types.h:460
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:182
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.
#define MPLS_LABEL_DEFAULT_TTL
The Default TTL added to MPLS label headers when no other value is available.
Definition: packet.h:50
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:85
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.
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
enum mpls_eos_bit_t_ mpls_eos_bit_t
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128