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