FD.io VPP  v21.06-1-gbb7418cf9
Vector Packet Processing
ip_path_mtu.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * ip_path_mtu.c
4  *
5  * Copyright (c) 2021 Graphiant.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19 
20 #include <vnet/ip/ip_path_mtu.h>
21 #include <vnet/ip/ip_frag.h>
22 #include <vnet/adj/adj_delegate.h>
23 #include <vnet/adj/adj_nbr.h>
24 #include <vnet/fib/fib_table.h>
26 
27 #include <vnet/dpo/drop_dpo.h>
28 
29 /**
30  * Path MTU
31  *
32  * A path is a peer. A peer is known by an IP address (in a table).
33  * Insert a DPO in the forwarding chain for the peer to perform the
34  * fragmentation.
35  * For attached peers, all traffic will use the peer's adjacency, there
36  * is already an MTU chekc in the adjacency (for the link's MTU) so as an
37  * optimisation, instead of using a DPO, we add a delegate to the adjacency
38  * to set the adjacency's MTU to the path MTU.
39  */
40 
41 /**
42  * the logger
43  */
45 
48 
49 /**
50  * DPO pool
51  */
53 
54 /**
55  * DPO type registered for these GBP FWD
56  */
58 
59 /**
60  * Fib node type for the tracker
61  */
63 
64 /**
65  * Path MTU tracker pool
66  */
68 
69 /**
70  * Delegate added to adjacencies to track path MTU
71  */
73 {
76 
78 
79 /* DB of all FIB PMTU settings */
80 typedef struct ip_pmtu_key_t_
81 {
82  ip46_address_t nh;
85 } __clib_packed ip_pmtu_key_t;
86 
87 static uword *ip_pmtu_db;
88 
89 #define IP_PMTU_TRKR_DBG(_ipt, _fmt, _args...) \
90  { \
91  vlib_log_debug (ip_pmtu_logger, "[%U]: " _fmt ": ", format_ip_pmtu, \
92  _ipt - ip_pmtu_pool, ##_args); \
93  }
94 #define IP_PMTU_DBG(_fmt, _args...) \
95  { \
96  vlib_log_debug (ip_pmtu_logger, _fmt ": ", ##_args); \
97  }
98 
99 static u8 *
100 format_ip_pmtu_flags (u8 *s, va_list *ap)
101 {
102  ip_pmtu_flags_t f = va_arg (*ap, ip_pmtu_flags_t);
103 
104  if (0)
105  ;
106 #define _(a, b, c) else if (f & IP_PMTU_FLAG_##a) s = format (s, "%s ", c);
108 #undef _
109 
110  return (s);
111 }
112 
113 u32
115 {
116  const fib_prefix_t *pfx;
117  u32 fib_index;
118 
119  pfx = fib_entry_get_prefix (ipt->ipt_fib_entry);
120  fib_index = fib_entry_get_fib_index (ipt->ipt_fib_entry);
121 
122  return (fib_table_get_table_id (fib_index, pfx->fp_proto));
123 }
124 
125 void
127 {
128  const fib_prefix_t *pfx;
129 
130  pfx = fib_entry_get_prefix (ipt->ipt_fib_entry);
131  ip_address_from_46 (&pfx->fp_addr, pfx->fp_proto, ip);
132 }
133 
134 static u8 *
135 format_ip_pmtu (u8 *s, va_list *ap)
136 {
137  ip_pmtu_t *ipt;
138  index_t ipti = va_arg (*ap, index_t);
139  const fib_prefix_t *pfx;
140  u32 fib_index;
141 
142  ipt = pool_elt_at_index (ip_pmtu_pool, ipti);
143  pfx = fib_entry_get_prefix (ipt->ipt_fib_entry);
144  fib_index = fib_entry_get_fib_index (ipt->ipt_fib_entry);
145 
146  s =
147  format (s, "[%d] [tbl:[%d:%d]] %U pmtu:[cfg:%d, oper:%d, parent:%d] [%U]",
148  ipti, ip_pmtu_get_table_id (ipt), fib_index, format_fib_prefix,
149  pfx, ipt->ipt_cfg_pmtu, ipt->ipt_oper_pmtu, ipt->ipt_parent_pmtu,
151 
152  return (s);
153 }
154 
155 static u8 *
157 {
159 
160  ip_adj = pool_elt_at_index (ip_path_mtu_adj_delegate_pool, aed->ad_index);
161 
162  s = format (s, "IP path-MTU: %d", ip_adj->pmtu);
163 
164  return (s);
165 }
166 
167 static void
169 {
171  const ip_pmtu_t *ipt;
172  ip_adjacency_t *adj;
173  u32 table_id;
174  uword *p;
175 
176  adj = adj_get (ai);
177 
178  switch (adj->lookup_next_index)
179  {
180  case IP_LOOKUP_NEXT_DROP:
181  case IP_LOOKUP_NEXT_PUNT:
188  case IP_LOOKUP_N_NEXT:
189  return;
190 
191  case IP_LOOKUP_NEXT_ARP:
194  break;
195  }
196 
198  adj->ia_nh_proto, adj->rewrite_header.sw_if_index);
199 
200  ip_pmtu_key_t key = {
201  .nh = adj->sub_type.nbr.next_hop,
202  .table_id = table_id,
203  .fproto = adj->ia_nh_proto,
204  };
205 
206  p = hash_get_mem (ip_pmtu_db, &key);
207 
208  if (NULL == p)
209  return;
210 
211  ipt = pool_elt_at_index (ip_pmtu_pool, p[0]);
212 
213  pool_get (ip_path_mtu_adj_delegate_pool, ipp_ad);
214  ipp_ad->pmtu = ipt->ipt_cfg_pmtu;
215 
217  ipp_ad - ip_path_mtu_adj_delegate_pool);
218 
219  adj_nbr_set_mtu (ai, ipp_ad->pmtu);
220 
221  IP_PMTU_TRKR_DBG (ipt, "adj-added:", ai);
222 }
223 
224 static void
226 {
227  pool_put_index (ip_path_mtu_adj_delegate_pool, ad->ad_index);
228 }
229 
230 static void
232 {
234 
235  ipp_ad = pool_elt_at_index (ip_path_mtu_adj_delegate_pool, ad->ad_index);
236 
237  adj_nbr_set_mtu (ad->ad_adj_index, ipp_ad->pmtu);
238 }
239 
240 const adj_delegate_vft_t ip_path_adj_delegate_vft = {
242  .adv_adj_deleted = ip_pmtu_adj_delegate_adj_deleted,
243  .adv_adj_modified = ip_pmtu_adj_delegate_adj_modified,
244  .adv_adj_created = ip_pmtu_adj_delegate_adj_created,
245 };
246 
247 static bool
249 {
250  return (pmtu == 0 || pmtu == 0xffff);
251 }
252 
253 static adj_walk_rc_t
255 {
256  adj_delegate_t *ad;
257 
259 
260  if (ad)
261  {
262  adj_nbr_set_mtu (ai, 0);
263 
264  pool_put_index (ip_path_mtu_adj_delegate_pool, ad->ad_index);
266  }
267  return (ADJ_WALK_RC_CONTINUE);
268 }
269 
270 static adj_walk_rc_t
272 {
274  adj_delegate_t *ad;
275  u16 *pmtup;
276 
277  pmtup = ctx;
279 
280  if (ad)
281  ipp_ad = pool_elt_at_index (ip_path_mtu_adj_delegate_pool, ad->ad_index);
282  else
283  {
284  pool_get (ip_path_mtu_adj_delegate_pool, ipp_ad);
285 
287  ipp_ad - ip_path_mtu_adj_delegate_pool);
288  }
289 
290  ipp_ad->pmtu = *pmtup;
291 
292  adj_nbr_set_mtu (ai, ipp_ad->pmtu);
293 
294  return (ADJ_WALK_RC_CONTINUE);
295 }
296 
297 static ip_pmtu_dpo_t *
299 {
300  ip_pmtu_dpo_t *ipm;
301 
302  pool_get_aligned_zero (ip_pmtu_dpo_pool, ipm, sizeof (ip_pmtu_dpo_t));
303 
304  return (ipm);
305 }
306 
307 static ip_pmtu_dpo_t *
309 {
311 
312  return (ip_pmtu_dpo_get (dpo->dpoi_index));
313 }
314 
315 static index_t
317 {
318  return (ipm - ip_pmtu_dpo_pool);
319 }
320 
321 static void
323 {
324  ip_pmtu_dpo_t *ipm;
325 
326  ipm = ip_pmtu_dpo_get_from_dpo (dpo);
327  ipm->ipm_locks++;
328 }
329 
330 static void
332 {
333  ip_pmtu_dpo_t *ipm;
334 
335  ipm = ip_pmtu_dpo_get_from_dpo (dpo);
336  ipm->ipm_locks--;
337 
338  if (0 == ipm->ipm_locks)
339  {
340  dpo_reset (&ipm->ipm_dpo);
341  pool_put (ip_pmtu_dpo_pool, ipm);
342  }
343 }
344 
345 static u32
347 {
348  ip_pmtu_dpo_t *ipm;
349 
350  ipm = ip_pmtu_dpo_get_from_dpo (dpo);
351 
352  return (dpo_get_urpf (&ipm->ipm_dpo));
353 }
354 
355 void
357 {
358  ip_pmtu_dpo_t *ipm;
359  dpo_id_t parent = DPO_INVALID;
360 
361  ipm = ip_pmtu_dpo_alloc ();
362 
363  ipm->ipm_proto = fib_proto_to_dpo (fproto);
364  ipm->ipm_pmtu = pmtu;
365 
366  dpo_copy (&parent, drop_dpo_get (ipm->ipm_proto));
367  dpo_stack (ip_pmtu_dpo_type, ipm->ipm_proto, &ipm->ipm_dpo, &parent);
369 }
370 
371 u8 *
372 format_ip_pmtu_dpo (u8 *s, va_list *ap)
373 {
374  index_t index = va_arg (*ap, index_t);
375  u32 indent = va_arg (*ap, u32);
376  ip_pmtu_dpo_t *ipm = ip_pmtu_dpo_get (index);
377 
378  s = format (s, "ip-pmtu-dpo: %U, mtu:%d", format_dpo_proto, ipm->ipm_proto,
379  ipm->ipm_pmtu);
380  s = format (s, "\n%U", format_white_space, indent + 2);
381  s = format (s, "%U", format_dpo_id, &ipm->ipm_dpo, indent + 4);
382 
383  return (s);
384 }
385 
386 /**
387  * Interpose a path MTU DPO
388  */
389 static void
390 ip_pmtu_dpo_interpose (const dpo_id_t *original, const dpo_id_t *parent,
391  dpo_id_t *clone)
392 {
393  ip_pmtu_dpo_t *ipm, *ipm_clone;
394 
395  ipm_clone = ip_pmtu_dpo_alloc ();
396  ipm = ip_pmtu_dpo_get (original->dpoi_index);
397 
398  ipm_clone->ipm_proto = ipm->ipm_proto;
399  ipm_clone->ipm_pmtu = ipm->ipm_pmtu;
400 
401  dpo_stack (ip_pmtu_dpo_type, ipm_clone->ipm_proto, &ipm_clone->ipm_dpo,
402  parent);
403  dpo_set (clone, ip_pmtu_dpo_type, ipm_clone->ipm_proto,
404  ip_pmtu_dpo_get_index (ipm_clone));
405 }
406 
407 static u16
409 {
410  ip_pmtu_dpo_t *ipd;
411 
412  ipd = pool_elt_at_index (ip_pmtu_dpo_pool, dpo->dpoi_index);
413 
414  return (ipd->ipm_pmtu);
415 }
416 
417 const static dpo_vft_t ip_pmtu_dpo_vft = {
419  .dv_unlock = ip_pmtu_dpo_unlock,
420  .dv_format = format_ip_pmtu_dpo,
421  .dv_get_urpf = ip_pmtu_dpo_get_urpf,
422  .dv_mk_interpose = ip_pmtu_dpo_interpose,
423  .dv_get_mtu = ip_pmtu_dpo_get_mtu,
424 };
425 
426 /**
427  * @brief The per-protocol VLIB graph nodes that are assigned to a glean
428  * object.
429  *
430  * this means that these graph nodes are ones from which a glean is the
431  * parent object in the DPO-graph.
432  */
433 const static char *const ip_pmtu_dpo_ip4_nodes[] = {
434  "ip4-pmtu-dpo",
435  NULL,
436 };
437 
438 const static char *const ip_pmtu_dpo_ip6_nodes[] = {
439  "ip6-pmtu-dpo",
440  NULL,
441 };
442 
443 const static char *const *const ip_pmtu_dpo_nodes[DPO_PROTO_NUM] = {
446 };
447 
448 static bool
450 {
451  const fib_prefix_t *pfx;
452  u32 cover, fib_index;
453 
454  fib_index = fib_entry_get_fib_index (fib_entry);
455  pfx = fib_entry_get_prefix (fib_entry);
456 
457  /*
458  * If the tracked prefix's cover is attached, then all packets that
459  * are forwarded to this neighbour will use the adjacency, this is a
460  * more efficient place to perform the MTU check and fragging
461  */
462  cover = fib_table_get_less_specific (fib_index, pfx);
463 
464  return (FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags (cover) ||
466 }
467 
468 static index_t
469 ip_pmtu_alloc (u32 fib_index, const fib_prefix_t *pfx,
470  const ip_pmtu_key_t *key, u16 pmtu)
471 {
472  dpo_id_t ip_dpo = DPO_INVALID;
473  ip_pmtu_t *ipt;
474  fib_node_index_t cover;
475  const dpo_id_t *lb_dpo;
476  index_t ipti;
477 
478  pool_get (ip_pmtu_pool, ipt);
480 
481  ipti = ipt - ip_pmtu_pool;
482  hash_set_mem_alloc (&ip_pmtu_db, key, ipti);
483 
484  ipt->ipt_cfg_pmtu = pmtu;
485  ipt->ipt_fib_entry = fib_entry_track (fib_index, pfx, ip_pmtu_fib_type, ipti,
486  &ipt->ipt_sibling);
487 
488  /*
489  * If the tracked prefix's cover is attached, then all packets that
490  * are forwarded to this neighbour will use the adjacency, this is a
491  * more efficient place to perform the MTU check and fragging
492  */
493  cover = fib_table_get_less_specific (fib_index, pfx);
494 
496  {
498 
499  ipt->ipt_flags |= IP_PMTU_FLAG_ATTACHED;
500  ipt->ipt_oper_pmtu = ipt->ipt_cfg_pmtu;
501 
502  sw_if_index = fib_entry_get_resolving_interface (cover);
503 
504  /* walk all adjs to add/update delegate */
505  adj_nbr_walk_nh (sw_if_index, pfx->fp_proto, &pfx->fp_addr,
507  }
508  else
509  {
510  ipt->ipt_flags |= IP_PMTU_FLAG_REMOTE;
511 
513 
514  ipt->ipt_oper_pmtu = clib_min (dpo_get_mtu (lb_dpo), ipt->ipt_cfg_pmtu);
515 
516  /*
517  * interpose a policy DPO from the nh so that MTU is applied
518  */
519  ip_pmtu_dpo_add_or_lock (pfx->fp_proto, ipt->ipt_oper_pmtu, &ip_dpo);
520 
522  FIB_ENTRY_FLAG_INTERPOSE, &ip_dpo);
523  dpo_reset (&ip_dpo);
524  }
525 
526  IP_PMTU_TRKR_DBG (ipt, "create");
527 
528  return (ipti);
529 }
530 
531 static void
533 {
534  bool was_attached, is_attached;
535  const fib_prefix_t *pfx;
536  u32 fib_index;
537 
538  pfx = fib_entry_get_prefix (ipt->ipt_fib_entry);
539  fib_index = fib_entry_get_fib_index (ipt->ipt_fib_entry);
540 
541  was_attached = !!(ipt->ipt_flags & IP_PMTU_FLAG_ATTACHED);
542  is_attached = ip_mtu_fib_entry_is_attached (ipt->ipt_fib_entry);
543 
544  if (was_attached && !is_attached)
545  {
546  /* transition from attached to remote - walk all adjs to remove delegate
547  */
550  &ipt->ipt_oper_pmtu);
551  ipt->ipt_flags &= ~IP_PMTU_FLAG_ATTACHED;
552  }
553  if (!was_attached && is_attached)
554  {
555  /* transition from remote to attached - remove the DPO */
557  ipt->ipt_flags &= ~IP_PMTU_FLAG_REMOTE;
558  }
559 
560  if (is_attached)
561  {
562  /* walk all adjs to add/update delegate */
563  ipt->ipt_oper_pmtu = ipt->ipt_cfg_pmtu;
566  &ipt->ipt_oper_pmtu);
567  ipt->ipt_flags |= IP_PMTU_FLAG_ATTACHED;
568  }
569  else
570  {
571  const dpo_id_t *lb_dpo;
572  u16 dpo_mtu;
573 
575 
576  ipt->ipt_flags |= IP_PMTU_FLAG_REMOTE;
578  dpo_mtu = dpo_get_mtu (lb_dpo);
579 
580  ipt->ipt_oper_pmtu = clib_min (dpo_mtu, ipt->ipt_cfg_pmtu);
581 
582  /*
583  * if the configured path-MTU is less that the egress/interface then
584  * interpose a policy DPO from the nh so that MTU is applied
585  */
586  if (ipt->ipt_oper_pmtu < dpo_mtu)
587  {
588  dpo_id_t ip_dpo = DPO_INVALID;
589 
590  ip_pmtu_dpo_add_or_lock (pfx->fp_proto, ipt->ipt_oper_pmtu, &ip_dpo);
591 
593  fib_index, pfx, ip_pmtu_source, FIB_ENTRY_FLAG_INTERPOSE, &ip_dpo);
594  dpo_reset (&ip_dpo);
595  }
596  }
597  IP_PMTU_TRKR_DBG (ipt, "stack");
598 }
599 
600 static void
602 {
603  ip_pmtu_t *ipt;
604 
605  ipt = pool_elt_at_index (ip_pmtu_pool, ipti);
606  ipt->ipt_flags &= ~IP_PMTU_FLAG_STALE;
607  ipt->ipt_cfg_pmtu = pmtu;
608 
609  ip_pmtu_stack (ipt);
610 }
611 
612 static index_t
614 {
615  ip_pmtu_t *ipt;
616  const fib_prefix_t *pfx;
617 
618  ipt = pool_elt_at_index (ip_pmtu_pool, ipti);
619  pfx = fib_entry_get_prefix (ipt->ipt_fib_entry);
620 
621  IP_PMTU_TRKR_DBG (ipt, "destroy");
622 
623  if (ipt->ipt_flags & IP_PMTU_FLAG_REMOTE)
626  else
627  /* remove the delegate from all the adjacencies */
630  NULL);
631 
632  /*
633  * Drop the fib entry we're tracking
634  */
636 
637  /*
638  * remove from DB and return to pool
639  */
641  pool_put (ip_pmtu_pool, ipt);
642 
643  return (ipti);
644 }
645 
646 int
648 {
649  fib_prefix_t pfx;
650  u32 fib_index;
651  uword *p;
652 
653  ip_address_to_fib_prefix (nh, &pfx);
654  fib_index = fib_table_find (pfx.fp_proto, table_id);
655 
656  if (~0 == fib_index)
657  return (VNET_API_ERROR_NO_SUCH_TABLE);
658 
659  ip_pmtu_key_t key = {
660  .fproto = pfx.fp_proto,
661  .table_id = table_id,
662  .nh = pfx.fp_addr,
663  };
664 
665  p = hash_get_mem (ip_pmtu_db, &key);
666 
667  if (!ip_path_mtu_value_invalid (pmtu))
668  {
669  /* Add or update of path MTU */
670  if (NULL == p)
671  ip_pmtu_alloc (fib_index, &pfx, &key, pmtu);
672  else
673  ip_pmtu_update (p[0], pmtu);
674  }
675  else
676  {
677  if (NULL != p)
678  ip_pmtu_destroy (p[0], &key);
679  }
680 
681  return (0);
682 }
683 
684 static walk_rc_t
686 {
687  ip_pmtu_t *ipt;
688 
689  ipt = ip_path_mtu_get (ipti);
690 
691  ipt->ipt_flags |= IP_PMTU_FLAG_STALE;
692 
693  return (WALK_CONTINUE);
694 }
695 
697 {
700 
701 static walk_rc_t
703 {
705  ip_pmtu_t *ipt;
706 
707  ipt = ip_path_mtu_get (ipti);
708 
709  if (ipt->ipt_flags & IP_PMTU_FLAG_STALE)
710  {
711  vec_add1 (ctx->indicies, ipti);
712  }
713 
714  return (WALK_CONTINUE);
715 }
716 
717 int
719 {
720  IP_PMTU_DBG ("replace-begin");
721 
723 
724  return (0);
725 }
726 
727 int
729 {
730  index_t *ipti;
731 
732  IP_PMTU_DBG ("replace-end");
733 
734  /*
735  * not safe to walk the pool whilst deleting, so create
736  * temporary storage of stale entries
737  */
739  .indicies = NULL,
740  };
741 
743 
744  vec_foreach (ipti, ctx.indicies)
745  {
746  ip_pmtu_t *ipt;
748 
749  ipt = ip_path_mtu_get (*ipti);
750  ip_pmtu_get_ip (ipt, &ip);
752  }
753 
754  vec_free (ctx.indicies);
755 
756  return (0);
757 }
758 
759 void
761 {
762  index_t ipmi;
763 
764  pool_foreach_index (ipmi, ip_pmtu_pool)
765  {
766  if (WALK_STOP == fn (ipmi, ctx))
767  break;
768  }
769 }
770 
771 static fib_node_t *
773 {
774  ip_pmtu_t *ipt;
775 
776  ipt = pool_elt_at_index (ip_pmtu_pool, index);
777 
778  return (&(ipt->ipt_node));
779 }
780 
781 static ip_pmtu_t *
783 {
784  return (
785  (ip_pmtu_t *) (((char *) node) - STRUCT_OFFSET_OF (ip_pmtu_t, ipt_node)));
786 }
787 
788 static void
790 {
791  /*
792  * the lifetime of the entry is managed by the API.
793  */
794  ASSERT (0);
795 }
796 
797 /*
798  * A back walk has reached this BIER entry
799  */
802 {
803  /*
804  * re-populate the ECMP tables with new choices
805  */
806  ip_pmtu_t *ipr = ip_pmtu_get_from_node (node);
807 
808  ip_pmtu_stack (ipr);
809 
810  /*
811  * no need to propagate further up the graph, since there's nothing there
812  */
814 }
815 
816 static const fib_node_vft_t ip_ptmu_fib_node_vft = {
818  .fnv_last_lock = ip_pmtu_last_lock_gone,
819  .fnv_back_walk = ip_pmtu_back_walk_notify,
820 };
821 
822 static clib_error_t *
824 {
826  adj_delegate_register_new_type (&ip_path_adj_delegate_vft);
829  ip_pmtu_fib_type = fib_node_register_new_type (&ip_ptmu_fib_node_vft);
830 
831  ip_pmtu_db = hash_create_mem (0, sizeof (ip_pmtu_key_t), sizeof (index_t));
832  ip_pmtu_logger = vlib_log_register_class ("ip", "pmtu");
834  dpo_register_new_type (&ip_pmtu_dpo_vft, ip_pmtu_dpo_nodes);
835 
836  return (NULL);
837 }
838 
840 
841 static clib_error_t *
843  vlib_cli_command_t *cmd)
844 {
845  index_t ipti;
846 
847  if (unformat (input, "%d", &ipti))
848  {
849  /*
850  * show one in detail
851  */
852  if (!pool_is_free_index (ip_pmtu_pool, ipti))
853  vlib_cli_output (vm, "%U", format_ip_pmtu, ipti);
854  else
855  vlib_cli_output (vm, "entry %d invalid", ipti);
856  }
857  else
858  {
859  /*
860  * show all
861  */
862  pool_foreach_index (ipti, ip_pmtu_pool)
863  {
864  vlib_cli_output (vm, "%U", format_ip_pmtu, ipti);
865  }
866  }
867 
868  return (NULL);
869 }
870 
871 VLIB_CLI_COMMAND (show_fib_entry, static) = {
872  .path = "show ip pmtu",
873  .function = show_ip_pmtu_command,
874  .short_help = "show ip path MTU",
875 };
876 
877 /*
878  * fd.io coding-style-patch-verification: ON
879  *
880  * Local Variables:
881  * eval: (c-set-style "gnu")
882  * End:
883  */
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:339
int ip_path_mtu_replace_begin(void)
Definition: ip_path_mtu.c:718
static void ip_pmtu_update(index_t ipti, u16 pmtu)
Definition: ip_path_mtu.c:601
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:211
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:428
enum fib_source_t_ fib_source_t
The different sources that can create a route.
u32 fib_entry_get_fib_index(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:1738
void ip_path_mtu_walk(ip_path_mtu_walk_t fn, void *ctx)
Definition: ip_path_mtu.c:760
void adj_nbr_walk_nh(u32 sw_if_index, fib_protocol_t adj_nh_proto, const ip46_address_t *nh, adj_walk_cb_t cb, void *ctx)
Walk adjacencies on a link with a given next-hop.
Definition: adj_nbr.c:684
fib_node_index_t fib_entry_track(u32 fib_index, const fib_prefix_t *prefix, fib_node_type_t child_type, index_t child_index, u32 *sibling)
Trackers are used on FIB entries by objects that which to track the changing state of the entry...
#define clib_min(x, y)
Definition: clib.h:342
#define pool_foreach_index(i, v)
Definition: pool.h:576
A virtual function table regisitered for a DPO type.
Definition: dpo.h:423
void adj_nbr_set_mtu(adj_index_t adj_index, u16 mtu)
Set the MTU on an adjacency.
Definition: adj_nbr.c:226
struct ip_path_mtu_adj_delegate_t_ ip_path_mtu_adj_delegate_t
Delegate added to adjacencies to track path MTU.
vl_api_fib_path_nh_t nh
Definition: fib_types.api:126
void fib_node_init(fib_node_t *node, fib_node_type_t type)
Definition: fib_node.c:185
fib_node_t ipt_node
linkage into the FIB graph
Definition: ip_path_mtu.h:75
struct ip_path_mtu_walk_sweep_ctx_t_ ip_path_mtu_walk_sweep_ctx_t
Definition: fib_entry.h:123
Multicast Adjacency.
Definition: adj.h:82
static void ip_pmtu_dpo_lock(dpo_id_t *dpo)
Definition: ip_path_mtu.c:322
Broadcast Adjacency.
Definition: adj.h:85
IP unicast adjacency.
Definition: adj.h:235
enum fib_node_back_walk_rc_t_ fib_node_back_walk_rc_t
Return code from a back walk function.
const dpo_id_t * fib_entry_contribute_ip_forwarding(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:506
This packet is to be rewritten and forwarded to the next processing node.
Definition: adj.h:73
add paths without path extensions
Definition: fib_source.h:210
void dpo_copy(dpo_id_t *dst, const dpo_id_t *src)
atomic copy a data-plane object.
Definition: dpo.c:264
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:43
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:607
static const char *const *const ip_pmtu_dpo_nodes[DPO_PROTO_NUM]
Definition: ip_path_mtu.c:443
u32 dpo_get_urpf(const dpo_id_t *dpo)
Get a uRPF interface for the DPO.
Definition: dpo.c:389
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:73
const fib_prefix_t * fib_entry_get_prefix(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:1728
fib_protocol_t fproto
Definition: ip_path_mtu.c:84
Definition: fib_entry.h:114
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:255
static adj_walk_rc_t ip_ptmu_adj_walk_remove(adj_index_t ai, void *ctx)
Definition: ip_path_mtu.c:254
static u8 * format_ip_pmtu(u8 *s, va_list *ap)
Definition: ip_path_mtu.c:135
int ip_path_mtu_replace_end(void)
Definition: ip_path_mtu.c:728
unsigned char u8
Definition: types.h:56
fib_node_type_t fib_node_register_new_type(const fib_node_vft_t *vft)
Create a new FIB node type and Register the function table for it.
Definition: fib_node.c:80
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
ip46_address_t nh
Definition: ip_path_mtu.c:82
The Path MTU DPO.
Definition: ip_path_mtu.h:26
static_always_inline ip_pmtu_t * ip_path_mtu_get(index_t index)
Definition: ip_path_mtu.h:115
static ip_pmtu_t * ip_pmtu_get_from_node(fib_node_t *node)
Definition: ip_path_mtu.c:782
static bool ip_path_mtu_value_invalid(u16 pmtu)
Definition: ip_path_mtu.c:248
unsigned int u32
Definition: types.h:88
Remote Path MTU tracking object.
Definition: ip_path_mtu.h:72
vlib_frame_t * f
static walk_rc_t ip_path_mtu_walk_sweep(index_t ipti, void *arg)
Definition: ip_path_mtu.c:702
Adjacency to punt this packet.
Definition: adj.h:55
const dpo_id_t * drop_dpo_get(dpo_proto_t proto)
Definition: drop_dpo.c:25
void ip_pmtu_get_ip(const ip_pmtu_t *ipt, ip_address_t *ip)
Definition: ip_path_mtu.c:126
enum walk_rc_t_ walk_rc_t
Walk return code.
static u8 * format_ip_path_mtu_adj_delegate(const adj_delegate_t *aed, u8 *s)
Definition: ip_path_mtu.c:156
static u16 ip_pmtu_dpo_get_mtu(const dpo_id_t *dpo)
Definition: ip_path_mtu.c:408
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:470
u32 vlib_log_class_t
Definition: vlib.h:52
static adj_delegate_type_t ip_pmtu_adj_delegate_type
Definition: ip_path_mtu.c:46
enum dpo_type_t_ dpo_type_t
Common types of data-path objects New types can be dynamically added using dpo_register_new_type() ...
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
walk_rc_t(* ip_path_mtu_walk_t)(index_t ipti, void *ctx)
Definition: ip_path_mtu.h:94
void fib_table_entry_special_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Remove a &#39;special&#39; entry from the FIB.
Definition: fib_table.c:424
Delegate added to adjacencies to track path MTU.
Definition: ip_path_mtu.c:72
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
enum adj_walk_rc_t_ adj_walk_rc_t
return codes from a adjacency walker callback function
description fragment has unexpected format
Definition: map.api:433
u8 * format_fib_prefix(u8 *s, va_list *args)
Definition: fib_types.c:283
static void ip_pmtu_adj_delegate_adj_created(adj_index_t ai)
Definition: ip_path_mtu.c:168
Aggregate type for a prefix.
Definition: fib_types.h:202
struct ip_pmtu_key_t_ ip_pmtu_key_t
void ip_address_to_fib_prefix(const ip_address_t *addr, fib_prefix_t *prefix)
convert from a IP address to a FIB prefix
Definition: ip_types.c:270
Adj delegate.
Definition: adj_delegate.h:50
int ip_path_mtu_update(const ip_address_t *nh, u32 table_id, u16 pmtu)
Definition: ip_path_mtu.c:647
u32 fib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1106
dpo_type_t dpo_register_new_type(const dpo_vft_t *vft, const char *const *const *nodes)
Create and register a new DPO type.
Definition: dpo.c:349
u16 ipt_cfg_pmtu
Configured MTU.
Definition: ip_path_mtu.h:83
union ip_adjacency_t_::@144 sub_type
fib_source_t fib_source_allocate(const char *name, fib_source_priority_t prio, fib_source_behaviour_t bh)
Definition: fib_source.c:118
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:172
#define hash_create_mem(elts, key_bytes, value_bytes)
Definition: hash.h:661
static clib_error_t * ip_path_module_init(vlib_main_t *vm)
Definition: ip_path_mtu.c:823
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:553
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
int adj_delegate_add(ip_adjacency_t *adj, adj_delegate_type_t adt, index_t adi)
Add a delegate to an adjacency.
Definition: adj_delegate.c:107
#define FIB_SOURCE_PRIORITY_HI
Some priority values that plugins might use when they are not to concerned where in the list they&#39;ll ...
Definition: fib_source.h:284
enum ip_pmtu_flags_t_ ip_pmtu_flags_t
void ip_address_from_46(const ip46_address_t *nh, fib_protocol_t fproto, ip_address_t *ip)
Definition: ip_types.c:259
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:225
dpo_type_t dpoi_type
the type
Definition: dpo.h:178
long ctx[MAX_CONNS]
Definition: main.c:144
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
enum adj_delegate_type_t_ adj_delegate_type_t
A Delagate is a means to implement the Delagation design pattern; the extension of an object&#39;s functi...
static fib_source_t ip_pmtu_source
Definition: ip_path_mtu.c:47
adj_index_t ad_adj_index
The ADJ entry object to which the delagate is attached.
Definition: adj_delegate.h:55
static fib_node_back_walk_rc_t ip_pmtu_back_walk_notify(fib_node_t *node, fib_node_back_walk_ctx_t *ctx)
Definition: ip_path_mtu.c:801
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:305
u8 * format_ip_pmtu_dpo(u8 *s, va_list *ap)
Definition: ip_path_mtu.c:372
This packet matches an "interface route" and packets need to be passed to ARP to find rewrite string ...
Definition: adj.h:68
#define pool_get_aligned_zero(P, E, A)
Allocate an object E from a pool P with alignment A and zero it.
Definition: pool.h:252
ip_pmtu_dpo_t * ip_pmtu_dpo_pool
DPO pool.
Definition: ip_path_mtu.c:52
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
An node in the FIB graph.
Definition: fib_node.h:301
static adj_walk_rc_t ip_ptmu_adj_walk_update(adj_index_t ai, void *ctx)
Definition: ip_path_mtu.c:271
u32 fib_entry_get_resolving_interface(fib_node_index_t entry_index)
Definition: fib_entry.c:1474
static index_t ip_pmtu_destroy(index_t ipti, const ip_pmtu_key_t *key)
Definition: ip_path_mtu.c:613
This packet matches an "incomplete adjacency" and packets need to be passed to ARP to find rewrite st...
Definition: adj.h:63
Adjacency to drop this packet.
Definition: adj.h:53
u32 ip_pmtu_get_table_id(const ip_pmtu_t *ipt)
Definition: ip_path_mtu.c:114
fib_node_index_t fib_table_entry_special_dpo_update(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, const dpo_id_t *dpo)
Update a &#39;special&#39; entry to the FIB that links to the DPO passed A special entry is an entry that the...
Definition: fib_table.c:363
dpo_id_t ipm_dpo
Stacked DPO.
Definition: ip_path_mtu.h:48
static vlib_log_class_t ip_pmtu_logger
Path MTU.
Definition: ip_path_mtu.c:44
index_t ad_index
The index passed by the provider to identify its delegate instance.
Definition: adj_delegate.h:66
static fib_node_t * ip_pmtu_get_node(fib_node_index_t index)
Definition: ip_path_mtu.c:772
static const char *const ip_pmtu_dpo_ip6_nodes[]
Definition: ip_path_mtu.c:438
static u32 ip_pmtu_dpo_get_urpf(const dpo_id_t *dpo)
Definition: ip_path_mtu.c:346
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:395
u32 index
Definition: flow_types.api:221
Multicast Midchain Adjacency.
Definition: adj.h:89
#define IP_PMTU_DBG(_fmt, _args...)
Definition: ip_path_mtu.c:94
fib_node_get_t fnv_get
Definition: fib_node.h:289
static ip_pmtu_dpo_t * ip_pmtu_dpo_get_from_dpo(const dpo_id_t *dpo)
Definition: ip_path_mtu.c:308
static void ip_pmtu_adj_delegate_adj_modified(adj_delegate_t *ad)
Definition: ip_path_mtu.c:231
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:29
static void ip_pmtu_stack(ip_pmtu_t *ipt)
Definition: ip_path_mtu.c:532
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:302
u32 adj_index_t
An index for adjacencies.
Definition: adj_types.h:30
static_always_inline ip_pmtu_dpo_t * ip_pmtu_dpo_get(index_t index)
Definition: ip_path_mtu.h:108
void dpo_set(dpo_id_t *dpo, dpo_type_t type, dpo_proto_t proto, index_t index)
Set/create a DPO ID The DPO will be locked.
Definition: dpo.c:188
u32 ipt_sibling
Definition: ip_path_mtu.h:79
Context passed between object during a back walk.
Definition: fib_node.h:214
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:163
This packets follow a mid-chain adjacency.
Definition: adj.h:76
fib_node_index_t fib_table_entry_special_dpo_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, const dpo_id_t *dpo)
Add a &#39;special&#39; entry to the FIB that links to the DPO passed A special entry is an entry that the FI...
Definition: fib_table.c:324
u32 fib_table_get_table_id_for_sw_if_index(fib_protocol_t proto, u32 sw_if_index)
Get the Table-ID of the FIB bound to the interface.
Definition: fib_table.c:1082
static void ip_pmtu_dpo_interpose(const dpo_id_t *original, const dpo_id_t *parent, dpo_id_t *clone)
Interpose a path MTU DPO.
Definition: ip_path_mtu.c:390
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:337
#define ASSERT(truth)
void fib_entry_untrack(fib_node_index_t fei, u32 sibling)
Stop tracking a FIB entry.
u16 ipt_oper_pmtu
operational MTU; the minimum value of the cfg and parent MTU
Definition: ip_path_mtu.h:89
adj_delegate_type_t adj_delegate_register_new_type(const adj_delegate_vft_t *vft)
adj_delegate_register_new_type
Definition: adj_delegate.c:218
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:716
u16 ipm_pmtu
Configured Path Mtu.
Definition: ip_path_mtu.h:38
adj_delegate_t * adj_delegate_get(const ip_adjacency_t *adj, adj_delegate_type_t type)
Get a delegate from an adjacency.
Definition: adj_delegate.c:58
u32 fib_table_get_table_id(u32 fib_index, fib_protocol_t proto)
Get the Table-ID of the FIB from protocol and index.
Definition: fib_table.c:1095
ip_pmtu_t * ip_pmtu_pool
Path MTU tracker pool.
Definition: ip_path_mtu.c:67
#define IP_PMTU_TRKR_DBG(_ipt, _fmt, _args...)
Definition: ip_path_mtu.c:89
static void hash_unset_mem_free(uword **h, const void *key)
Definition: hash.h:295
adj_delegate_format_t adv_format
Definition: adj_delegate.h:95
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:343
u8 * format_dpo_id(u8 *s, va_list *args)
Format a DPO_id_t oject.
Definition: dpo.c:150
static walk_rc_t ip_path_mtu_walk_mark(index_t ipti, void *ctx)
Definition: ip_path_mtu.c:685
typedef key
Definition: ipsec_types.api:88
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
fib_protocol_t ia_nh_proto
The protocol of the neighbor/peer.
Definition: adj.h:350
#define DPO_PROTO_NUM
Definition: dpo.h:72
u16 dpo_get_mtu(const dpo_id_t *dpo)
Get the MTU DPO.
Definition: dpo.c:401
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:190
vl_api_address_t ip
Definition: l2.api:558
static fib_node_type_t ip_pmtu_fib_type
Fib node type for the tracker.
Definition: ip_path_mtu.c:62
ip_pmtu_flags_t ipt_flags
Definition: ip_path_mtu.h:80
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
static void ip_pmtu_adj_delegate_adj_deleted(adj_delegate_t *ad)
Definition: ip_path_mtu.c:225
ip_lookup_next_t lookup_next_index
Next hop after ip4-lookup.
Definition: adj.h:337
u64 uword
Definition: types.h:112
void ip_pmtu_dpo_add_or_lock(fib_protocol_t fproto, u16 pmtu, dpo_id_t *dpo)
Definition: ip_path_mtu.c:356
static dpo_type_t ip_pmtu_dpo_type
DPO type registered for these GBP FWD.
Definition: ip_path_mtu.c:57
u32 table_id
Definition: wireguard.api:102
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:204
static uword * ip_pmtu_db
Definition: ip_path_mtu.c:87
static ip_pmtu_dpo_t * ip_pmtu_dpo_alloc(void)
Definition: ip_path_mtu.c:298
static index_t ip_pmtu_alloc(u32 fib_index, const fib_prefix_t *pfx, const ip_pmtu_key_t *key, u16 pmtu)
Definition: ip_path_mtu.c:469
An ADJ delegate virtual function table.
Definition: adj_delegate.h:94
static clib_error_t * show_ip_pmtu_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip_path_mtu.c:842
static ip_path_mtu_adj_delegate_t * ip_path_mtu_adj_delegate_pool
Definition: ip_path_mtu.c:77
u8 * format_dpo_proto(u8 *s, va_list *args)
format a DPO protocol
Definition: dpo.c:180
static void ip_pmtu_last_lock_gone(fib_node_t *node)
Definition: ip_path_mtu.c:789
static bool ip_mtu_fib_entry_is_attached(fib_node_index_t fib_entry)
Definition: ip_path_mtu.c:449
#define hash_get_mem(h, key)
Definition: hash.h:269
A FIB graph nodes virtual function table.
Definition: fib_node.h:288
enum fib_node_type_t_ fib_node_type_t
The types of nodes in a FIB graph.
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:234
#define vec_foreach(var, vec)
Vector iterator.
fib_node_index_t ipt_fib_entry
Track fib entry.
Definition: ip_path_mtu.h:78
static void hash_set_mem_alloc(uword **h, const void *key, uword v)
Definition: hash.h:279
u16 ipm_locks
number of locks.
Definition: ip_path_mtu.h:43
dpo_proto_t ipm_proto
The protocol of packets using this DPO.
Definition: ip_path_mtu.h:31
struct ip_adjacency_t_::@144::@145 nbr
IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE.
static void ip_pmtu_dpo_unlock(dpo_id_t *dpo)
Definition: ip_path_mtu.c:331
u16 ipt_parent_pmtu
MTU from the parent MTU.
Definition: ip_path_mtu.h:86
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
void adj_delegate_remove(adj_index_t ai, adj_delegate_type_t type)
Remove a delegate from an adjacency.
Definition: adj_delegate.c:65
static const char *const ip_pmtu_dpo_ip4_nodes[]
The per-protocol VLIB graph nodes that are assigned to a glean object.
Definition: ip_path_mtu.c:433
fib_node_index_t fib_table_get_less_specific(u32 fib_index, const fib_prefix_t *prefix)
Get the less specific (covering) prefix.
Definition: fib_table.c:133
static index_t ip_pmtu_dpo_get_index(ip_pmtu_dpo_t *ipm)
Definition: ip_path_mtu.c:316
void dpo_stack(dpo_type_t child_type, dpo_proto_t child_proto, dpo_id_t *dpo, const dpo_id_t *parent)
Stack one DPO object on another, and thus establish a child-parent relationship.
Definition: dpo.c:535
static u8 * format_ip_pmtu_flags(u8 *s, va_list *ap)
Definition: ip_path_mtu.c:100
fib_entry_flag_t fib_entry_get_flags(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:291