FD.io VPP  v21.01.1
Vector Packet Processing
mpls_tunnel.c
Go to the documentation of this file.
1 /*
2  * mpls_tunnel.c: MPLS tunnel interfaces (i.e. for RSVP-TE)
3  *
4  * Copyright (c) 2012 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <vnet/vnet.h>
19 #include <vnet/mpls/mpls_tunnel.h>
20 #include <vnet/mpls/mpls_types.h>
21 #include <vnet/ip/ip.h>
22 #include <vnet/fib/fib_path_list.h>
23 #include <vnet/adj/adj_midchain.h>
24 #include <vnet/adj/adj_mcast.h>
25 #include <vnet/dpo/replicate_dpo.h>
26 #include <vnet/fib/mpls_fib.h>
27 
28 /**
29  * @brief pool of tunnel instances
30  */
32 
33 /**
34  * @brief DB of SW index to tunnel index
35  */
37 
38 /**
39  * @brief MPLS tunnel flags strings
40  */
42 
43 /**
44  * @brief Packet trace structure
45  */
46 typedef struct mpls_tunnel_trace_t_
47 {
48  /**
49  * Tunnel-id / index in tunnel vector
50  */
53 
54 static u8 *
56  va_list * args)
57 {
58  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
59  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
60  mpls_tunnel_trace_t * t = va_arg (*args, mpls_tunnel_trace_t *);
61 
62  s = format (s, "MPLS: tunnel %d", t->tunnel_id);
63  return s;
64 }
65 
66 typedef enum
67 {
71 
72 /**
73  * @brief TX function. Only called L2. L3 traffic uses the adj-midchains
74  */
78 {
81  u16 nexts[VLIB_FRAME_SIZE], *next;
82  u32 n_left;
83 
84  n_left = frame->n_vectors;
85  b = bufs;
86  next = nexts;
87 
88  vlib_get_buffers (vm, from, bufs, n_left);
89 
90  while (n_left > 2)
91  {
92  const mpls_tunnel_t *mt0, *mt1;
93  u32 sw_if_index0, sw_if_index1;
94 
95  sw_if_index0 = vnet_buffer(b[0])->sw_if_index[VLIB_TX];
96  sw_if_index1 = vnet_buffer(b[1])->sw_if_index[VLIB_TX];
97 
98  mt0 = pool_elt_at_index(mpls_tunnel_pool,
99  mpls_tunnel_db[sw_if_index0]);
100  mt1 = pool_elt_at_index(mpls_tunnel_pool,
101  mpls_tunnel_db[sw_if_index1]);
102 
103  vnet_buffer(b[0])->ip.adj_index[VLIB_TX] = mt0->mt_l2_lb.dpoi_index;
104  vnet_buffer(b[1])->ip.adj_index[VLIB_TX] = mt1->mt_l2_lb.dpoi_index;
105  next[0] = mt0->mt_l2_lb.dpoi_next_node;
106  next[1] = mt1->mt_l2_lb.dpoi_next_node;
107 
108  /* since we are coming out of the L2 world, where the vlib_buffer
109  * union is used for other things, make sure it is clean for
110  * MPLS from now on.
111  */
112  vnet_buffer(b[0])->mpls.first = 0;
113  vnet_buffer(b[1])->mpls.first = 0;
114 
115  if (PREDICT_FALSE(b[0]->flags & VLIB_BUFFER_IS_TRACED))
116  {
118  b[0], sizeof (*tr));
119  tr->tunnel_id = mpls_tunnel_db[sw_if_index0];
120  }
121  if (PREDICT_FALSE(b[1]->flags & VLIB_BUFFER_IS_TRACED))
122  {
124  b[1], sizeof (*tr));
125  tr->tunnel_id = mpls_tunnel_db[sw_if_index1];
126  }
127 
128  b += 2;
129  n_left -= 2;
130  next += 2;
131  }
132  while (n_left)
133  {
134  const mpls_tunnel_t *mt0;
135  u32 sw_if_index0;
136 
137  sw_if_index0 = vnet_buffer(b[0])->sw_if_index[VLIB_TX];
138  mt0 = pool_elt_at_index(mpls_tunnel_pool,
139  mpls_tunnel_db[sw_if_index0]);
140 
141  vnet_buffer(b[0])->ip.adj_index[VLIB_TX] = mt0->mt_l2_lb.dpoi_index;
142  next[0] = mt0->mt_l2_lb.dpoi_next_node;
143 
144  /* since we are coming out of the L2 world, where the vlib_buffer
145  * union is used for other things, make sure it is clean for
146  * MPLS from now on.
147  */
148  vnet_buffer(b[0])->mpls.first = 0;
149 
150  if (PREDICT_FALSE(b[0]->flags & VLIB_BUFFER_IS_TRACED))
151  {
153  b[0], sizeof (*tr));
154  tr->tunnel_id = mpls_tunnel_db[sw_if_index0];
155  }
156 
157  b += 1;
158  n_left -= 1;
159  next += 1;
160  }
161 
162  vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
163 
164  return frame->n_vectors;
165 }
166 
168 {
169  .name = "mpls-tunnel-tx",
170  .vector_size = sizeof (u32),
171  .format_trace = format_mpls_tunnel_tx_trace,
173  .n_errors = 0,
174  .n_next_nodes = 0,
175  /* MPLS_TUNNEL_ENCAP_N_NEXT, */
176  /* .next_nodes = { */
177  /* [MPLS_TUNNEL_ENCAP_NEXT_L2_MIDCHAIN] = "mpls-load-balance", */
178  /* }, */
179 };
180 
181 /**
182  * @brief Get a tunnel object from a SW interface index
183  */
184 static mpls_tunnel_t*
186 {
187  if ((vec_len(mpls_tunnel_db) <= sw_if_index) ||
188  (~0 == mpls_tunnel_db[sw_if_index]))
189  return (NULL);
190 
191  return (pool_elt_at_index(mpls_tunnel_pool,
192  mpls_tunnel_db[sw_if_index]));
193 }
194 
195 /**
196  * @brief Build a rewrite string for the MPLS tunnel.
197  */
198 static u8*
200 {
201  /*
202  * passing the adj code a NULL rewrite means 'i don't have one cos
203  * t'other end is unresolved'. That's not the case here. For the mpls
204  * tunnel there are just no bytes of encap to apply in the adj. We'll impose
205  * the label stack once we choose a path. So return a zero length rewrite.
206  */
207  u8 *rewrite = NULL;
208 
209  vec_validate(rewrite, 0);
210  vec_reset_length(rewrite);
211 
212  return (rewrite);
213 }
214 
215 /**
216  * @brief Build a rewrite string for the MPLS tunnel.
217  */
218 static u8*
221  vnet_link_t link_type,
222  const void *dst_address)
223 {
224  return (mpls_tunnel_build_rewrite_i());
225 }
226 
228 {
233 
236  fib_node_index_t path_index,
237  void *arg)
238 {
240  fib_path_ext_t *path_ext;
241 
242  ctx = arg;
243 
244  /*
245  * if the path is not resolved, don't include it.
246  */
247  if (!fib_path_is_resolved(path_index))
248  {
250  }
251 
252  /*
253  * get the matching path-extension for the path being visited.
254  */
256  path_index);
257 
258  /*
259  * we don't want IP TTL decrements for packets hitting the MPLS labels
260  * we stack on, since the IP TTL decrement is done by the adj
261  */
263 
264  /*
265  * found a matching extension. stack it to obtain the forwarding
266  * info for this path.
267  */
268  ctx->next_hops = fib_path_ext_stack(path_ext,
269  ctx->fct,
270  ctx->fct,
271  ctx->next_hops);
272 
274 }
275 
276 static void
278  vnet_link_t linkt,
280  dpo_id_t *dpo_lb)
281 {
282  dpo_proto_t lb_proto;
283 
284  /*
285  * If the entry has path extensions then we construct a load-balance
286  * by stacking the extensions on the forwarding chains of the paths.
287  * Otherwise we use the load-balance of the path-list
288  */
290  .mt = mt,
291  .next_hops = NULL,
292  .fct = fct,
293  };
294 
295  /*
296  * As an optimisation we allocate the vector of next-hops to be sized
297  * equal to the maximum nuber of paths we will need, which is also the
298  * most likely number we will need, since in most cases the paths are 'up'.
299  */
302 
303  lb_proto = fib_forw_chain_type_to_dpo_proto(fct);
304 
306  {
309  &ctx);
310  }
311 
312  if (!dpo_id_is_valid(dpo_lb))
313  {
314  /*
315  * first time create
316  */
318  {
319  dpo_set(dpo_lb,
321  lb_proto,
322  replicate_create(0, lb_proto));
323  }
324  else
325  {
326  flow_hash_config_t fhc;
327 
328  switch (linkt)
329  {
330  case VNET_LINK_MPLS:
332  break;
333  case VNET_LINK_IP4:
334  case VNET_LINK_IP6:
335  fhc = IP_FLOW_HASH_DEFAULT;
336  break;
337  default:
338  fhc = 0;
339  break;
340  }
341 
342  dpo_set(dpo_lb,
344  lb_proto,
345  load_balance_create(0, lb_proto, fhc));
346  }
347  }
348 
350  {
351  /*
352  * MPLS multicast
353  */
355  }
356  else
357  {
359  ctx.next_hops,
361  vec_free(ctx.next_hops);
362  }
363 }
364 
365 /**
366  * mpls_tunnel_stack
367  *
368  * 'stack' (resolve the recursion for) the tunnel's midchain adjacency
369  */
370 static void
372 {
373  ip_adjacency_t *adj;
374  mpls_tunnel_t *mt;
376 
377  adj = adj_get(ai);
378  sw_if_index = adj->rewrite_header.sw_if_index;
379 
380  mt = mpls_tunnel_get_from_sw_if_index(sw_if_index);
381 
382  if (NULL == mt || FIB_NODE_INDEX_INVALID == mt->mt_path_list)
383  return;
384 
386  {
388  return;
389  }
390 
391  /*
392  * while we're stacking the adj, remove the tunnel from the child list
393  * of the path list. this breaks a circular dependency of walk updates
394  * where the create of adjacencies in the children can lead to walks
395  * that get back here.
396  */
398 
400  mt->mt_sibling_index);
401 
402  /*
403  * Construct the DPO (load-balance or replicate) that we can stack
404  * the tunnel's midchain on
405  */
407  mt->mt_hw_if_index) &
409  {
410  dpo_id_t dpo = DPO_INVALID;
411 
413  adj->ia_link,
415  adj_get_link_type(ai)),
416  &dpo);
417 
418  adj_nbr_midchain_stack(ai, &dpo);
419  dpo_reset(&dpo);
420  }
421  else
422  {
424  }
425 
428  mt - mpls_tunnel_pool);
429 
431 }
432 
433 /**
434  * @brief Call back when restacking all adjacencies on a MPLS interface
435  */
436 static adj_walk_rc_t
438  void *ctx)
439 {
440  mpls_tunnel_stack(ai);
441 
442  return (ADJ_WALK_RC_CONTINUE);
443 }
444 
445 static void
447 {
449 
450  /*
451  * walk all the adjacencies on the MPLS interface and restack them
452  */
453  if (mt->mt_flags & MPLS_TUNNEL_FLAG_L2)
454  {
455  /*
456  * Stack a load-balance that drops, whilst we have no paths
457  */
458  dpo_id_t dpo = DPO_INVALID;
459 
463  &dpo);
464 
466  &mt->mt_l2_lb,
467  &dpo);
468  dpo_reset(&dpo);
469  }
470  else
471  {
473  {
475  proto,
477  NULL);
478  }
479  }
480 }
481 
482 static clib_error_t *
484  u32 hw_if_index,
485  u32 flags)
486 {
488  mpls_tunnel_t *mt;
489 
490  hi = vnet_get_hw_interface (vnm, hw_if_index);
491 
493 
494  if (NULL == mt)
495  return (NULL);
496 
498  vnet_hw_interface_set_flags (vnm, hw_if_index,
500  else
501  vnet_hw_interface_set_flags (vnm, hw_if_index, 0 /* down */);
502 
504 
505  return (NULL);
506 }
507 
508 /**
509  * @brief Fixup the adj rewrite post encap. This is a no-op since the
510  * rewrite is a stack of labels.
511  */
512 static void
514  const ip_adjacency_t *adj,
515  vlib_buffer_t *b0,
516  const void*data)
517 {
518  /*
519  * A no-op w.r.t. the header. but reset the 'have we pushed any
520  * MPLS labels onto the packet' flag. That way when we enter the
521  * tunnel we'll get a TTL set to 255
522  */
523  vnet_buffer(b0)->mpls.first = 0;
524 }
525 
526 static void
529  adj_index_t ai)
530 {
531  ip_adjacency_t *adj;
532 
533  ASSERT(ADJ_INDEX_INVALID != ai);
534 
535  adj = adj_get(ai);
536 
537  switch (adj->lookup_next_index)
538  {
539  case IP_LOOKUP_NEXT_ARP:
543  NULL,
546  break;
548  /*
549  * Construct a partial rewrite from the known ethernet mcast dest MAC
550  * There's no MAC fixup, so the last 2 parameters are 0
551  */
553  NULL,
556  0, 0);
557  break;
558 
559  case IP_LOOKUP_NEXT_DROP:
560  case IP_LOOKUP_NEXT_PUNT:
566  case IP_LOOKUP_N_NEXT:
567  ASSERT (0);
568  break;
569  }
570 
571  mpls_tunnel_stack(ai);
572 }
573 
574 static u8 *
575 format_mpls_tunnel_name (u8 * s, va_list * args)
576 {
577  u32 dev_instance = va_arg (*args, u32);
578  return format (s, "mpls-tunnel%d", dev_instance);
579 }
580 
581 static u8 *
582 format_mpls_tunnel_device (u8 * s, va_list * args)
583 {
584  u32 dev_instance = va_arg (*args, u32);
585  CLIB_UNUSED (int verbose) = va_arg (*args, int);
586 
587  return (format (s, "MPLS-tunnel: id %d\n", dev_instance));
588 }
589 
590 VNET_DEVICE_CLASS (mpls_tunnel_class) = {
591  .name = "MPLS tunnel device",
592  .format_device_name = format_mpls_tunnel_name,
593  .format_device = format_mpls_tunnel_device,
594  .format_tx_trace = format_mpls_tunnel_tx_trace,
595  .admin_up_down_function = mpls_tunnel_admin_up_down,
596 };
597 
598 VNET_HW_INTERFACE_CLASS (mpls_tunnel_hw_interface_class) = {
599  .name = "MPLS-Tunnel",
600  .update_adjacency = mpls_tunnel_update_adj,
601  .build_rewrite = mpls_tunnel_build_rewrite,
603 };
604 
605 const mpls_tunnel_t *
607 {
608  return (pool_elt_at_index(mpls_tunnel_pool, mti));
609 }
610 
611 /**
612  * @brief Walk all the MPLS tunnels
613  */
614 void
616  void *ctx)
617 {
618  u32 mti;
619 
620  pool_foreach_index (mti, mpls_tunnel_pool)
621  {
622  cb(mti, ctx);
623  }
624 }
625 
626 void
628 {
629  mpls_tunnel_t *mt;
630 
631  mt = mpls_tunnel_get_from_sw_if_index(sw_if_index);
632 
633  if (NULL == mt)
634  return;
635 
638  mt->mt_sibling_index);
639  dpo_reset(&mt->mt_l2_lb);
640 
642 
643  pool_put(mpls_tunnel_pool, mt);
645 }
646 
647 u32
649  u8 is_multicast,
650  u8 *tag)
651 {
653  mpls_tunnel_t *mt;
654  vnet_main_t * vnm;
655  u32 mti;
656 
657  vnm = vnet_get_main();
658  pool_get(mpls_tunnel_pool, mt);
659  clib_memset (mt, 0, sizeof (*mt));
660  mti = mt - mpls_tunnel_pool;
664 
665  if (is_multicast)
667  if (l2_only)
669  if (tag)
670  memcpy(mt->mt_tag, tag, sizeof(mt->mt_tag));
671  else
672  mt->mt_tag[0] = '\0';
673 
674  /*
675  * Create a new tunnel HW interface
676  */
678  vnm,
679  mpls_tunnel_class.index,
680  mti,
681  mpls_tunnel_hw_interface_class.index,
682  mti);
683  hi = vnet_get_hw_interface (vnm, mt->mt_hw_if_index);
684 
685  if (mt->mt_flags & MPLS_TUNNEL_FLAG_L2)
687  mpls_tunnel_tx.index);
688 
689  /* Standard default MPLS tunnel MTU. */
690  vnet_sw_interface_set_mtu (vnm, hi->sw_if_index, 9000);
691 
692  /*
693  * Add the new tunnel to the tunnel DB - key:SW if index
694  */
695  mt->mt_sw_if_index = hi->sw_if_index;
697  mpls_tunnel_db[mt->mt_sw_if_index] = mti;
698 
699  return (mt->mt_sw_if_index);
700 }
701 
702 void
704  fib_route_path_t *rpaths)
705 {
706  fib_route_path_t *rpath;
707  mpls_tunnel_t *mt;
708  u32 mti;
709 
710  mt = mpls_tunnel_get_from_sw_if_index(sw_if_index);
711 
712  if (NULL == mt)
713  return;
714 
715  mti = mt - mpls_tunnel_pool;
716 
717  /*
718  * construct a path-list from the path provided
719  */
721  {
725  mti);
726  }
727  else
728  {
729  fib_node_index_t old_pl_index;
730 
731  old_pl_index = mt->mt_path_list;
732 
733  mt->mt_path_list =
734  fib_path_list_copy_and_path_add(old_pl_index,
736  rpaths);
737 
738  fib_path_list_child_remove(old_pl_index,
739  mt->mt_sibling_index);
742  mti);
743  /*
744  * re-resolve all the path-extensions with the new path-list
745  */
747  }
748  vec_foreach(rpath, rpaths)
749  {
751  mt->mt_path_list,
753  rpath);
754  }
756 }
757 
758 int
760  fib_route_path_t *rpaths)
761 {
762  mpls_tunnel_t *mt;
763  u32 mti;
764 
765  mt = mpls_tunnel_get_from_sw_if_index(sw_if_index);
766 
767  if (NULL == mt)
768  return (0);
769 
770  mti = mt - mpls_tunnel_pool;
771 
772  /*
773  * construct a path-list from the path provided
774  */
776  {
777  /* can't remove a path if we have onoe */
778  return (0);
779  }
780  else
781  {
782  fib_node_index_t old_pl_index;
783 
784  old_pl_index = mt->mt_path_list;
785 
786  fib_path_list_lock(old_pl_index);
787  mt->mt_path_list =
790  rpaths);
791 
792  fib_path_list_child_remove(old_pl_index,
793  mt->mt_sibling_index);
794 
796  {
797  /* no paths left */
798  fib_path_list_unlock(old_pl_index);
799  return (0);
800  }
801  else
802  {
803  mt->mt_sibling_index =
806  mti);
807  }
808  /*
809  * find the matching path extension and remove it
810  */
813  rpaths);
814 
815  /*
816  * re-resolve all the path-extensions with the new path-list
817  */
819  mt->mt_path_list);
820 
822  fib_path_list_unlock(old_pl_index);
823  }
824 
826 }
827 
828 int
830 {
831  mpls_tunnel_t *mt;
832 
833  mt = mpls_tunnel_get_from_sw_if_index(sw_if_index);
834 
835  if (NULL == mt)
836  return (~0);
837 
838  return (mt - mpls_tunnel_pool);
839 }
840 
841 static clib_error_t *
843  unformat_input_t * input,
844  vlib_cli_command_t * cmd)
845 {
846  unformat_input_t _line_input, * line_input = &_line_input;
847  vnet_main_t * vnm = vnet_get_main();
848  u8 is_del = 0, l2_only = 0, is_multicast =0;
849  fib_route_path_t rpath, *rpaths = NULL;
850  u32 sw_if_index = ~0, payload_proto;
851  clib_error_t *error = NULL;
852 
853  clib_memset(&rpath, 0, sizeof(rpath));
854  payload_proto = DPO_PROTO_MPLS;
855 
856  /* Get a line of input. */
857  if (! unformat_user (input, unformat_line_input, line_input))
858  return 0;
859 
860  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
861  {
862  if (unformat (line_input, "del %U",
864  &sw_if_index))
865  is_del = 1;
866  else if (unformat (line_input, "add %U",
868  &sw_if_index))
869  is_del = 0;
870  else if (unformat (line_input, "add"))
871  is_del = 0;
872  else if (unformat (line_input, "l2-only"))
873  l2_only = 1;
874  else if (unformat (line_input, "multicast"))
875  is_multicast = 1;
876  else if (unformat (line_input, "via %U",
878  &rpath, &payload_proto))
879  vec_add1(rpaths, rpath);
880  else
881  {
882  error = clib_error_return (0, "unknown input '%U'",
883  format_unformat_error, line_input);
884  goto done;
885  }
886  }
887 
888  if (is_del)
889  {
890  if (NULL == rpaths)
891  {
892  vnet_mpls_tunnel_del(sw_if_index);
893  }
894  else if (!vnet_mpls_tunnel_path_remove(sw_if_index, rpaths))
895  {
896  vnet_mpls_tunnel_del(sw_if_index);
897  }
898  }
899  else
900  {
901  if (0 == vec_len(rpath.frp_label_stack))
902  {
903  error = clib_error_return (0, "No Output Labels '%U'",
904  format_unformat_error, line_input);
905  goto done;
906  }
907 
908  if (~0 == sw_if_index)
909  {
910  sw_if_index = vnet_mpls_tunnel_create(l2_only, is_multicast, NULL);
911  }
912  vnet_mpls_tunnel_path_add(sw_if_index, rpaths);
913  }
914 
915 done:
916  vec_free(rpaths);
917  unformat_free (line_input);
918 
919  return error;
920 }
921 
922 /*?
923  * This command create a uni-directional MPLS tunnel
924  *
925  * @cliexpar
926  * @cliexstart{create mpls tunnel}
927  * create mpls tunnel via 10.0.0.1 GigEthernet0/8/0 out-label 33 out-label 34
928  * @cliexend
929  ?*/
930 VLIB_CLI_COMMAND (create_mpls_tunnel_command, static) = {
931  .path = "mpls tunnel",
932  .short_help =
933  "mpls tunnel [multicast] [l2-only] via [next-hop-address] [next-hop-interface] [next-hop-table <value>] [weight <value>] [preference <value>] [udp-encap-id <value>] [ip4-lookup-in-table <value>] [ip6-lookup-in-table <value>] [mpls-lookup-in-table <value>] [resolve-via-host] [resolve-via-connected] [rx-ip4 <interface>] [out-labels <value value value>]",
935 };
936 
937 static u8 *
938 format_mpls_tunnel (u8 * s, va_list * args)
939 {
940  mpls_tunnel_t *mt = va_arg (*args, mpls_tunnel_t *);
942 
943  s = format(s, "mpls-tunnel%d: sw_if_index:%d hw_if_index:%d",
944  mt - mpls_tunnel_pool,
945  mt->mt_sw_if_index,
946  mt->mt_hw_if_index);
947  if (MPLS_TUNNEL_FLAG_NONE != mt->mt_flags) {
948  s = format(s, " \n flags:");
950  if ((1<<attr) & mt->mt_flags) {
951  s = format (s, "%s,", mpls_tunnel_attribute_names[attr]);
952  }
953  }
954  }
955  s = format(s, "\n via:\n");
957  s = format(s, "%U", format_fib_path_ext_list, &mt->mt_path_exts);
958  s = format(s, "\n");
959 
960  if (mt->mt_flags & MPLS_TUNNEL_FLAG_L2)
961  {
962  s = format(s, " forwarding: %U\n",
965  s = format(s, " %U\n", format_dpo_id, &mt->mt_l2_lb, 2);
966  }
967 
968  return (s);
969 }
970 
971 static clib_error_t *
973  unformat_input_t * input,
974  vlib_cli_command_t * cmd)
975 {
976  mpls_tunnel_t * mt;
977  u32 mti = ~0;
978 
979  if (pool_elts (mpls_tunnel_pool) == 0)
980  vlib_cli_output (vm, "No MPLS tunnels configured...");
981 
983  {
984  if (unformat (input, "%d", &mti))
985  ;
986  else
987  break;
988  }
989 
990  if (~0 == mti)
991  {
992  pool_foreach (mt, mpls_tunnel_pool)
993  {
994  vlib_cli_output (vm, "[@%d] %U",
995  mt - mpls_tunnel_pool,
996  format_mpls_tunnel, mt);
997  }
998  }
999  else
1000  {
1001  if (pool_is_free_index(mpls_tunnel_pool, mti))
1002  return clib_error_return (0, "Not a tunnel index %d", mti);
1003 
1004  mt = pool_elt_at_index(mpls_tunnel_pool, mti);
1005 
1006  vlib_cli_output (vm, "[@%d] %U",
1007  mt - mpls_tunnel_pool,
1008  format_mpls_tunnel, mt);
1009  }
1010 
1011  return 0;
1012 }
1013 
1014 /*?
1015  * This command to show MPLS tunnels
1016  *
1017  * @cliexpar
1018  * @cliexstart{sh mpls tunnel 2}
1019  * [@2] mpls_tunnel2: sw_if_index:5 hw_if_index:5
1020  * label-stack:
1021  * 3,
1022  * via:
1023  * index:26 locks:1 proto:ipv4 uPRF-list:26 len:1 itfs:[2, ]
1024  * index:26 pl-index:26 ipv4 weight=1 attached-nexthop: oper-flags:resolved,
1025  * 10.0.0.2 loop0
1026  * [@0]: ipv4 via 10.0.0.2 loop0: IP4: de:ad:00:00:00:00 -> 00:00:11:aa:bb:cc
1027  * @cliexend
1028  ?*/
1029 VLIB_CLI_COMMAND (show_mpls_tunnel_command, static) = {
1030  .path = "show mpls tunnel",
1031  .function = show_mpls_tunnel_command_fn,
1032 };
1033 
1034 static mpls_tunnel_t *
1036 {
1038  return ((mpls_tunnel_t*) (((char*)node) -
1039  STRUCT_OFFSET_OF(mpls_tunnel_t, mt_node)));
1040 }
1041 
1042 /**
1043  * Function definition to backwalk a FIB node
1044  */
1048 {
1050 
1051  return (FIB_NODE_BACK_WALK_CONTINUE);
1052 }
1053 
1054 /**
1055  * Function definition to get a FIB node from its index
1056  */
1057 static fib_node_t*
1059 {
1060  mpls_tunnel_t * mt;
1061 
1062  mt = pool_elt_at_index(mpls_tunnel_pool, index);
1063 
1064  return (&mt->mt_node);
1065 }
1066 
1067 /**
1068  * Function definition to inform the FIB node that its last lock has gone.
1069  */
1070 static void
1072 {
1073  /*
1074  * The MPLS MPLS tunnel is a root of the graph. As such
1075  * it never has children and thus is never locked.
1076  */
1077  ASSERT(0);
1078 }
1079 
1080 /*
1081  * Virtual function table registered by MPLS MPLS tunnels
1082  * for participation in the FIB object graph.
1083  */
1084 const static fib_node_vft_t mpls_vft = {
1086  .fnv_last_lock = mpls_tunnel_last_lock_gone,
1087  .fnv_back_walk = mpls_tunnel_back_walk,
1088 };
1089 
1090 static clib_error_t *
1092 {
1094 
1095  return 0;
1096 }
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
int fib_path_is_resolved(fib_node_index_t path_index)
Definition: fib_path.c:2670
void vnet_set_interface_output_node(vnet_main_t *vnm, u32 hw_if_index, u32 node_index)
Set interface output node - for interface registered without its output/tx nodes created because its ...
void dpo_stack_from_node(u32 child_node_index, 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:536
static u8 * format_mpls_tunnel_tx_trace(u8 *s, va_list *args)
Definition: mpls_tunnel.c:55
Packet trace structure.
Definition: mpls_tunnel.c:46
fib_forward_chain_type_t fib_forw_chain_type_from_link_type(vnet_link_t link_type)
Convert from a adjacency&#39;s link type to chain type.
Definition: fib_types.c:493
#define pool_foreach_index(i, v)
Definition: pool.h:569
#define CLIB_UNUSED(x)
Definition: clib.h:87
static void mpls_tunnel_fixup(vlib_main_t *vm, const ip_adjacency_t *adj, vlib_buffer_t *b0, const void *data)
Fixup the adj rewrite post encap.
Definition: mpls_tunnel.c:513
void fib_path_list_child_remove(fib_node_index_t path_list_index, u32 si)
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
A representation of a path as described by a route producer.
Definition: fib_types.h:500
static fib_path_list_walk_rc_t mpls_tunnel_collect_forwarding(fib_node_index_t pl_index, fib_node_index_t path_index, void *arg)
Definition: mpls_tunnel.c:235
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:527
void vnet_sw_interface_set_mtu(vnet_main_t *vnm, u32 sw_if_index, u32 mtu)
Definition: interface.c:686
fib_node_index_t mt_path_list
The path-list over which the tunnel&#39;s destination is reachable.
Definition: mpls_tunnel.h:91
void fib_node_init(fib_node_t *node, fib_node_type_t type)
Definition: fib_node.c:185
uword unformat_fib_route_path(unformat_input_t *input, va_list *args)
Unformat a fib_route_path_t from CLI input.
Definition: fib_types.c:540
static int dpo_id_is_valid(const dpo_id_t *dpoi)
Return true if the DPO object is valid, i.e.
Definition: dpo.h:214
vlib_node_registration_t mpls_tunnel_tx
(constructor) VLIB_REGISTER_NODE (mpls_tunnel_tx)
Definition: mpls_tunnel.c:167
#define FOR_EACH_MPLS_TUNNEL_ATTRIBUTE(_item)
Definition: mpls_tunnel.h:40
Multicast Adjacency.
Definition: adj.h:82
vnet_link_t adj_get_link_type(adj_index_t ai)
Return the link type of the adjacency.
Definition: adj.c:506
mpls_tunnel_flags_t mt_flags
Tunnel flags.
Definition: mpls_tunnel.h:65
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
Broadcast Adjacency.
Definition: adj.h:85
IP unicast adjacency.
Definition: adj.h:235
An MPLS extension that maintains the path&#39;s outgoing labels,.
Definition: fib_path_ext.h:31
enum fib_node_back_walk_rc_t_ fib_node_back_walk_rc_t
Return code from a back walk function.
A uni-directional MPLS tunnel.
Definition: mpls_tunnel.h:55
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
dpo_proto_t fib_forw_chain_type_to_dpo_proto(fib_forward_chain_type_t fct)
Convert from a chain type to the DPO proto it will install.
Definition: fib_types.c:516
This packet is to be rewritten and forwarded to the next processing node.
Definition: adj.h:73
static clib_error_t * mpls_tunnel_admin_up_down(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: mpls_tunnel.c:483
struct mpls_tunnel_collect_forwarding_ctx_t_ mpls_tunnel_collect_forwarding_ctx_t
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:592
fib_node_t mt_node
The tunnel hooks into the FIB control plane graph.
Definition: mpls_tunnel.h:60
void fib_path_list_walk(fib_node_index_t path_list_index, fib_path_list_walk_fn_t func, void *ctx)
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:70
u32 vnet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, u32 hw_class_index, u32 hw_instance)
Definition: interface.c:794
vlib_main_t * vm
Definition: in2out_ed.c:1580
unformat_function_t unformat_vnet_sw_interface
static u8 * format_mpls_tunnel_name(u8 *s, va_list *args)
Definition: mpls_tunnel.c:575
#define VLIB_NODE_FN(node)
Definition: node.h:203
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, vnet_hw_interface_flags_t flags)
Definition: interface.c:509
const mpls_tunnel_t * mpls_tunnel_get(u32 mti)
Definition: mpls_tunnel.c:606
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:251
u32 fib_path_list_child_add(fib_node_index_t path_list_index, fib_node_type_t child_type, fib_node_index_t child_index)
static u8 * format_mpls_tunnel_device(u8 *s, va_list *args)
Definition: mpls_tunnel.c:582
void(* mpls_tunnel_walk_cb_t)(u32 index, void *ctx)
Callback function invoked while walking MPLS tunnels.
Definition: mpls_tunnel.h:140
unsigned char u8
Definition: types.h:56
u8 data[128]
Definition: ipsec_types.api:90
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
static fib_node_back_walk_rc_t mpls_tunnel_back_walk(fib_node_t *node, fib_node_back_walk_ctx_t *ctx)
Function definition to backwalk a FIB node.
Definition: mpls_tunnel.c:1046
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
void fib_node_register_type(fib_node_type_t type, const fib_node_vft_t *vft)
fib_node_register_type
Definition: fib_node.c:60
vnet_link_t ia_link
link/ether-type 1 bytes
Definition: adj.h:343
index_t load_balance_create(u32 n_buckets, dpo_proto_t lb_proto, flow_hash_config_t fhc)
Definition: load_balance.c:264
Adjacency to punt this packet.
Definition: adj.h:55
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:467
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
static u32 * mpls_tunnel_db
DB of SW index to tunnel index.
Definition: mpls_tunnel.c:36
enum adj_walk_rc_t_ adj_walk_rc_t
return codes from a adjacency walker callback function
VNET_HW_INTERFACE_CLASS(mpls_tunnel_hw_interface_class)
description fragment has unexpected format
Definition: map.api:433
#define clib_error_return(e, args...)
Definition: error.h:99
fib_path_ext_list_t mt_path_exts
A vector of path extensions o hold the label stack for each path.
Definition: mpls_tunnel.h:101
const cJSON *const b
Definition: cJSON.h:255
void load_balance_multipath_update(const dpo_id_t *dpo, const load_balance_path_t *raw_nhs, load_balance_flags_t flags)
Definition: load_balance.c:627
unsigned int u32
Definition: types.h:88
Contribute an object that is to be used to forward Ethernet packets.
Definition: fib_types.h:140
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
static u8 * format_mpls_tunnel(u8 *s, va_list *args)
Definition: mpls_tunnel.c:938
u8 mt_tag[64]
User defined name tag for this MPLS Tunnel.
Definition: mpls_tunnel.h:70
#define VLIB_FRAME_SIZE
Definition: node.h:378
#define MPLS_TUNNEL_ATTRIBUTES
Definition: mpls_tunnel.h:36
fib_path_ext_t * fib_path_ext_list_find_by_path_index(const fib_path_ext_list_t *list, fib_node_index_t path_index)
Definition: fib_path_ext.c:326
fib_path_ext_mpls_flags_t fpe_mpls_flags
For an MPLS type extension.
Definition: fib_path_ext.h:120
unformat_function_t unformat_line_input
Definition: format.h:282
vl_api_fib_path_type_t type
Definition: fib_types.api:123
fib_node_index_t fib_path_list_copy_and_path_add(fib_node_index_t orig_path_list_index, fib_path_list_flags_t flags, const fib_route_path_t *rpaths)
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
Definition: cJSON.c:84
void vnet_mpls_tunnel_del(u32 sw_if_index)
Delete an MPLS tunnel.
Definition: mpls_tunnel.c:627
#define ADJ_INDEX_INVALID
Invalid ADJ index - used when no adj is known likewise blazoned capitals INVALID speak volumes where ...
Definition: adj_types.h:36
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:546
fib_node_index_t fib_path_list_create(fib_path_list_flags_t flags, const fib_route_path_t *rpaths)
static const char * mpls_tunnel_attribute_names[]
MPLS tunnel flags strings.
Definition: mpls_tunnel.c:41
int vnet_mpls_tunnel_get_index(u32 sw_if_index)
return the tunnel index from the sw_if_index
Definition: mpls_tunnel.c:829
static uword vnet_hw_interface_get_flags(vnet_main_t *vnm, u32 hw_if_index)
vl_api_ip_proto_t proto
Definition: acl_types.api:51
long ctx[MAX_CONNS]
Definition: main.c:144
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
load-balancing over a choice of [un]equal cost paths
Definition: dpo.h:102
#define MPLS_FLOW_HASH_DEFAULT
There are no options for controlling the MPLS flow hash.
Definition: mpls_fib.h:39
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:301
static mpls_tunnel_t * mpls_tunnel_get_from_sw_if_index(u32 sw_if_index)
Get a tunnel object from a SW interface index.
Definition: mpls_tunnel.c:185
#define PREDICT_FALSE(x)
Definition: clib.h:121
fib_mpls_label_t * frp_label_stack
The outgoing MPLS label Stack.
Definition: fib_types.h:560
This packet matches an "interface route" and packets need to be passed to ARP to find rewrite string ...
Definition: adj.h:68
void fib_path_list_lock(fib_node_index_t path_list_index)
u32 mt_sibling_index
sibling index on the path-list so notifications are received.
Definition: mpls_tunnel.h:96
fib_node_type_t fn_type
The node&#39;s type.
Definition: fib_node.h:299
#define IP_FLOW_HASH_DEFAULT
Default: 5-tuple without the "reverse" bit.
Definition: ip_flow_hash.h:29
An node in the FIB graph.
Definition: fib_node.h:295
mpls_tunnel_encap_next_t
Definition: mpls_tunnel.c:66
static adj_walk_rc_t mpls_adj_walk_cb(adj_index_t ai, void *ctx)
Call back when restacking all adjacencies on a MPLS interface.
Definition: mpls_tunnel.c:437
fib_node_index_t fib_path_list_copy_and_path_remove(fib_node_index_t orig_path_list_index, fib_path_list_flags_t flags, const fib_route_path_t *rpaths)
void replicate_multipath_update(const dpo_id_t *dpo, load_balance_path_t *next_hops)
This packet matches an "incomplete adjacency" and packets need to be passed to ARP to find rewrite st...
Definition: adj.h:63
u32 tunnel_id
Tunnel-id / index in tunnel vector.
Definition: mpls_tunnel.c:51
Adjacency to drop this packet.
Definition: adj.h:53
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:170
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
static u8 * mpls_tunnel_build_rewrite_i(void)
Build a rewrite string for the MPLS tunnel.
Definition: mpls_tunnel.c:199
static_always_inline void vlib_buffer_enqueue_to_next(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u16 *nexts, uword count)
Definition: buffer_node.h:339
VNET_DEVICE_CLASS(mpls_tunnel_class)
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
Multicast Midchain Adjacency.
Definition: adj.h:89
static void mpls_tunnel_restack(mpls_tunnel_t *mt)
Definition: mpls_tunnel.c:446
void adj_nbr_midchain_update_rewrite(adj_index_t adj_index, adj_midchain_fixup_t fixup, const void *fixup_data, adj_flags_t flags, u8 *rewrite)
adj_nbr_midchain_update_rewrite
Definition: adj_midchain.c:440
fib_node_get_t fnv_get
Definition: fib_node.h:283
void fib_path_ext_list_remove(fib_path_ext_list_t *list, fib_path_ext_type_t ext_type, const fib_route_path_t *rpath)
Definition: fib_path_ext.c:428
u32 fib_path_list_get_n_paths(fib_node_index_t path_list_index)
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:29
void mpls_tunnel_walk(mpls_tunnel_walk_cb_t cb, void *ctx)
Walk all the MPLS tunnels.
Definition: mpls_tunnel.c:615
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:298
u32 adj_index_t
An index for adjacencies.
Definition: adj_types.h:30
void adj_mcast_midchain_update_rewrite(adj_index_t adj_index, adj_midchain_fixup_t fixup, const void *fixup_data, adj_flags_t flags, u8 *rewrite, u8 offset, u32 mask)
adj_mcast_midchain_update_rewrite
Definition: adj_mcast.c:139
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 fib_path_list_unlock(fib_node_index_t path_list_index)
index_t replicate_create(u32 n_buckets, dpo_proto_t rep_proto)
void adj_nbr_walk(u32 sw_if_index, fib_protocol_t adj_nh_proto, adj_walk_cb_t cb, void *ctx)
Walk all adjacencies on a link for a given next-hop protocol.
Definition: adj_nbr.c:571
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1580
static clib_error_t * mpls_tunnel_init(vlib_main_t *vm)
Definition: mpls_tunnel.c:1091
Context passed between object during a back walk.
Definition: fib_node.h:208
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
static mpls_tunnel_t * mpls_tunnel_pool
pool of tunnel instances
Definition: mpls_tunnel.c:31
This packets follow a mid-chain adjacency.
Definition: adj.h:76
#define ASSERT(truth)
int vnet_mpls_tunnel_path_remove(u32 sw_if_index, fib_route_path_t *rpaths)
remove a path from a tunnel.
Definition: mpls_tunnel.c:759
void adj_nbr_midchain_stack(adj_index_t adj_index, const dpo_id_t *next)
adj_nbr_midchain_stack
Definition: adj_midchain.c:641
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
enum vnet_link_t_ vnet_link_t
Link Type: A description of the protocol of packets on the link.
void vnet_delete_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:1011
enum fib_forward_chain_type_t_ fib_forward_chain_type_t
FIB output chain type.
u32 mt_hw_if_index
The HW interface index of the tunnel interfaces.
Definition: mpls_tunnel.h:81
u8 * format_fib_forw_chain_type(u8 *s, va_list *args)
Definition: fib_types.c:49
void adj_nbr_midchain_unstack(adj_index_t adj_index)
adj_nbr_midchain_unstack
Definition: adj_midchain.c:530
u8 * format_dpo_id(u8 *s, va_list *args)
Format a DPO_id_t oject.
Definition: dpo.c:148
vl_api_ip4_address_t hi
Definition: arp.api:37
static u8 * mpls_tunnel_build_rewrite(vnet_main_t *vnm, u32 sw_if_index, vnet_link_t link_type, const void *dst_address)
Build a rewrite string for the MPLS tunnel.
Definition: mpls_tunnel.c:219
u32 vnet_mpls_tunnel_create(u8 l2_only, u8 is_multicast, u8 *tag)
Create a new MPLS tunnel.
Definition: mpls_tunnel.c:648
This packets needs to go to ICMP error.
Definition: adj.h:79
This packet is for one of our own IP addresses.
Definition: adj.h:58
Definition: defs.h:47
enum fib_path_list_walk_rc_t_ fib_path_list_walk_rc_t
return code to control pat-hlist walk
void vnet_mpls_tunnel_path_add(u32 sw_if_index, fib_route_path_t *rpaths)
Add a path to an MPLS tunnel.
Definition: mpls_tunnel.c:703
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:188
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:30
void fib_path_ext_list_resolve(fib_path_ext_list_t *list, fib_node_index_t path_list_index)
Definition: fib_path_ext.c:416
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
ip_lookup_next_t lookup_next_index
Next hop after ip4-lookup.
Definition: adj.h:337
static clib_error_t * vnet_create_mpls_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: mpls_tunnel.c:842
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1581
static void mpls_tunnel_stack(adj_index_t ai)
mpls_tunnel_stack
Definition: mpls_tunnel.c:371
VLIB buffer representation.
Definition: buffer.h:102
u8 * fib_path_list_format(fib_node_index_t path_list_index, u8 *s)
static void unformat_free(unformat_input_t *i)
Definition: format.h:162
struct mpls_tunnel_trace_t_ mpls_tunnel_trace_t
Packet trace structure.
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:297
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:202
a point 2 point interface
Definition: interface.h:387
u32 index
Definition: flow_types.api:221
static void mpls_tunnel_last_lock_gone(fib_node_t *node)
Function definition to inform the FIB node that its last lock has gone.
Definition: mpls_tunnel.c:1071
One path from an [EU]CMP set that the client wants to add to a load-balance object.
Definition: load_balance.h:62
#define FOR_EACH_FIB_IP_PROTOCOL(_item)
Definition: fib_types.h:69
A FIB graph nodes virtual function table.
Definition: fib_node.h:282
#define vnet_buffer(b)
Definition: buffer.h:417
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
u32 flow_hash_config_t
A flow hash configuration is a mask of the flow hash options.
Definition: ip_flow_hash.h:43
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:232
#define vec_foreach(var, vec)
Vector iterator.
A path extension is a per-entry addition to the forwarding information when packets are sent for that...
Definition: fib_path_ext.h:98
u8 * format_fib_path_ext_list(u8 *s, va_list *args)
Definition: fib_path_ext.c:461
u32 mt_sw_if_index
The SW interface index of the tunnel interfaces.
Definition: mpls_tunnel.h:86
dpo_id_t mt_l2_lb
If the tunnel is an L2 tunnel, this is the link type ETHERNET load-balance.
Definition: mpls_tunnel.h:76
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:634
static fib_node_t * mpls_tunnel_fib_node_get(fib_node_index_t index)
Function definition to get a FIB node from its index.
Definition: mpls_tunnel.c:1058
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:184
enum mpls_tunnel_attribute_t_ mpls_tunnel_attribute_t
static_always_inline void vlib_get_buffers(vlib_main_t *vm, u32 *bi, vlib_buffer_t **b, int count)
Translate array of buffer indices into buffer pointers.
Definition: buffer_funcs.h:280
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:556
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
static clib_error_t * show_mpls_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: mpls_tunnel.c:972
fib_forward_chain_type_t fct
Definition: mpls_tunnel.c:231
fib_path_ext_t * fib_path_ext_list_insert(fib_path_ext_list_t *list, fib_node_index_t path_list_index, fib_path_ext_type_t ext_type, const fib_route_path_t *rpath)
Definition: fib_path_ext.c:372
static void mpls_tunnel_mk_lb(mpls_tunnel_t *mt, vnet_link_t linkt, fib_forward_chain_type_t fct, dpo_id_t *dpo_lb)
Definition: mpls_tunnel.c:277
load_balance_path_t * fib_path_ext_stack(fib_path_ext_t *path_ext, fib_forward_chain_type_t child_fct, fib_forward_chain_type_t imp_null_fct, load_balance_path_t *nhs)
Definition: fib_path_ext.c:165
static void mpls_tunnel_update_adj(vnet_main_t *vnm, u32 sw_if_index, adj_index_t ai)
Definition: mpls_tunnel.c:527
static mpls_tunnel_t * mpls_tunnel_from_fib_node(fib_node_t *node)
Definition: mpls_tunnel.c:1035
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127