FD.io VPP  v18.10-32-g1161dda
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/pg/pg.h>
20 #include <vnet/mpls/mpls_tunnel.h>
21 #include <vnet/mpls/mpls_types.h>
22 #include <vnet/ip/ip.h>
23 #include <vnet/fib/fib_path_list.h>
24 #include <vnet/adj/adj_midchain.h>
25 #include <vnet/adj/adj_mcast.h>
26 #include <vnet/dpo/replicate_dpo.h>
27 #include <vnet/fib/mpls_fib.h>
28 
29 /**
30  * @brief pool of tunnel instances
31  */
33 
34 /**
35  * @brief DB of SW index to tunnel index
36  */
38 
39 /**
40  * @brief MPLS tunnel flags strings
41  */
43 
44 /**
45  * @brief Get a tunnel object from a SW interface index
46  */
47 static mpls_tunnel_t*
49 {
50  if ((vec_len(mpls_tunnel_db) <= sw_if_index) ||
51  (~0 == mpls_tunnel_db[sw_if_index]))
52  return (NULL);
53 
54  return (pool_elt_at_index(mpls_tunnel_pool,
55  mpls_tunnel_db[sw_if_index]));
56 }
57 
58 /**
59  * @brief Build a rewrite string for the MPLS tunnel.
60  */
61 static u8*
63 {
64  /*
65  * passing the adj code a NULL rewirte means 'i don't have one cos
66  * t'other end is unresolved'. That's not the case here. For the mpls
67  * tunnel there are just no bytes of encap to apply in the adj. We'll impose
68  * the label stack once we choose a path. So return a zero length rewrite.
69  */
70  u8 *rewrite = NULL;
71 
72  vec_validate(rewrite, 0);
73  vec_reset_length(rewrite);
74 
75  return (rewrite);
76 }
77 
78 /**
79  * @brief Build a rewrite string for the MPLS tunnel.
80  */
81 static u8*
84  vnet_link_t link_type,
85  const void *dst_address)
86 {
87  return (mpls_tunnel_build_rewrite_i());
88 }
89 
91 {
93  const mpls_tunnel_t *mt;
96 
99  fib_node_index_t path_index,
100  void *arg)
101 {
103  fib_path_ext_t *path_ext;
104 
105  ctx = arg;
106 
107  /*
108  * if the path is not resolved, don't include it.
109  */
110  if (!fib_path_is_resolved(path_index))
111  {
113  }
114 
115  /*
116  * get the matching path-extension for the path being visited.
117  */
119  path_index);
120 
121  /*
122  * we don't want IP TTL decrements for packets hitting the MPLS labels
123  * we stack on, since the IP TTL decrement is done by the adj
124  */
126 
127  /*
128  * found a matching extension. stack it to obtain the forwarding
129  * info for this path.
130  */
131  ctx->next_hops = fib_path_ext_stack(path_ext,
132  ctx->fct,
133  ctx->fct,
134  ctx->next_hops);
135 
137 }
138 
139 static void
141  vnet_link_t linkt,
143  dpo_id_t *dpo_lb)
144 {
145  dpo_proto_t lb_proto;
146 
147  /*
148  * If the entry has path extensions then we construct a load-balance
149  * by stacking the extensions on the forwarding chains of the paths.
150  * Otherwise we use the load-balance of the path-list
151  */
153  .mt = mt,
154  .next_hops = NULL,
155  .fct = fct,
156  };
157 
158  /*
159  * As an optimisation we allocate the vector of next-hops to be sized
160  * equal to the maximum nuber of paths we will need, which is also the
161  * most likely number we will need, since in most cases the paths are 'up'.
162  */
165 
166  lb_proto = fib_forw_chain_type_to_dpo_proto(fct);
167 
169  {
172  &ctx);
173  }
174 
175  if (!dpo_id_is_valid(dpo_lb))
176  {
177  /*
178  * first time create
179  */
181  {
182  dpo_set(dpo_lb,
184  lb_proto,
185  replicate_create(0, lb_proto));
186  }
187  else
188  {
189  flow_hash_config_t fhc;
190 
191  switch (linkt)
192  {
193  case VNET_LINK_MPLS:
195  break;
196  case VNET_LINK_IP4:
197  case VNET_LINK_IP6:
198  fhc = IP_FLOW_HASH_DEFAULT;
199  break;
200  default:
201  fhc = 0;
202  break;
203  }
204 
205  dpo_set(dpo_lb,
207  lb_proto,
208  load_balance_create(0, lb_proto, fhc));
209  }
210  }
211 
213  {
214  /*
215  * MPLS multicast
216  */
218  }
219  else
220  {
222  ctx.next_hops,
224  vec_free(ctx.next_hops);
225  }
226 }
227 
228 /**
229  * mpls_tunnel_stack
230  *
231  * 'stack' (resolve the recursion for) the tunnel's midchain adjacency
232  */
233 static void
235 {
236  ip_adjacency_t *adj;
237  mpls_tunnel_t *mt;
239 
240  adj = adj_get(ai);
241  sw_if_index = adj->rewrite_header.sw_if_index;
242 
243  mt = mpls_tunnel_get_from_sw_if_index(sw_if_index);
244 
245  if (NULL == mt)
246  return;
247 
248  /*
249  * while we're stacking the adj, remove the tunnel from the child list
250  * of the path list. this breaks a circular dependency of walk updates
251  * where the create of adjacencies in the children can lead to walks
252  * that get back here.
253  */
255 
257  mt->mt_sibling_index);
258 
259  /*
260  * Construct the DPO (load-balance or replicate) that we can stack
261  * the tunnel's midchain on
262  */
264  mt->mt_hw_if_index) &
266  {
267  dpo_id_t dpo = DPO_INVALID;
268 
270  adj->ia_link,
272  adj_get_link_type(ai)),
273  &dpo);
274 
275  adj_nbr_midchain_stack(ai, &dpo);
276  dpo_reset(&dpo);
277  }
278  else
279  {
281  }
282 
285  mt - mpls_tunnel_pool);
286 
288 }
289 
290 /**
291  * @brief Call back when restacking all adjacencies on a MPLS interface
292  */
293 static adj_walk_rc_t
295  void *ctx)
296 {
297  mpls_tunnel_stack(ai);
298 
299  return (ADJ_WALK_RC_CONTINUE);
300 }
301 
302 static void
304 {
305  fib_protocol_t proto;
306 
307  /*
308  * walk all the adjacencies on the MPLS interface and restack them
309  */
310  if (mt->mt_flags & MPLS_TUNNEL_FLAG_L2)
311  {
312  /*
313  * Stack a load-balance that drops, whilst we have no paths
314  */
316  dpo_id_t dpo = DPO_INVALID;
317 
321  &dpo);
322 
325  &mt->mt_l2_lb,
326  &dpo);
327  dpo_reset(&dpo);
328  }
329  else
330  {
331  FOR_EACH_FIB_PROTOCOL(proto)
332  {
334  proto,
336  NULL);
337  }
338  }
339 }
340 
341 static clib_error_t *
343  u32 hw_if_index,
344  u32 flags)
345 {
347  mpls_tunnel_t *mt;
348 
349  hi = vnet_get_hw_interface (vnm, hw_if_index);
350 
352 
353  if (NULL == mt)
354  return (NULL);
355 
357  vnet_hw_interface_set_flags (vnm, hw_if_index,
359  else
360  vnet_hw_interface_set_flags (vnm, hw_if_index, 0 /* down */);
361 
363 
364  return (NULL);
365 }
366 
367 /**
368  * @brief Fixup the adj rewrite post encap. This is a no-op since the
369  * rewrite is a stack of labels.
370  */
371 static void
373  ip_adjacency_t *adj,
374  vlib_buffer_t *b0,
375  const void*data)
376 {
377  /*
378  * A no-op w.r.t. the header. but reset the 'have we pushed any
379  * MPLS labels onto the packet' flag. That way when we enter the
380  * tunnel we'll get a TTL set to 255
381  */
382  vnet_buffer(b0)->mpls.first = 0;
383 }
384 
385 static void
388  adj_index_t ai)
389 {
390  ip_adjacency_t *adj;
391 
392  ASSERT(ADJ_INDEX_INVALID != ai);
393 
394  adj = adj_get(ai);
395 
396  switch (adj->lookup_next_index)
397  {
398  case IP_LOOKUP_NEXT_ARP:
402  NULL,
405  break;
407  /*
408  * Construct a partial rewrite from the known ethernet mcast dest MAC
409  * There's no MAC fixup, so the last 2 parameters are 0
410  */
412  NULL,
415  0, 0);
416  break;
417 
418  case IP_LOOKUP_NEXT_DROP:
419  case IP_LOOKUP_NEXT_PUNT:
425  case IP_LOOKUP_N_NEXT:
426  ASSERT (0);
427  break;
428  }
429 
430  mpls_tunnel_stack(ai);
431 }
432 
433 static u8 *
434 format_mpls_tunnel_name (u8 * s, va_list * args)
435 {
436  u32 dev_instance = va_arg (*args, u32);
437  return format (s, "mpls-tunnel%d", dev_instance);
438 }
439 
440 static u8 *
441 format_mpls_tunnel_device (u8 * s, va_list * args)
442 {
443  u32 dev_instance = va_arg (*args, u32);
444  CLIB_UNUSED (int verbose) = va_arg (*args, int);
445 
446  return (format (s, "MPLS-tunnel: id %d\n", dev_instance));
447 }
448 
449 /**
450  * @brief Packet trace structure
451  */
452 typedef struct mpls_tunnel_trace_t_
453 {
454  /**
455  * Tunnel-id / index in tunnel vector
456  */
459 
460 static u8 *
462  va_list * args)
463 {
464  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
465  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
466  mpls_tunnel_trace_t * t = va_arg (*args, mpls_tunnel_trace_t *);
467 
468  s = format (s, "MPLS: tunnel %d", t->tunnel_id);
469  return s;
470 }
471 
472 /**
473  * @brief TX function. Only called L2. L3 traffic uses the adj-midchains
474  */
475 static uword
477  vlib_node_runtime_t * node,
478  vlib_frame_t * frame)
479 {
480  u32 next_index;
481  u32 * from, * to_next, n_left_from, n_left_to_next;
482  vnet_interface_output_runtime_t * rd = (void *) node->runtime_data;
483  const mpls_tunnel_t *mt;
484 
485  mt = pool_elt_at_index(mpls_tunnel_pool, rd->dev_instance);
486 
487  /* Vector of buffer / pkt indices we're supposed to process */
488  from = vlib_frame_vector_args (frame);
489 
490  /* Number of buffers / pkts */
491  n_left_from = frame->n_vectors;
492 
493  /* Speculatively send the first buffer to the last disposition we used */
494  next_index = node->cached_next_index;
495 
496  while (n_left_from > 0)
497  {
498  /* set up to enqueue to our disposition with index = next_index */
499  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
500 
501  /*
502  * FIXME DUAL LOOP
503  */
504  while (n_left_from > 0 && n_left_to_next > 0)
505  {
506  vlib_buffer_t * b0;
507  u32 bi0;
508 
509  bi0 = from[0];
510  to_next[0] = bi0;
511  from += 1;
512  to_next += 1;
513  n_left_from -= 1;
514  n_left_to_next -= 1;
515 
516  b0 = vlib_get_buffer(vm, bi0);
517 
518  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mt->mt_l2_lb.dpoi_index;
519  /* since we are coming out of the L2 world, where the vlib_buffer
520  * union is used for other things, make sure it is clean for
521  * MPLS from now on.
522  */
523  vnet_buffer(b0)->mpls.first = 0;
524 
525  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
526  {
527  mpls_tunnel_trace_t *tr = vlib_add_trace (vm, node,
528  b0, sizeof (*tr));
529  tr->tunnel_id = rd->dev_instance;
530  }
531 
532  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
533  to_next, n_left_to_next,
534  bi0, mt->mt_l2_lb.dpoi_next_node);
535  }
536 
537  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
538  }
539 
540  return frame->n_vectors;
541 }
542 
543 VNET_DEVICE_CLASS (mpls_tunnel_class) = {
544  .name = "MPLS tunnel device",
545  .format_device_name = format_mpls_tunnel_name,
546  .format_device = format_mpls_tunnel_device,
547  .format_tx_trace = format_mpls_tunnel_tx_trace,
548  .tx_function = mpls_tunnel_tx,
549  .admin_up_down_function = mpls_tunnel_admin_up_down,
550 };
551 
552 VNET_HW_INTERFACE_CLASS (mpls_tunnel_hw_interface_class) = {
553  .name = "MPLS-Tunnel",
554  .update_adjacency = mpls_tunnel_update_adj,
555  .build_rewrite = mpls_tunnel_build_rewrite,
557 };
558 
559 const mpls_tunnel_t *
561 {
562  return (pool_elt_at_index(mpls_tunnel_pool, mti));
563 }
564 
565 /**
566  * @brief Walk all the MPLS tunnels
567  */
568 void
570  void *ctx)
571 {
572  u32 mti;
573 
574  pool_foreach_index(mti, mpls_tunnel_pool,
575  ({
576  cb(mti, ctx);
577  }));
578 }
579 
580 void
582 {
583  mpls_tunnel_t *mt;
584 
585  mt = mpls_tunnel_get_from_sw_if_index(sw_if_index);
586 
587  if (NULL == mt)
588  return;
589 
592  mt->mt_sibling_index);
593  dpo_reset(&mt->mt_l2_lb);
594 
596 
597  pool_put(mpls_tunnel_pool, mt);
599 }
600 
601 u32
603  u8 is_multicast)
604 {
606  mpls_tunnel_t *mt;
607  vnet_main_t * vnm;
608  u32 mti;
609 
610  vnm = vnet_get_main();
611  pool_get(mpls_tunnel_pool, mt);
612  memset (mt, 0, sizeof (*mt));
613  mti = mt - mpls_tunnel_pool;
617 
618  if (is_multicast)
620  if (l2_only)
622 
623  /*
624  * Create a new tunnel HW interface
625  */
627  vnm,
628  mpls_tunnel_class.index,
629  mti,
630  mpls_tunnel_hw_interface_class.index,
631  mti);
632  hi = vnet_get_hw_interface (vnm, mt->mt_hw_if_index);
633 
634  /* Standard default MPLS tunnel MTU. */
635  vnet_sw_interface_set_mtu (vnm, hi->sw_if_index, 9000);
636 
637  /*
638  * Add the new tunnel to the tunnel DB - key:SW if index
639  */
640  mt->mt_sw_if_index = hi->sw_if_index;
642  mpls_tunnel_db[mt->mt_sw_if_index] = mti;
643 
644  return (mt->mt_sw_if_index);
645 }
646 
647 void
649  fib_route_path_t *rpaths)
650 {
651  mpls_tunnel_t *mt;
652  u32 mti;
653 
654  mt = mpls_tunnel_get_from_sw_if_index(sw_if_index);
655 
656  if (NULL == mt)
657  return;
658 
659  mti = mt - mpls_tunnel_pool;
660 
661  /*
662  * construct a path-list from the path provided
663  */
665  {
669  mti);
670  }
671  else
672  {
673  fib_node_index_t old_pl_index;
674 
675  old_pl_index = mt->mt_path_list;
676 
677  mt->mt_path_list =
678  fib_path_list_copy_and_path_add(old_pl_index,
680  rpaths);
681 
682  fib_path_list_child_remove(old_pl_index,
683  mt->mt_sibling_index);
686  mti);
687  /*
688  * re-resolve all the path-extensions with the new path-list
689  */
691  }
693  mt->mt_path_list,
695  rpaths);
697 }
698 
699 int
701  fib_route_path_t *rpaths)
702 {
703  mpls_tunnel_t *mt;
704  u32 mti;
705 
706  mt = mpls_tunnel_get_from_sw_if_index(sw_if_index);
707 
708  if (NULL == mt)
709  return (0);
710 
711  mti = mt - mpls_tunnel_pool;
712 
713  /*
714  * construct a path-list from the path provided
715  */
717  {
718  /* can't remove a path if we have onoe */
719  return (0);
720  }
721  else
722  {
723  fib_node_index_t old_pl_index;
724 
725  old_pl_index = mt->mt_path_list;
726 
727  mt->mt_path_list =
730  rpaths);
731 
732  fib_path_list_child_remove(old_pl_index,
733  mt->mt_sibling_index);
734 
736  {
737  /* no paths left */
738  return (0);
739  }
740  else
741  {
742  mt->mt_sibling_index =
745  mti);
746  }
747  /*
748  * find the matching path extension and remove it
749  */
752  rpaths);
753 
754  /*
755  * re-resolve all the path-extensions with the new path-list
756  */
758  mt->mt_path_list);
759 
761  }
762 
764 }
765 
766 int
768 {
769  mpls_tunnel_t *mt;
770 
771  mt = mpls_tunnel_get_from_sw_if_index(sw_if_index);
772 
773  if (NULL == mt)
774  return (~0);
775 
776  return (mt - mpls_tunnel_pool);
777 }
778 
779 static clib_error_t *
781  unformat_input_t * input,
782  vlib_cli_command_t * cmd)
783 {
784  unformat_input_t _line_input, * line_input = &_line_input;
785  vnet_main_t * vnm = vnet_get_main();
786  u8 is_del = 0, l2_only = 0, is_multicast =0;
787  fib_route_path_t rpath, *rpaths = NULL;
788  u32 sw_if_index = ~0, payload_proto;
789  clib_error_t *error = NULL;
790 
791  memset(&rpath, 0, sizeof(rpath));
792  payload_proto = DPO_PROTO_MPLS;
793 
794  /* Get a line of input. */
795  if (! unformat_user (input, unformat_line_input, line_input))
796  return 0;
797 
798  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
799  {
800  if (unformat (line_input, "del %U",
802  &sw_if_index))
803  is_del = 1;
804  else if (unformat (line_input, "add %U",
806  &sw_if_index))
807  is_del = 0;
808  else if (unformat (line_input, "add"))
809  is_del = 0;
810  else if (unformat (line_input, "l2-only"))
811  l2_only = 1;
812  else if (unformat (line_input, "multicast"))
813  is_multicast = 1;
814  else if (unformat (line_input, "via %U",
816  &rpath, &payload_proto))
817  vec_add1(rpaths, rpath);
818  else
819  {
820  error = clib_error_return (0, "unknown input '%U'",
821  format_unformat_error, line_input);
822  goto done;
823  }
824  }
825 
826  if (is_del)
827  {
828  if (NULL == rpaths)
829  {
830  vnet_mpls_tunnel_del(sw_if_index);
831  }
832  else if (!vnet_mpls_tunnel_path_remove(sw_if_index, rpaths))
833  {
834  vnet_mpls_tunnel_del(sw_if_index);
835  }
836  }
837  else
838  {
839  if (0 == vec_len(rpath.frp_label_stack))
840  {
841  error = clib_error_return (0, "No Output Labels '%U'",
842  format_unformat_error, line_input);
843  goto done;
844  }
845 
846  if (~0 == sw_if_index)
847  {
848  sw_if_index = vnet_mpls_tunnel_create(l2_only, is_multicast);
849  }
850  vnet_mpls_tunnel_path_add(sw_if_index, rpaths);
851  }
852 
853 done:
854  vec_free(rpaths);
855  unformat_free (line_input);
856 
857  return error;
858 }
859 
860 /*?
861  * This command create a uni-directional MPLS tunnel
862  *
863  * @cliexpar
864  * @cliexstart{create mpls tunnel}
865  * create mpls tunnel via 10.0.0.1 GigEthernet0/8/0 out-label 33 out-label 34
866  * @cliexend
867  ?*/
868 VLIB_CLI_COMMAND (create_mpls_tunnel_command, static) = {
869  .path = "mpls tunnel",
870  .short_help =
871  "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>]",
873 };
874 
875 static u8 *
876 format_mpls_tunnel (u8 * s, va_list * args)
877 {
878  mpls_tunnel_t *mt = va_arg (*args, mpls_tunnel_t *);
880 
881  s = format(s, "mpls_tunnel%d: sw_if_index:%d hw_if_index:%d",
882  mt - mpls_tunnel_pool,
883  mt->mt_sw_if_index,
884  mt->mt_hw_if_index);
885  if (MPLS_TUNNEL_FLAG_NONE != mt->mt_flags) {
886  s = format(s, " \n flags:");
888  if ((1<<attr) & mt->mt_flags) {
889  s = format (s, "%s,", mpls_tunnel_attribute_names[attr]);
890  }
891  }
892  }
893  s = format(s, "\n via:\n");
895  s = format(s, "%U", format_fib_path_ext_list, &mt->mt_path_exts);
896  s = format(s, "\n");
897 
898  if (mt->mt_flags & MPLS_TUNNEL_FLAG_L2)
899  {
900  s = format(s, " forwarding: %U\n",
903  s = format(s, " %U\n", format_dpo_id, &mt->mt_l2_lb, 2);
904  }
905 
906  return (s);
907 }
908 
909 static clib_error_t *
911  unformat_input_t * input,
912  vlib_cli_command_t * cmd)
913 {
914  mpls_tunnel_t * mt;
915  u32 mti = ~0;
916 
917  if (pool_elts (mpls_tunnel_pool) == 0)
918  vlib_cli_output (vm, "No MPLS tunnels configured...");
919 
921  {
922  if (unformat (input, "%d", &mti))
923  ;
924  else
925  break;
926  }
927 
928  if (~0 == mti)
929  {
930  pool_foreach (mt, mpls_tunnel_pool,
931  ({
932  vlib_cli_output (vm, "[@%d] %U",
933  mt - mpls_tunnel_pool,
934  format_mpls_tunnel, mt);
935  }));
936  }
937  else
938  {
939  if (pool_is_free_index(mpls_tunnel_pool, mti))
940  return clib_error_return (0, "Not a tunnel index %d", mti);
941 
942  mt = pool_elt_at_index(mpls_tunnel_pool, mti);
943 
944  vlib_cli_output (vm, "[@%d] %U",
945  mt - mpls_tunnel_pool,
946  format_mpls_tunnel, mt);
947  }
948 
949  return 0;
950 }
951 
952 /*?
953  * This command to show MPLS tunnels
954  *
955  * @cliexpar
956  * @cliexstart{sh mpls tunnel 2}
957  * [@2] mpls_tunnel2: sw_if_index:5 hw_if_index:5
958  * label-stack:
959  * 3,
960  * via:
961  * index:26 locks:1 proto:ipv4 uPRF-list:26 len:1 itfs:[2, ]
962  * index:26 pl-index:26 ipv4 weight=1 attached-nexthop: oper-flags:resolved,
963  * 10.0.0.2 loop0
964  * [@0]: ipv4 via 10.0.0.2 loop0: IP4: de:ad:00:00:00:00 -> 00:00:11:aa:bb:cc
965  * @cliexend
966  ?*/
967 VLIB_CLI_COMMAND (show_mpls_tunnel_command, static) = {
968  .path = "show mpls tunnel",
969  .function = show_mpls_tunnel_command_fn,
970 };
971 
972 static mpls_tunnel_t *
974 {
976  return ((mpls_tunnel_t*) (((char*)node) -
977  STRUCT_OFFSET_OF(mpls_tunnel_t, mt_node)));
978 }
979 
980 /**
981  * Function definition to backwalk a FIB node
982  */
986 {
988 
990 }
991 
992 /**
993  * Function definition to get a FIB node from its index
994  */
995 static fib_node_t*
997 {
998  mpls_tunnel_t * mt;
999 
1000  mt = pool_elt_at_index(mpls_tunnel_pool, index);
1001 
1002  return (&mt->mt_node);
1003 }
1004 
1005 /**
1006  * Function definition to inform the FIB node that its last lock has gone.
1007  */
1008 static void
1010 {
1011  /*
1012  * The MPLS MPLS tunnel is a root of the graph. As such
1013  * it never has children and thus is never locked.
1014  */
1015  ASSERT(0);
1016 }
1017 
1018 /*
1019  * Virtual function table registered by MPLS MPLS tunnels
1020  * for participation in the FIB object graph.
1021  */
1022 const static fib_node_vft_t mpls_vft = {
1024  .fnv_last_lock = mpls_tunnel_last_lock_gone,
1025  .fnv_back_walk = mpls_tunnel_back_walk,
1026 };
1027 
1028 static clib_error_t *
1030 {
1032 
1033  return 0;
1034 }
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:437
int fib_path_is_resolved(fib_node_index_t path_index)
Definition: fib_path.c:2569
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:530
static u8 * format_mpls_tunnel_tx_trace(u8 *s, va_list *args)
Definition: mpls_tunnel.c:461
vmrglw vmrglh hi
Packet trace structure.
Definition: mpls_tunnel.c:452
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:387
#define CLIB_UNUSED(x)
Definition: clib.h:81
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 *rpath)
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: interface.c:469
void fib_path_list_child_remove(fib_node_index_t path_list_index, u32 si)
u8 runtime_data[0]
Function dependent node-runtime data.
Definition: node.h:521
A representation of a path as described by a route producer.
Definition: fib_types.h:470
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:98
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
fib_node_index_t mt_path_list
The path-list over which the tunnel&#39;s destination is reachable.
Definition: mpls_tunnel.h:86
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:434
static int dpo_id_is_valid(const dpo_id_t *dpoi)
Return true if the DPO object is valid, i.e.
Definition: dpo.h:207
#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:400
#define NULL
Definition: clib.h:57
mpls_tunnel_flags_t mt_flags
Tunnel flags.
Definition: mpls_tunnel.h:65
Broadcasr Adjacency.
Definition: adj.h:85
IP unicast adjacency.
Definition: adj.h:185
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:410
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:342
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:523
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:983
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:64
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
unformat_function_t unformat_vnet_sw_interface
static uword mpls_tunnel_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
TX function.
Definition: mpls_tunnel.c:476
static u8 * format_mpls_tunnel_name(u8 *s, va_list *args)
Definition: mpls_tunnel.c:434
#define VNET_HW_INTERFACE_FLAG_LINK_UP
Definition: interface.h:494
static void mpls_tunnel_fixup(vlib_main_t *vm, ip_adjacency_t *adj, vlib_buffer_t *b0, const void *data)
Fixup the adj rewrite post encap.
Definition: mpls_tunnel.c:372
const mpls_tunnel_t * mpls_tunnel_get(u32 mti)
Definition: mpls_tunnel.c:560
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:228
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:441
void(* mpls_tunnel_walk_cb_t)(u32 index, void *ctx)
Callback function invoked while walking MPLS tunnels.
Definition: mpls_tunnel.h:134
unsigned char u8
Definition: types.h:56
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:984
#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:206
index_t load_balance_create(u32 n_buckets, dpo_proto_t lb_proto, flow_hash_config_t fhc)
Definition: load_balance.c:203
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:380
memset(h->entries, 0, sizeof(h->entries[0])*entries)
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:443
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:163
static u32 * mpls_tunnel_db
DB of SW index to tunnel index.
Definition: mpls_tunnel.c:37
u32 sw_if_index
Definition: vxlan_gbp.api:39
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)
#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:96
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:503
unsigned int u32
Definition: types.h:88
Contribute an object that is to be used to forward Ethernet packets.
Definition: fib_types.h:141
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
static u8 * format_mpls_tunnel(u8 *s, va_list *args)
Definition: mpls_tunnel.c:876
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:703
#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
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:168
void vnet_mpls_tunnel_del(u32 sw_if_index)
Delete an MPLS tunnel.
Definition: mpls_tunnel.c:581
#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:464
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:42
int vnet_mpls_tunnel_get_index(u32 sw_if_index)
return the tunnel index from the sw_if_index
Definition: mpls_tunnel.c:767
static uword vnet_hw_interface_get_flags(vnet_main_t *vnm, u32 hw_if_index)
long ctx[MAX_CONNS]
Definition: main.c:144
struct _unformat_input_t unformat_input_t
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:274
#define FOR_EACH_FIB_PROTOCOL(_item)
Definition: fib_types.h:65
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:48
#define PREDICT_FALSE(x)
Definition: clib.h:107
fib_mpls_label_t * frp_label_stack
The outgoing MPLS label Stack.
Definition: fib_types.h:525
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:91
fib_node_type_t fn_type
The node&#39;s type.
Definition: fib_node.h:293
#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
An node in the FIB graph.
Definition: fib_node.h:289
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:364
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:294
u32 flags
Definition: vhost_user.h:115
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:457
Adjacency to drop this packet.
Definition: adj.h:53
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
u16 n_vectors
Definition: node.h:401
static u8 * mpls_tunnel_build_rewrite_i(void)
Build a rewrite string for the MPLS tunnel.
Definition: mpls_tunnel.c:62
vlib_main_t * vm
Definition: buffer.c:294
VNET_DEVICE_CLASS(mpls_tunnel_class)
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:339
Multicast Midchain Adjacency.
Definition: adj.h:89
static void mpls_tunnel_restack(mpls_tunnel_t *mt)
Definition: mpls_tunnel.c:303
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:506
fib_node_get_t fnv_get
Definition: fib_node.h:277
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:425
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:30
void mpls_tunnel_walk(mpls_tunnel_walk_cb_t cb, void *ctx)
Walk all the MPLS tunnels.
Definition: mpls_tunnel.c:569
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:271
u32 adj_index_t
An index for adjacencies.
Definition: adj_types.h:30
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:455
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:136
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:185
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 the neighbour Adjacencies on a given interface.
Definition: adj_nbr.c:572
static clib_error_t * mpls_tunnel_init(vlib_main_t *vm)
Definition: mpls_tunnel.c:1029
Context passed between object during a back walk.
Definition: fib_node.h:202
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:155
static mpls_tunnel_t * mpls_tunnel_pool
pool of tunnel instances
Definition: mpls_tunnel.c:32
This packets follow a mid-chain adjacency.
Definition: adj.h:76
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:513
u32 vnet_mpls_tunnel_create(u8 l2_only, u8 is_multicast)
Create a new MPLS tunnel.
Definition: mpls_tunnel.c:602
#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:700
void adj_nbr_midchain_stack(adj_index_t adj_index, const dpo_id_t *next)
adj_nbr_midchain_stack
Definition: adj_midchain.c:571
enum vnet_link_t_ vnet_link_t
Link Type: A description of the protocol of packets on the link.
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:76
u8 * format_fib_forw_chain_type(u8 *s, va_list *args)
Definition: fib_types.c:48
#define IP_FLOW_HASH_DEFAULT
Default: 5-tuple without the "reverse" bit.
Definition: lookup.h:69
void adj_nbr_midchain_unstack(adj_index_t adj_index)
adj_nbr_midchain_unstack
Definition: adj_midchain.c:549
u8 * format_dpo_id(u8 *s, va_list *args)
Format a DPO_id_t oject
Definition: dpo.c:147
u32 flow_hash_config_t
A flow hash configuration is a mask of the flow hash options.
Definition: lookup.h:82
void vnet_delete_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
Definition: interface.c:913
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:82
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:57
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:648
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:184
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:31
void fib_path_ext_list_resolve(fib_path_ext_list_t *list, fib_node_index_t path_list_index)
Definition: fib_path_ext.c:413
#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:200
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:780
static void mpls_tunnel_stack(adj_index_t ai)
mpls_tunnel_stack
Definition: mpls_tunnel.c:234
u8 * fib_path_list_format(fib_node_index_t path_list_index, u8 *s)
u64 uword
Definition: types.h:112
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:267
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:195
a point 2 point interface
Definition: interface.h:381
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:1009
One path from an [EU]CMP set that the client wants to add to a load-balance object.
Definition: load_balance.h:62
void vnet_sw_interface_set_mtu(vnet_main_t *vnm, u32 sw_if_index, u32 mtu)
Definition: interface.c:605
A FIB graph nodes virtual function table.
Definition: fib_node.h:276
#define vnet_buffer(b)
Definition: buffer.h:344
load_balance_path_t * next_hops
Definition: mpls_tunnel.c:92
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:231
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:458
u32 mt_sw_if_index
The SW interface index of the tunnel interfaces.
Definition: mpls_tunnel.h:81
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:71
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:996
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:180
enum mpls_tunnel_attribute_t_ mpls_tunnel_attribute_t
#define pool_foreach_index(i, v, body)
Iterate pool by index.
Definition: pool.h:488
#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:486
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:116
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:725
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:58
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
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:910
fib_forward_chain_type_t fct
Definition: mpls_tunnel.c:94
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:369
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:140
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:386
static mpls_tunnel_t * mpls_tunnel_from_fib_node(fib_node_t *node)
Definition: mpls_tunnel.c:973
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128