FD.io VPP  v18.10-34-gcce845e
Vector Packet Processing
fib_path.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <vlib/vlib.h>
17 #include <vnet/vnet.h>
18 #include <vnet/ip/format.h>
19 #include <vnet/ip/ip.h>
20 #include <vnet/dpo/drop_dpo.h>
21 #include <vnet/dpo/receive_dpo.h>
23 #include <vnet/dpo/lookup_dpo.h>
26 #include <vnet/dpo/dvr_dpo.h>
27 #include <vnet/dpo/drop_dpo.h>
28 
29 #include <vnet/adj/adj.h>
30 #include <vnet/adj/adj_mcast.h>
31 
32 #include <vnet/fib/fib_path.h>
33 #include <vnet/fib/fib_node.h>
34 #include <vnet/fib/fib_table.h>
35 #include <vnet/fib/fib_entry.h>
36 #include <vnet/fib/fib_path_list.h>
37 #include <vnet/fib/fib_internal.h>
38 #include <vnet/fib/fib_urpf_list.h>
39 #include <vnet/fib/mpls_fib.h>
40 #include <vnet/udp/udp_encap.h>
41 #include <vnet/bier/bier_fmask.h>
42 #include <vnet/bier/bier_table.h>
43 #include <vnet/bier/bier_imp.h>
45 
46 /**
47  * Enurmeration of path types
48  */
49 typedef enum fib_path_type_t_ {
50  /**
51  * Marker. Add new types after this one.
52  */
54  /**
55  * Attached-nexthop. An interface and a nexthop are known.
56  */
58  /**
59  * attached. Only the interface is known.
60  */
62  /**
63  * recursive. Only the next-hop is known.
64  */
66  /**
67  * special. nothing is known. so we drop.
68  */
70  /**
71  * exclusive. user provided adj.
72  */
74  /**
75  * deag. Link to a lookup adj in the next table
76  */
78  /**
79  * interface receive.
80  */
82  /**
83  * Path resolves via a UDP encap object.
84  */
86  /**
87  * receive. it's for-us.
88  */
90  /**
91  * bier-imp. it's via a BIER imposition.
92  */
94  /**
95  * bier-fmask. it's via a BIER ECMP-table.
96  */
98  /**
99  * bier-fmask. it's via a BIER f-mask.
100  */
102  /**
103  * via a DVR.
104  */
106  /**
107  * Marker. Add new types before this one, then update it.
108  */
110 } __attribute__ ((packed)) fib_path_type_t;
111 
112 /**
113  * The maximum number of path_types
114  */
115 #define FIB_PATH_TYPE_MAX (FIB_PATH_TYPE_LAST + 1)
116 
117 #define FIB_PATH_TYPES { \
118  [FIB_PATH_TYPE_ATTACHED_NEXT_HOP] = "attached-nexthop", \
119  [FIB_PATH_TYPE_ATTACHED] = "attached", \
120  [FIB_PATH_TYPE_RECURSIVE] = "recursive", \
121  [FIB_PATH_TYPE_SPECIAL] = "special", \
122  [FIB_PATH_TYPE_EXCLUSIVE] = "exclusive", \
123  [FIB_PATH_TYPE_DEAG] = "deag", \
124  [FIB_PATH_TYPE_INTF_RX] = "intf-rx", \
125  [FIB_PATH_TYPE_UDP_ENCAP] = "udp-encap", \
126  [FIB_PATH_TYPE_RECEIVE] = "receive", \
127  [FIB_PATH_TYPE_BIER_IMP] = "bier-imp", \
128  [FIB_PATH_TYPE_BIER_TABLE] = "bier-table", \
129  [FIB_PATH_TYPE_BIER_FMASK] = "bier-fmask", \
130  [FIB_PATH_TYPE_DVR] = "dvr", \
131 }
132 
133 #define FOR_EACH_FIB_PATH_TYPE(_item) \
134  for (_item = FIB_PATH_TYPE_FIRST; \
135  _item <= FIB_PATH_TYPE_LAST; \
136  _item++)
137 
138 /**
139  * Enurmeration of path operational (i.e. derived) attributes
140  */
142  /**
143  * Marker. Add new types after this one.
144  */
146  /**
147  * The path forms part of a recursive loop.
148  */
150  /**
151  * The path is resolved
152  */
154  /**
155  * The path is attached, despite what the next-hop may say.
156  */
158  /**
159  * The path has become a permanent drop.
160  */
162  /**
163  * Marker. Add new types before this one, then update it.
164  */
166 } __attribute__ ((packed)) fib_path_oper_attribute_t;
167 
168 /**
169  * The maximum number of path operational attributes
170  */
171 #define FIB_PATH_OPER_ATTRIBUTE_MAX (FIB_PATH_OPER_ATTRIBUTE_LAST + 1)
172 
173 #define FIB_PATH_OPER_ATTRIBUTES { \
174  [FIB_PATH_OPER_ATTRIBUTE_RECURSIVE_LOOP] = "recursive-loop", \
175  [FIB_PATH_OPER_ATTRIBUTE_RESOLVED] = "resolved", \
176  [FIB_PATH_OPER_ATTRIBUTE_DROP] = "drop", \
177 }
178 
179 #define FOR_EACH_FIB_PATH_OPER_ATTRIBUTE(_item) \
180  for (_item = FIB_PATH_OPER_ATTRIBUTE_FIRST; \
181  _item <= FIB_PATH_OPER_ATTRIBUTE_LAST; \
182  _item++)
183 
184 /**
185  * Path flags from the attributes
186  */
193 } __attribute__ ((packed)) fib_path_oper_flags_t;
194 
195 /**
196  * A FIB path
197  */
198 typedef struct fib_path_t_ {
199  /**
200  * A path is a node in the FIB graph.
201  */
203 
204  /**
205  * The index of the path-list to which this path belongs
206  */
208 
209  /**
210  * This marks the start of the memory area used to hash
211  * the path
212  */
213  STRUCT_MARK(path_hash_start);
214 
215  /**
216  * Configuration Flags
217  */
219 
220  /**
221  * The type of the path. This is the selector for the union
222  */
223  fib_path_type_t fp_type;
224 
225  /**
226  * The protocol of the next-hop, i.e. the address family of the
227  * next-hop's address. We can't derive this from the address itself
228  * since the address can be all zeros
229  */
231 
232  /**
233  * UCMP [unnormalised] weigth
234  */
236 
237  /**
238  * A path preference. 0 is the best.
239  * Only paths of the best preference, that are 'up', are considered
240  * for forwarding.
241  */
243 
244  /**
245  * per-type union of the data required to resolve the path
246  */
247  union {
248  struct {
249  /**
250  * The next-hop
251  */
252  ip46_address_t fp_nh;
253  /**
254  * The interface
255  */
257  } attached_next_hop;
258  struct {
259  /**
260  * The interface
261  */
262  u32 fp_interface;
263  } attached;
264  struct {
265  union
266  {
267  /**
268  * The next-hop
269  */
270  ip46_address_t fp_ip;
271  struct {
272  /**
273  * The local label to resolve through.
274  */
276  /**
277  * The EOS bit of the resolving label
278  */
280  };
281  } fp_nh;
282  union {
283  /**
284  * The FIB table index in which to find the next-hop.
285  */
287  /**
288  * The BIER FIB the fmask is in
289  */
291  };
292  } recursive;
293  struct {
294  /**
295  * BIER FMask ID
296  */
298  } bier_fmask;
299  struct {
300  /**
301  * The BIER table's ID
302  */
304  } bier_table;
305  struct {
306  /**
307  * The BIER imposition object
308  * this is part of the path's key, since the index_t
309  * of an imposition object is the object's key.
310  */
312  } bier_imp;
313  struct {
314  /**
315  * The FIB index in which to perfom the next lookup
316  */
317  fib_node_index_t fp_tbl_id;
318  /**
319  * The RPF-ID to tag the packets with
320  */
322  } deag;
323  struct {
324  } special;
325  struct {
326  /**
327  * The user provided 'exclusive' DPO
328  */
330  } exclusive;
331  struct {
332  /**
333  * The interface on which the local address is configured
334  */
335  u32 fp_interface;
336  /**
337  * The next-hop
338  */
339  ip46_address_t fp_addr;
340  } receive;
341  struct {
342  /**
343  * The interface on which the packets will be input.
344  */
345  u32 fp_interface;
346  } intf_rx;
347  struct {
348  /**
349  * The UDP Encap object this path resolves through
350  */
352  } udp_encap;
353  struct {
354  /**
355  * The interface
356  */
357  u32 fp_interface;
358  } dvr;
359  };
360  STRUCT_MARK(path_hash_end);
361 
362  /**
363  * Memebers in this last section represent information that is
364  * dervied during resolution. It should not be copied to new paths
365  * nor compared.
366  */
367 
368  /**
369  * Operational Flags
370  */
371  fib_path_oper_flags_t fp_oper_flags;
372 
373  union {
374  /**
375  * the resolving via fib. not part of the union, since it it not part
376  * of the path's hash.
377  */
379  /**
380  * the resolving bier-table
381  */
383  /**
384  * the resolving bier-fmask
385  */
387  };
388 
389  /**
390  * The Data-path objects through which this path resolves for IP.
391  */
393 
394  /**
395  * the index of this path in the parent's child list.
396  */
398 } fib_path_t;
399 
400 /*
401  * Array of strings/names for the path types and attributes
402  */
403 static const char *fib_path_type_names[] = FIB_PATH_TYPES;
404 static const char *fib_path_oper_attribute_names[] = FIB_PATH_OPER_ATTRIBUTES;
405 static const char *fib_path_cfg_attribute_names[] = FIB_PATH_CFG_ATTRIBUTES;
406 
407 /*
408  * The memory pool from which we allocate all the paths
409  */
411 
412 /*
413  * Debug macro
414  */
415 #ifdef FIB_DEBUG
416 #define FIB_PATH_DBG(_p, _fmt, _args...) \
417 { \
418  u8 *_tmp = NULL; \
419  _tmp = fib_path_format(fib_path_get_index(_p), _tmp); \
420  clib_warning("path:[%d:%U]:" _fmt, \
421  fib_path_get_index(_p), format_fib_path, _p, 0,\
422  ##_args); \
423  vec_free(_tmp); \
424 }
425 #else
426 #define FIB_PATH_DBG(_p, _fmt, _args...)
427 #endif
428 
429 static fib_path_t *
431 {
432  return (pool_elt_at_index(fib_path_pool, index));
433 }
434 
435 static fib_node_index_t
437 {
438  return (path - fib_path_pool);
439 }
440 
441 static fib_node_t *
443 {
444  return ((fib_node_t*)fib_path_get(index));
445 }
446 
447 static fib_path_t*
449 {
451  return ((fib_path_t*)node);
452 }
453 
454 u8 *
455 format_fib_path (u8 * s, va_list * args)
456 {
457  fib_node_index_t path_index = va_arg (*args, fib_node_index_t);
458  u32 indent = va_arg (*args, u32);
459  vnet_main_t * vnm = vnet_get_main();
460  fib_path_oper_attribute_t oattr;
462  fib_path_t *path;
463 
464  path = fib_path_get(path_index);
465 
466  s = format (s, "%Upath:[%d] ", format_white_space, indent,
467  fib_path_get_index(path));
468  s = format (s, "pl-index:%d ", path->fp_pl_index);
469  s = format (s, "%U ", format_dpo_proto, path->fp_nh_proto);
470  s = format (s, "weight=%d ", path->fp_weight);
471  s = format (s, "pref=%d ", path->fp_preference);
472  s = format (s, "%s: ", fib_path_type_names[path->fp_type]);
473  if (FIB_PATH_OPER_FLAG_NONE != path->fp_oper_flags) {
474  s = format(s, " oper-flags:");
476  if ((1<<oattr) & path->fp_oper_flags) {
477  s = format (s, "%s,", fib_path_oper_attribute_names[oattr]);
478  }
479  }
480  }
481  if (FIB_PATH_CFG_FLAG_NONE != path->fp_cfg_flags) {
482  s = format(s, " cfg-flags:");
484  if ((1<<cattr) & path->fp_cfg_flags) {
485  s = format (s, "%s,", fib_path_cfg_attribute_names[cattr]);
486  }
487  }
488  }
489  s = format(s, "\n%U", format_white_space, indent+2);
490 
491  switch (path->fp_type)
492  {
494  s = format (s, "%U", format_ip46_address,
495  &path->attached_next_hop.fp_nh,
496  IP46_TYPE_ANY);
498  {
499  s = format (s, " if_index:%d", path->attached_next_hop.fp_interface);
500  }
501  else
502  {
503  s = format (s, " %U",
505  vnm,
507  vnm,
508  path->attached_next_hop.fp_interface));
510  path->attached_next_hop.fp_interface))
511  {
512  s = format (s, " (p2p)");
513  }
514  }
515  if (!dpo_id_is_valid(&path->fp_dpo))
516  {
517  s = format(s, "\n%Uunresolved", format_white_space, indent+2);
518  }
519  else
520  {
521  s = format(s, "\n%U%U",
522  format_white_space, indent,
524  &path->fp_dpo, 13);
525  }
526  break;
529  {
530  s = format (s, "if_index:%d", path->attached_next_hop.fp_interface);
531  }
532  else
533  {
534  s = format (s, " %U",
536  vnm,
538  vnm,
539  path->attached.fp_interface));
540  }
541  break;
543  if (DPO_PROTO_MPLS == path->fp_nh_proto)
544  {
545  s = format (s, "via %U %U",
547  path->recursive.fp_nh.fp_local_label,
549  path->recursive.fp_nh.fp_eos);
550  }
551  else
552  {
553  s = format (s, "via %U",
555  &path->recursive.fp_nh.fp_ip,
556  IP46_TYPE_ANY);
557  }
558  s = format (s, " in fib:%d",
559  path->recursive.fp_tbl_id,
560  path->fp_via_fib);
561  s = format (s, " via-fib:%d", path->fp_via_fib);
562  s = format (s, " via-dpo:[%U:%d]",
564  path->fp_dpo.dpoi_index);
565 
566  break;
568  s = format (s, "UDP-encap ID:%d", path->udp_encap.fp_udp_encap_id);
569  break;
571  s = format (s, "via bier-table:[%U}",
573  &path->bier_table.fp_bier_tbl);
574  s = format (s, " via-dpo:[%U:%d]",
576  path->fp_dpo.dpoi_index);
577  break;
579  s = format (s, "via-fmask:%d", path->bier_fmask.fp_bier_fmask);
580  s = format (s, " via-dpo:[%U:%d]",
582  path->fp_dpo.dpoi_index);
583  break;
585  s = format (s, "via %U", format_bier_imp,
586  path->bier_imp.fp_bier_imp, 0, BIER_SHOW_BRIEF);
587  break;
588  case FIB_PATH_TYPE_DVR:
589  s = format (s, " %U",
591  vnm,
593  vnm,
594  path->dvr.fp_interface));
595  break;
599  case FIB_PATH_TYPE_DEAG:
601  if (dpo_id_is_valid(&path->fp_dpo))
602  {
603  s = format(s, "%U", format_dpo_id,
604  &path->fp_dpo, indent+2);
605  }
606  break;
607  }
608  return (s);
609 }
610 
611 u8 *
613 {
614  fib_path_t *path;
615 
616  path = fib_path_get(pi);
617  ASSERT(NULL != path);
618 
619  return (format (s, "%U", format_fib_path, path));
620 }
621 
622 /*
623  * fib_path_last_lock_gone
624  *
625  * We don't share paths, we share path lists, so the [un]lock functions
626  * are no-ops
627  */
628 static void
630 {
631  ASSERT(0);
632 }
633 
634 static const adj_index_t
636  vnet_link_t link)
637 {
639  path->attached_next_hop.fp_interface))
640  {
641  /*
642  * if the interface is p2p then the adj for the specific
643  * neighbour on that link will never exist. on p2p links
644  * the subnet address (the attached route) links to the
645  * auto-adj (see below), we want that adj here too.
646  */
648  link,
649  &zero_addr,
650  path->attached_next_hop.fp_interface));
651  }
652  else
653  {
655  link,
656  &path->attached_next_hop.fp_nh,
657  path->attached_next_hop.fp_interface));
658  }
659 }
660 
661 static void
663 {
664  /*
665  * resolve directly via the adjacnecy discribed by the
666  * interface and next-hop
667  */
668  dpo_set(&path->fp_dpo,
670  path->fp_nh_proto,
672  path,
674 
675  /*
676  * become a child of the adjacency so we receive updates
677  * when its rewrite changes
678  */
681  fib_path_get_index(path));
682 
684  path->attached_next_hop.fp_interface) ||
685  !adj_is_up(path->fp_dpo.dpoi_index))
686  {
688  }
689 }
690 
691 static const adj_index_t
693  vnet_link_t link)
694 {
696  path->attached.fp_interface))
697  {
698  /*
699  * point-2-point interfaces do not require a glean, since
700  * there is nothing to ARP. Install a rewrite/nbr adj instead
701  */
703  link,
704  &zero_addr,
705  path->attached.fp_interface));
706  }
707  else
708  {
710  link,
711  path->attached.fp_interface,
712  NULL));
713  }
714 }
715 
716 /*
717  * create of update the paths recursive adj
718  */
719 static void
722  dpo_id_t *dpo)
723 {
724  dpo_id_t via_dpo = DPO_INVALID;
725 
726  /*
727  * get the DPO to resolve through from the via-entry
728  */
730  fct,
731  &via_dpo);
732 
733 
734  /*
735  * hope for the best - clear if restrictions apply.
736  */
738 
739  /*
740  * Validate any recursion constraints and over-ride the via
741  * adj if not met
742  */
744  {
746  dpo_copy(&via_dpo, drop_dpo_get(path->fp_nh_proto));
747  }
749  {
750  /*
751  * the via FIB must be a host route.
752  * note the via FIB just added will always be a host route
753  * since it is an RR source added host route. So what we need to
754  * check is whether the route has other sources. If it does then
755  * some other source has added it as a host route. If it doesn't
756  * then it was added only here and inherits forwarding from a cover.
757  * the cover is not a host route.
758  * The RR source is the lowest priority source, so we check if it
759  * is the best. if it is there are no other sources.
760  */
762  {
764  dpo_copy(&via_dpo, drop_dpo_get(path->fp_nh_proto));
765 
766  /*
767  * PIC edge trigger. let the load-balance maps know
768  */
770  }
771  }
773  {
774  /*
775  * RR source entries inherit the flags from the cover, so
776  * we can check the via directly
777  */
779  {
781  dpo_copy(&via_dpo, drop_dpo_get(path->fp_nh_proto));
782 
783  /*
784  * PIC edge trigger. let the load-balance maps know
785  */
787  }
788  }
789  /*
790  * check for over-riding factors on the FIB entry itself
791  */
792  if (!fib_entry_is_resolved(path->fp_via_fib))
793  {
795  dpo_copy(&via_dpo, drop_dpo_get(path->fp_nh_proto));
796 
797  /*
798  * PIC edge trigger. let the load-balance maps know
799  */
801  }
802 
803  /*
804  * If this path is contributing a drop, then it's not resolved
805  */
806  if (dpo_is_drop(&via_dpo) || load_balance_is_drop(&via_dpo))
807  {
809  }
810 
811  /*
812  * update the path's contributed DPO
813  */
814  dpo_copy(dpo, &via_dpo);
815 
816  FIB_PATH_DBG(path, "recursive update:");
817 
818  dpo_reset(&via_dpo);
819 }
820 
821 /*
822  * re-evaulate the forwarding state for a via fmask path
823  */
824 static void
826  dpo_id_t *dpo)
827 {
828  bier_fmask_contribute_forwarding(path->bier_fmask.fp_bier_fmask, dpo);
829 
830  /*
831  * if we are stakcing on the drop, then the path is not resolved
832  */
833  if (dpo_is_drop(dpo))
834  {
836  }
837  else
838  {
840  }
841 }
842 
843 /*
844  * fib_path_is_permanent_drop
845  *
846  * Return !0 if the path is configured to permanently drop,
847  * despite other attributes.
848  */
849 static int
851 {
852  return ((path->fp_cfg_flags & FIB_PATH_CFG_FLAG_DROP) ||
854 }
855 
856 /*
857  * fib_path_unresolve
858  *
859  * Remove our dependency on the resolution target
860  */
861 static void
863 {
864  /*
865  * the forced drop path does not need unresolving
866  */
867  if (fib_path_is_permanent_drop(path))
868  {
869  return;
870  }
871 
872  switch (path->fp_type)
873  {
875  if (FIB_NODE_INDEX_INVALID != path->fp_via_fib)
876  {
878  path->fp_sibling);
881  FIB_SOURCE_RR);
882  fib_table_unlock(path->recursive.fp_tbl_id,
884  FIB_SOURCE_RR);
886  }
887  break;
890  path->fp_sibling);
891  break;
894  break;
897  break;
900  path->fp_sibling);
902  break;
905  path->fp_sibling);
907  break;
910  break;
912  dpo_reset(&path->exclusive.fp_ex_dpo);
913  break;
917  case FIB_PATH_TYPE_DEAG:
918  case FIB_PATH_TYPE_DVR:
919  /*
920  * these hold only the path's DPO, which is reset below.
921  */
922  break;
923  }
924 
925  /*
926  * release the adj we were holding and pick up the
927  * drop just in case.
928  */
929  dpo_reset(&path->fp_dpo);
931 
932  return;
933 }
934 
937 {
938  if (DPO_PROTO_MPLS == path->fp_nh_proto)
939  {
940  if (FIB_PATH_TYPE_RECURSIVE == path->fp_type &&
941  MPLS_EOS == path->recursive.fp_nh.fp_eos)
942  {
944  }
945  else
946  {
948  }
949  }
950  else
951  {
953  }
954 }
955 
956 /*
957  * fib_path_back_walk_notify
958  *
959  * A back walk has reach this path.
960  */
964 {
965  fib_path_t *path;
966 
967  path = fib_path_from_fib_node(node);
968 
969  switch (path->fp_type)
970  {
973  {
974  /*
975  * modify the recursive adjacency to use the new forwarding
976  * of the via-fib.
977  * this update is visible to packets in flight in the DP.
978  */
980  path,
982  &path->fp_dpo);
983  }
986  {
987  /*
988  * ADJ updates (complete<->incomplete) do not need to propagate to
989  * recursive entries.
990  * The only reason its needed as far back as here, is that the adj
991  * and the incomplete adj are a different DPO type, so the LBs need
992  * to re-stack.
993  * If this walk was quashed in the fib_entry, then any non-fib_path
994  * children (like tunnels that collapse out the LB when they stack)
995  * would not see the update.
996  */
998  }
999  break;
1002  {
1003  /*
1004  * update to use the BIER fmask's new forwading
1005  */
1006  fib_path_bier_fmask_update(path, &path->fp_dpo);
1007  }
1010  {
1011  /*
1012  * ADJ updates (complete<->incomplete) do not need to propagate to
1013  * recursive entries.
1014  * The only reason its needed as far back as here, is that the adj
1015  * and the incomplete adj are a different DPO type, so the LBs need
1016  * to re-stack.
1017  * If this walk was quashed in the fib_entry, then any non-fib_path
1018  * children (like tunnels that collapse out the LB when they stack)
1019  * would not see the update.
1020  */
1021  return (FIB_NODE_BACK_WALK_CONTINUE);
1022  }
1023  break;
1025  /*
1026 FIXME comment
1027  * ADJ_UPDATE backwalk pass silently through here and up to
1028  * the path-list when the multipath adj collapse occurs.
1029  * The reason we do this is that the assumtption is that VPP
1030  * runs in an environment where the Control-Plane is remote
1031  * and hence reacts slowly to link up down. In order to remove
1032  * this down link from the ECMP set quickly, we back-walk.
1033  * VPP also has dedicated CPUs, so we are not stealing resources
1034  * from the CP to do so.
1035  */
1037  {
1039  {
1040  /*
1041  * alreday resolved. no need to walk back again
1042  */
1043  return (FIB_NODE_BACK_WALK_CONTINUE);
1044  }
1046  }
1048  {
1050  {
1051  /*
1052  * alreday unresolved. no need to walk back again
1053  */
1054  return (FIB_NODE_BACK_WALK_CONTINUE);
1055  }
1057  }
1059  {
1060  /*
1061  * The interface this path resolves through has been deleted.
1062  * This will leave the path in a permanent drop state. The route
1063  * needs to be removed and readded (and hence the path-list deleted)
1064  * before it can forward again.
1065  */
1066  fib_path_unresolve(path);
1068  }
1070  {
1071  /*
1072  * restack the DPO to pick up the correct DPO sub-type
1073  */
1074  uword if_is_up;
1075  adj_index_t ai;
1076 
1077  if_is_up = vnet_sw_interface_is_admin_up(
1078  vnet_get_main(),
1079  path->attached_next_hop.fp_interface);
1080 
1082  path,
1084 
1086  if (if_is_up && adj_is_up(ai))
1087  {
1089  }
1090 
1091  dpo_set(&path->fp_dpo, DPO_ADJACENCY, path->fp_nh_proto, ai);
1092  adj_unlock(ai);
1093 
1094  if (!if_is_up)
1095  {
1096  /*
1097  * If the interface is not up there is no reason to walk
1098  * back to children. if we did they would only evalute
1099  * that this path is unresolved and hence it would
1100  * not contribute the adjacency - so it would be wasted
1101  * CPU time.
1102  */
1103  return (FIB_NODE_BACK_WALK_CONTINUE);
1104  }
1105  }
1107  {
1109  {
1110  /*
1111  * alreday unresolved. no need to walk back again
1112  */
1113  return (FIB_NODE_BACK_WALK_CONTINUE);
1114  }
1115  /*
1116  * the adj has gone down. the path is no longer resolved.
1117  */
1119  }
1120  break;
1122  case FIB_PATH_TYPE_DVR:
1123  /*
1124  * FIXME; this could schedule a lower priority walk, since attached
1125  * routes are not usually in ECMP configurations so the backwalk to
1126  * the FIB entry does not need to be high priority
1127  */
1129  {
1131  }
1133  {
1135  }
1137  {
1138  fib_path_unresolve(path);
1140  }
1141  break;
1143  {
1144  dpo_id_t via_dpo = DPO_INVALID;
1145 
1146  /*
1147  * hope for the best - clear if restrictions apply.
1148  */
1150 
1151  udp_encap_contribute_forwarding(path->udp_encap.fp_udp_encap_id,
1152  path->fp_nh_proto,
1153  &via_dpo);
1154  /*
1155  * If this path is contributing a drop, then it's not resolved
1156  */
1157  if (dpo_is_drop(&via_dpo) || load_balance_is_drop(&via_dpo))
1158  {
1160  }
1161 
1162  /*
1163  * update the path's contributed DPO
1164  */
1165  dpo_copy(&path->fp_dpo, &via_dpo);
1166  dpo_reset(&via_dpo);
1167  break;
1168  }
1169  case FIB_PATH_TYPE_INTF_RX:
1170  ASSERT(0);
1171  case FIB_PATH_TYPE_DEAG:
1172  /*
1173  * FIXME When VRF delete is allowed this will need a poke.
1174  */
1175  case FIB_PATH_TYPE_SPECIAL:
1176  case FIB_PATH_TYPE_RECEIVE:
1180  /*
1181  * these path types have no parents. so to be
1182  * walked from one is unexpected.
1183  */
1184  ASSERT(0);
1185  break;
1186  }
1187 
1188  /*
1189  * propagate the backwalk further to the path-list
1190  */
1192 
1193  return (FIB_NODE_BACK_WALK_CONTINUE);
1194 }
1195 
1196 static void
1198 {
1199  fib_show_memory_usage("Path",
1200  pool_elts(fib_path_pool),
1201  pool_len(fib_path_pool),
1202  sizeof(fib_path_t));
1203 }
1204 
1205 /*
1206  * The FIB path's graph node virtual function table
1207  */
1208 static const fib_node_vft_t fib_path_vft = {
1210  .fnv_last_lock = fib_path_last_lock_gone,
1211  .fnv_back_walk = fib_path_back_walk_notify,
1212  .fnv_mem_show = fib_path_memory_show,
1213 };
1214 
1215 static fib_path_cfg_flags_t
1217 {
1219 
1221  cfg_flags |= FIB_PATH_CFG_FLAG_RESOLVE_HOST;
1224  if (rpath->frp_flags & FIB_ROUTE_PATH_LOCAL)
1225  cfg_flags |= FIB_PATH_CFG_FLAG_LOCAL;
1226  if (rpath->frp_flags & FIB_ROUTE_PATH_ATTACHED)
1227  cfg_flags |= FIB_PATH_CFG_FLAG_ATTACHED;
1228  if (rpath->frp_flags & FIB_ROUTE_PATH_INTF_RX)
1229  cfg_flags |= FIB_PATH_CFG_FLAG_INTF_RX;
1230  if (rpath->frp_flags & FIB_ROUTE_PATH_RPF_ID)
1231  cfg_flags |= FIB_PATH_CFG_FLAG_RPF_ID;
1232  if (rpath->frp_flags & FIB_ROUTE_PATH_EXCLUSIVE)
1233  cfg_flags |= FIB_PATH_CFG_FLAG_EXCLUSIVE;
1234  if (rpath->frp_flags & FIB_ROUTE_PATH_DROP)
1235  cfg_flags |= FIB_PATH_CFG_FLAG_DROP;
1237  cfg_flags |= FIB_PATH_CFG_FLAG_DEAG_SRC;
1238 
1239  return (cfg_flags);
1240 }
1241 
1242 /*
1243  * fib_path_create
1244  *
1245  * Create and initialise a new path object.
1246  * return the index of the path.
1247  */
1250  const fib_route_path_t *rpath)
1251 {
1252  fib_path_t *path;
1253 
1254  pool_get(fib_path_pool, path);
1255  memset(path, 0, sizeof(*path));
1256 
1257  fib_node_init(&path->fp_node,
1259 
1260  dpo_reset(&path->fp_dpo);
1261  path->fp_pl_index = pl_index;
1262  path->fp_nh_proto = rpath->frp_proto;
1264  path->fp_weight = rpath->frp_weight;
1265  if (0 == path->fp_weight)
1266  {
1267  /*
1268  * a weight of 0 is a meaningless value. We could either reject it, and thus force
1269  * clients to always use 1, or we can accept it and fixup approrpiately.
1270  */
1271  path->fp_weight = 1;
1272  }
1273  path->fp_preference = rpath->frp_preference;
1275 
1276  /*
1277  * deduce the path's tpye from the parementers and save what is needed.
1278  */
1280  {
1282  path->receive.fp_interface = rpath->frp_sw_if_index;
1283  path->receive.fp_addr = rpath->frp_addr;
1284  }
1285  else if (rpath->frp_flags & FIB_ROUTE_PATH_UDP_ENCAP)
1286  {
1288  path->udp_encap.fp_udp_encap_id = rpath->frp_udp_encap_id;
1289  }
1290  else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_INTF_RX)
1291  {
1293  path->intf_rx.fp_interface = rpath->frp_sw_if_index;
1294  }
1295  else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RPF_ID)
1296  {
1297  path->fp_type = FIB_PATH_TYPE_DEAG;
1298  path->deag.fp_tbl_id = rpath->frp_fib_index;
1299  path->deag.fp_rpf_id = rpath->frp_rpf_id;
1300  }
1301  else if (rpath->frp_flags & FIB_ROUTE_PATH_BIER_FMASK)
1302  {
1304  path->bier_fmask.fp_bier_fmask = rpath->frp_bier_fmask;
1305  }
1306  else if (rpath->frp_flags & FIB_ROUTE_PATH_BIER_IMP)
1307  {
1309  path->bier_imp.fp_bier_imp = rpath->frp_bier_imp;
1310  }
1311  else if (rpath->frp_flags & FIB_ROUTE_PATH_BIER_TABLE)
1312  {
1314  path->bier_table.fp_bier_tbl = rpath->frp_bier_tbl;
1315  }
1316  else if (rpath->frp_flags & FIB_ROUTE_PATH_DEAG)
1317  {
1318  path->fp_type = FIB_PATH_TYPE_DEAG;
1319  path->deag.fp_tbl_id = rpath->frp_fib_index;
1320  }
1321  else if (rpath->frp_flags & FIB_ROUTE_PATH_DVR)
1322  {
1323  path->fp_type = FIB_PATH_TYPE_DVR;
1324  path->dvr.fp_interface = rpath->frp_sw_if_index;
1325  }
1326  else if (rpath->frp_flags & FIB_ROUTE_PATH_EXCLUSIVE)
1327  {
1329  dpo_copy(&path->exclusive.fp_ex_dpo, &rpath->dpo);
1330  }
1331  else if (~0 != rpath->frp_sw_if_index)
1332  {
1333  if (ip46_address_is_zero(&rpath->frp_addr))
1334  {
1336  path->attached.fp_interface = rpath->frp_sw_if_index;
1337  }
1338  else
1339  {
1341  path->attached_next_hop.fp_interface = rpath->frp_sw_if_index;
1342  path->attached_next_hop.fp_nh = rpath->frp_addr;
1343  }
1344  }
1345  else
1346  {
1347  if (ip46_address_is_zero(&rpath->frp_addr))
1348  {
1349  if (~0 == rpath->frp_fib_index)
1350  {
1352  }
1353  else
1354  {
1355  path->fp_type = FIB_PATH_TYPE_DEAG;
1356  path->deag.fp_tbl_id = rpath->frp_fib_index;
1357  path->deag.fp_rpf_id = ~0;
1358  }
1359  }
1360  else
1361  {
1363  if (DPO_PROTO_MPLS == path->fp_nh_proto)
1364  {
1365  path->recursive.fp_nh.fp_local_label = rpath->frp_local_label;
1366  path->recursive.fp_nh.fp_eos = rpath->frp_eos;
1367  }
1368  else
1369  {
1370  path->recursive.fp_nh.fp_ip = rpath->frp_addr;
1371  }
1372  path->recursive.fp_tbl_id = rpath->frp_fib_index;
1373  }
1374  }
1375 
1376  FIB_PATH_DBG(path, "create");
1377 
1378  return (fib_path_get_index(path));
1379 }
1380 
1381 /*
1382  * fib_path_create_special
1383  *
1384  * Create and initialise a new path object.
1385  * return the index of the path.
1386  */
1389  dpo_proto_t nh_proto,
1391  const dpo_id_t *dpo)
1392 {
1393  fib_path_t *path;
1394 
1395  pool_get(fib_path_pool, path);
1396  memset(path, 0, sizeof(*path));
1397 
1398  fib_node_init(&path->fp_node,
1400  dpo_reset(&path->fp_dpo);
1401 
1402  path->fp_pl_index = pl_index;
1403  path->fp_weight = 1;
1404  path->fp_preference = 0;
1405  path->fp_nh_proto = nh_proto;
1407  path->fp_cfg_flags = flags;
1408 
1409  if (FIB_PATH_CFG_FLAG_DROP & flags)
1410  {
1412  }
1413  else if (FIB_PATH_CFG_FLAG_LOCAL & flags)
1414  {
1416  path->attached.fp_interface = FIB_NODE_INDEX_INVALID;
1417  }
1418  else
1419  {
1421  ASSERT(NULL != dpo);
1422  dpo_copy(&path->exclusive.fp_ex_dpo, dpo);
1423  }
1424 
1425  return (fib_path_get_index(path));
1426 }
1427 
1428 /*
1429  * fib_path_copy
1430  *
1431  * Copy a path. return index of new path.
1432  */
1435  fib_node_index_t path_list_index)
1436 {
1437  fib_path_t *path, *orig_path;
1438 
1439  pool_get(fib_path_pool, path);
1440 
1441  orig_path = fib_path_get(path_index);
1442  ASSERT(NULL != orig_path);
1443 
1444  memcpy(path, orig_path, sizeof(*path));
1445 
1446  FIB_PATH_DBG(path, "create-copy:%d", path_index);
1447 
1448  /*
1449  * reset the dynamic section
1450  */
1453  path->fp_pl_index = path_list_index;
1455  memset(&path->fp_dpo, 0, sizeof(path->fp_dpo));
1456  dpo_reset(&path->fp_dpo);
1457 
1458  return (fib_path_get_index(path));
1459 }
1460 
1461 /*
1462  * fib_path_destroy
1463  *
1464  * destroy a path that is no longer required
1465  */
1466 void
1468 {
1469  fib_path_t *path;
1470 
1471  path = fib_path_get(path_index);
1472 
1473  ASSERT(NULL != path);
1474  FIB_PATH_DBG(path, "destroy");
1475 
1476  fib_path_unresolve(path);
1477 
1478  fib_node_deinit(&path->fp_node);
1479  pool_put(fib_path_pool, path);
1480 }
1481 
1482 /*
1483  * fib_path_destroy
1484  *
1485  * destroy a path that is no longer required
1486  */
1487 uword
1489 {
1490  fib_path_t *path;
1491 
1492  path = fib_path_get(path_index);
1493 
1494  return (hash_memory(STRUCT_MARK_PTR(path, path_hash_start),
1495  (STRUCT_OFFSET_OF(fib_path_t, path_hash_end) -
1496  STRUCT_OFFSET_OF(fib_path_t, path_hash_start)),
1497  0));
1498 }
1499 
1500 /*
1501  * fib_path_cmp_i
1502  *
1503  * Compare two paths for equivalence.
1504  */
1505 static int
1507  const fib_path_t *path2)
1508 {
1509  int res;
1510 
1511  res = 1;
1512 
1513  /*
1514  * paths of different types and protocol are not equal.
1515  * different weights and/or preference only are the same path.
1516  */
1517  if (path1->fp_type != path2->fp_type)
1518  {
1519  res = (path1->fp_type - path2->fp_type);
1520  }
1521  else if (path1->fp_nh_proto != path2->fp_nh_proto)
1522  {
1523  res = (path1->fp_nh_proto - path2->fp_nh_proto);
1524  }
1525  else
1526  {
1527  /*
1528  * both paths are of the same type.
1529  * consider each type and its attributes in turn.
1530  */
1531  switch (path1->fp_type)
1532  {
1534  res = ip46_address_cmp(&path1->attached_next_hop.fp_nh,
1535  &path2->attached_next_hop.fp_nh);
1536  if (0 == res) {
1537  res = (path1->attached_next_hop.fp_interface -
1538  path2->attached_next_hop.fp_interface);
1539  }
1540  break;
1542  res = (path1->attached.fp_interface -
1543  path2->attached.fp_interface);
1544  break;
1546  res = ip46_address_cmp(&path1->recursive.fp_nh,
1547  &path2->recursive.fp_nh);
1548 
1549  if (0 == res)
1550  {
1551  res = (path1->recursive.fp_tbl_id - path2->recursive.fp_tbl_id);
1552  }
1553  break;
1555  res = (path1->bier_fmask.fp_bier_fmask -
1556  path2->bier_fmask.fp_bier_fmask);
1557  break;
1559  res = (path1->bier_imp.fp_bier_imp -
1560  path2->bier_imp.fp_bier_imp);
1561  break;
1563  res = bier_table_id_cmp(&path1->bier_table.fp_bier_tbl,
1564  &path2->bier_table.fp_bier_tbl);
1565  break;
1566  case FIB_PATH_TYPE_DEAG:
1567  res = (path1->deag.fp_tbl_id - path2->deag.fp_tbl_id);
1568  if (0 == res)
1569  {
1570  res = (path1->deag.fp_rpf_id - path2->deag.fp_rpf_id);
1571  }
1572  break;
1573  case FIB_PATH_TYPE_INTF_RX:
1574  res = (path1->intf_rx.fp_interface - path2->intf_rx.fp_interface);
1575  break;
1577  res = (path1->udp_encap.fp_udp_encap_id - path2->udp_encap.fp_udp_encap_id);
1578  break;
1579  case FIB_PATH_TYPE_DVR:
1580  res = (path1->dvr.fp_interface - path2->dvr.fp_interface);
1581  break;
1583  res = dpo_cmp(&path1->exclusive.fp_ex_dpo, &path2->exclusive.fp_ex_dpo);
1584  break;
1585  case FIB_PATH_TYPE_SPECIAL:
1586  case FIB_PATH_TYPE_RECEIVE:
1587  res = 0;
1588  break;
1589  }
1590  }
1591  return (res);
1592 }
1593 
1594 /*
1595  * fib_path_cmp_for_sort
1596  *
1597  * Compare two paths for equivalence. Used during path sorting.
1598  * As usual 0 means equal.
1599  */
1600 int
1602  void * v2)
1603 {
1604  fib_node_index_t *pi1 = v1, *pi2 = v2;
1605  fib_path_t *path1, *path2;
1606 
1607  path1 = fib_path_get(*pi1);
1608  path2 = fib_path_get(*pi2);
1609 
1610  /*
1611  * when sorting paths we want the highest preference paths
1612  * first, so that the choices set built is in prefernce order
1613  */
1614  if (path1->fp_preference != path2->fp_preference)
1615  {
1616  return (path1->fp_preference - path2->fp_preference);
1617  }
1618 
1619  return (fib_path_cmp_i(path1, path2));
1620 }
1621 
1622 /*
1623  * fib_path_cmp
1624  *
1625  * Compare two paths for equivalence.
1626  */
1627 int
1629  fib_node_index_t pi2)
1630 {
1631  fib_path_t *path1, *path2;
1632 
1633  path1 = fib_path_get(pi1);
1634  path2 = fib_path_get(pi2);
1635 
1636  return (fib_path_cmp_i(path1, path2));
1637 }
1638 
1639 int
1641  const fib_route_path_t *rpath)
1642 {
1643  fib_path_t *path;
1644  int res;
1645 
1646  path = fib_path_get(path_index);
1647 
1648  res = 1;
1649 
1650  if (path->fp_weight != rpath->frp_weight)
1651  {
1652  res = (path->fp_weight - rpath->frp_weight);
1653  }
1654  else
1655  {
1656  /*
1657  * both paths are of the same type.
1658  * consider each type and its attributes in turn.
1659  */
1660  switch (path->fp_type)
1661  {
1663  res = ip46_address_cmp(&path->attached_next_hop.fp_nh,
1664  &rpath->frp_addr);
1665  if (0 == res)
1666  {
1667  res = (path->attached_next_hop.fp_interface -
1668  rpath->frp_sw_if_index);
1669  }
1670  break;
1672  res = (path->attached.fp_interface - rpath->frp_sw_if_index);
1673  break;
1675  if (DPO_PROTO_MPLS == path->fp_nh_proto)
1676  {
1677  res = path->recursive.fp_nh.fp_local_label - rpath->frp_local_label;
1678 
1679  if (res == 0)
1680  {
1681  res = path->recursive.fp_nh.fp_eos - rpath->frp_eos;
1682  }
1683  }
1684  else
1685  {
1686  res = ip46_address_cmp(&path->recursive.fp_nh.fp_ip,
1687  &rpath->frp_addr);
1688  }
1689 
1690  if (0 == res)
1691  {
1692  res = (path->recursive.fp_tbl_id - rpath->frp_fib_index);
1693  }
1694  break;
1696  res = (path->bier_fmask.fp_bier_fmask - rpath->frp_bier_fmask);
1697  break;
1699  res = (path->bier_imp.fp_bier_imp - rpath->frp_bier_imp);
1700  break;
1702  res = bier_table_id_cmp(&path->bier_table.fp_bier_tbl,
1703  &rpath->frp_bier_tbl);
1704  break;
1705  case FIB_PATH_TYPE_INTF_RX:
1706  res = (path->intf_rx.fp_interface - rpath->frp_sw_if_index);
1707  break;
1709  res = (path->udp_encap.fp_udp_encap_id - rpath->frp_udp_encap_id);
1710  break;
1711  case FIB_PATH_TYPE_DEAG:
1712  res = (path->deag.fp_tbl_id - rpath->frp_fib_index);
1713  if (0 == res)
1714  {
1715  res = (path->deag.fp_rpf_id - rpath->frp_rpf_id);
1716  }
1717  break;
1718  case FIB_PATH_TYPE_DVR:
1719  res = (path->dvr.fp_interface - rpath->frp_sw_if_index);
1720  break;
1722  res = dpo_cmp(&path->exclusive.fp_ex_dpo, &rpath->dpo);
1723  break;
1724  case FIB_PATH_TYPE_SPECIAL:
1725  case FIB_PATH_TYPE_RECEIVE:
1726  res = 0;
1727  break;
1728  }
1729  }
1730  return (res);
1731 }
1732 
1733 /*
1734  * fib_path_recursive_loop_detect
1735  *
1736  * A forward walk of the FIB object graph to detect for a cycle/loop. This
1737  * walk is initiated when an entry is linking to a new path list or from an old.
1738  * The entry vector passed contains all the FIB entrys that are children of this
1739  * path (it is all the entries encountered on the walk so far). If this vector
1740  * contains the entry this path resolve via, then a loop is about to form.
1741  * The loop must be allowed to form, since we need the dependencies in place
1742  * so that we can track when the loop breaks.
1743  * However, we MUST not produce a loop in the forwarding graph (else packets
1744  * would loop around the switch path until the loop breaks), so we mark recursive
1745  * paths as looped so that they do not contribute forwarding information.
1746  * By marking the path as looped, an etry such as;
1747  * X/Y
1748  * via a.a.a.a (looped)
1749  * via b.b.b.b (not looped)
1750  * can still forward using the info provided by b.b.b.b only
1751  */
1752 int
1754  fib_node_index_t **entry_indicies)
1755 {
1756  fib_path_t *path;
1757 
1758  path = fib_path_get(path_index);
1759 
1760  /*
1761  * the forced drop path is never looped, cos it is never resolved.
1762  */
1763  if (fib_path_is_permanent_drop(path))
1764  {
1765  return (0);
1766  }
1767 
1768  switch (path->fp_type)
1769  {
1771  {
1772  fib_node_index_t *entry_index, *entries;
1773  int looped = 0;
1774  entries = *entry_indicies;
1775 
1776  vec_foreach(entry_index, entries) {
1777  if (*entry_index == path->fp_via_fib)
1778  {
1779  /*
1780  * the entry that is about to link to this path-list (or
1781  * one of this path-list's children) is the same entry that
1782  * this recursive path resolves through. this is a cycle.
1783  * abort the walk.
1784  */
1785  looped = 1;
1786  break;
1787  }
1788  }
1789 
1790  if (looped)
1791  {
1792  FIB_PATH_DBG(path, "recursive loop formed");
1794 
1795  dpo_copy(&path->fp_dpo, drop_dpo_get(path->fp_nh_proto));
1796  }
1797  else
1798  {
1799  /*
1800  * no loop here yet. keep forward walking the graph.
1801  */
1802  if (fib_entry_recursive_loop_detect(path->fp_via_fib, entry_indicies))
1803  {
1804  FIB_PATH_DBG(path, "recursive loop formed");
1806  }
1807  else
1808  {
1809  FIB_PATH_DBG(path, "recursive loop cleared");
1811  }
1812  }
1813  break;
1814  }
1817  case FIB_PATH_TYPE_SPECIAL:
1818  case FIB_PATH_TYPE_DEAG:
1819  case FIB_PATH_TYPE_DVR:
1820  case FIB_PATH_TYPE_RECEIVE:
1821  case FIB_PATH_TYPE_INTF_RX:
1827  /*
1828  * these path types cannot be part of a loop, since they are the leaves
1829  * of the graph.
1830  */
1831  break;
1832  }
1833 
1834  return (fib_path_is_looped(path_index));
1835 }
1836 
1837 int
1839 {
1840  fib_path_t *path;
1841 
1842  path = fib_path_get(path_index);
1843 
1844  /*
1845  * hope for the best.
1846  */
1848 
1849  /*
1850  * the forced drop path resolves via the drop adj
1851  */
1852  if (fib_path_is_permanent_drop(path))
1853  {
1854  dpo_copy(&path->fp_dpo, drop_dpo_get(path->fp_nh_proto));
1856  return (fib_path_is_resolved(path_index));
1857  }
1858 
1859  switch (path->fp_type)
1860  {
1863  break;
1865  /*
1866  * path->attached.fp_interface
1867  */
1869  path->attached.fp_interface))
1870  {
1872  }
1873  dpo_set(&path->fp_dpo,
1874  DPO_ADJACENCY,
1875  path->fp_nh_proto,
1877  dpo_proto_to_link(path->fp_nh_proto)));
1878 
1879  /*
1880  * become a child of the adjacency so we receive updates
1881  * when the interface state changes
1882  */
1883  path->fp_sibling = adj_child_add(path->fp_dpo.dpoi_index,
1885  fib_path_get_index(path));
1886  break;
1888  {
1889  /*
1890  * Create a RR source entry in the table for the address
1891  * that this path recurses through.
1892  * This resolve action is recursive, hence we may create
1893  * more paths in the process. more creates mean maybe realloc
1894  * of this path.
1895  */
1896  fib_node_index_t fei;
1897  fib_prefix_t pfx;
1898 
1900 
1901  if (DPO_PROTO_MPLS == path->fp_nh_proto)
1902  {
1903  fib_prefix_from_mpls_label(path->recursive.fp_nh.fp_local_label,
1904  path->recursive.fp_nh.fp_eos,
1905  &pfx);
1906  }
1907  else
1908  {
1909  fib_prefix_from_ip46_addr(&path->recursive.fp_nh.fp_ip, &pfx);
1910  }
1911 
1912  fib_table_lock(path->recursive.fp_tbl_id,
1914  FIB_SOURCE_RR);
1915  fei = fib_table_entry_special_add(path->recursive.fp_tbl_id,
1916  &pfx,
1917  FIB_SOURCE_RR,
1919 
1920  path = fib_path_get(path_index);
1921  path->fp_via_fib = fei;
1922 
1923  /*
1924  * become a dependent child of the entry so the path is
1925  * informed when the forwarding for the entry changes.
1926  */
1929  fib_path_get_index(path));
1930 
1931  /*
1932  * create and configure the IP DPO
1933  */
1935  path,
1936  fib_path_to_chain_type(path),
1937  &path->fp_dpo);
1938 
1939  break;
1940  }
1942  {
1943  /*
1944  * become a dependent child of the entry so the path is
1945  * informed when the forwarding for the entry changes.
1946  */
1947  path->fp_sibling = bier_fmask_child_add(path->bier_fmask.fp_bier_fmask,
1949  fib_path_get_index(path));
1950 
1951  path->fp_via_bier_fmask = path->bier_fmask.fp_bier_fmask;
1952  fib_path_bier_fmask_update(path, &path->fp_dpo);
1953 
1954  break;
1955  }
1957  bier_imp_lock(path->bier_imp.fp_bier_imp);
1958  bier_imp_contribute_forwarding(path->bier_imp.fp_bier_imp,
1959  DPO_PROTO_IP4,
1960  &path->fp_dpo);
1961  break;
1963  {
1964  /*
1965  * Find/create the BIER table to link to
1966  */
1968 
1969  path->fp_via_bier_tbl =
1970  bier_table_ecmp_create_and_lock(&path->bier_table.fp_bier_tbl);
1971 
1973  &path->fp_dpo);
1974  break;
1975  }
1976  case FIB_PATH_TYPE_SPECIAL:
1977  /*
1978  * Resolve via the drop
1979  */
1980  dpo_copy(&path->fp_dpo, drop_dpo_get(path->fp_nh_proto));
1981  break;
1982  case FIB_PATH_TYPE_DEAG:
1983  {
1984  if (DPO_PROTO_BIER == path->fp_nh_proto)
1985  {
1987  &path->fp_dpo);
1988  }
1989  else
1990  {
1991  /*
1992  * Resolve via a lookup DPO.
1993  * FIXME. control plane should add routes with a table ID
1994  */
1995  lookup_input_t input;
1996  lookup_cast_t cast;
1997 
1998  cast = (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RPF_ID ?
2000  LOOKUP_UNICAST);
2001  input = (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_DEAG_SRC ?
2004 
2005  lookup_dpo_add_or_lock_w_fib_index(path->deag.fp_tbl_id,
2006  path->fp_nh_proto,
2007  cast,
2008  input,
2010  &path->fp_dpo);
2011  }
2012  break;
2013  }
2014  case FIB_PATH_TYPE_DVR:
2015  dvr_dpo_add_or_lock(path->attached.fp_interface,
2016  path->fp_nh_proto,
2017  &path->fp_dpo);
2018  break;
2019  case FIB_PATH_TYPE_RECEIVE:
2020  /*
2021  * Resolve via a receive DPO.
2022  */
2024  path->receive.fp_interface,
2025  &path->receive.fp_addr,
2026  &path->fp_dpo);
2027  break;
2029  udp_encap_lock(path->udp_encap.fp_udp_encap_id);
2030  udp_encap_contribute_forwarding(path->udp_encap.fp_udp_encap_id,
2031  path->fp_nh_proto,
2032  &path->fp_dpo);
2033  break;
2034  case FIB_PATH_TYPE_INTF_RX: {
2035  /*
2036  * Resolve via a receive DPO.
2037  */
2039  path->intf_rx.fp_interface,
2040  &path->fp_dpo);
2041  break;
2042  }
2044  /*
2045  * Resolve via the user provided DPO
2046  */
2047  dpo_copy(&path->fp_dpo, &path->exclusive.fp_ex_dpo);
2048  break;
2049  }
2050 
2051  return (fib_path_is_resolved(path_index));
2052 }
2053 
2054 u32
2056 {
2057  fib_path_t *path;
2058 
2059  path = fib_path_get(path_index);
2060 
2061  switch (path->fp_type)
2062  {
2064  return (path->attached_next_hop.fp_interface);
2066  return (path->attached.fp_interface);
2067  case FIB_PATH_TYPE_RECEIVE:
2068  return (path->receive.fp_interface);
2070  if (fib_path_is_resolved(path_index))
2071  {
2073  }
2074  break;
2075  case FIB_PATH_TYPE_DVR:
2076  return (path->dvr.fp_interface);
2077  case FIB_PATH_TYPE_INTF_RX:
2079  case FIB_PATH_TYPE_SPECIAL:
2080  case FIB_PATH_TYPE_DEAG:
2085  break;
2086  }
2087  return (dpo_get_urpf(&path->fp_dpo));
2088 }
2089 
2090 index_t
2092 {
2093  fib_path_t *path;
2094 
2095  path = fib_path_get(path_index);
2096 
2097  switch (path->fp_type)
2098  {
2101  case FIB_PATH_TYPE_RECEIVE:
2102  case FIB_PATH_TYPE_INTF_RX:
2103  case FIB_PATH_TYPE_SPECIAL:
2104  case FIB_PATH_TYPE_DEAG:
2105  case FIB_PATH_TYPE_DVR:
2107  break;
2109  return (path->udp_encap.fp_udp_encap_id);
2111  return (path->fp_via_fib);
2113  return (path->bier_fmask.fp_bier_fmask);
2115  return (path->fp_via_bier_tbl);
2117  return (path->bier_imp.fp_bier_imp);
2118  }
2119  return (~0);
2120 }
2121 
2124 {
2125  fib_path_t *path;
2126 
2127  path = fib_path_get(path_index);
2128 
2129  ASSERT(dpo_is_adj(&path->fp_dpo));
2130  if (dpo_is_adj(&path->fp_dpo))
2131  {
2132  return (path->fp_dpo.dpoi_index);
2133  }
2134  return (ADJ_INDEX_INVALID);
2135 }
2136 
2137 u16
2139 {
2140  fib_path_t *path;
2141 
2142  path = fib_path_get(path_index);
2143 
2144  ASSERT(path);
2145 
2146  return (path->fp_weight);
2147 }
2148 
2149 u16
2151 {
2152  fib_path_t *path;
2153 
2154  path = fib_path_get(path_index);
2155 
2156  ASSERT(path);
2157 
2158  return (path->fp_preference);
2159 }
2160 
2161 u32
2163 {
2164  fib_path_t *path;
2165 
2166  path = fib_path_get(path_index);
2167 
2168  ASSERT(path);
2169 
2171  {
2172  return (path->deag.fp_rpf_id);
2173  }
2174 
2175  return (~0);
2176 }
2177 
2178 /**
2179  * @brief Contribute the path's adjacency to the list passed.
2180  * By calling this function over all paths, recursively, a child
2181  * can construct its full set of forwarding adjacencies, and hence its
2182  * uRPF list.
2183  */
2184 void
2186  index_t urpf)
2187 {
2188  fib_path_t *path;
2189 
2190  path = fib_path_get(path_index);
2191 
2192  /*
2193  * resolved and unresolved paths contribute to the RPF list.
2194  */
2195  switch (path->fp_type)
2196  {
2198  fib_urpf_list_append(urpf, path->attached_next_hop.fp_interface);
2199  break;
2200 
2202  fib_urpf_list_append(urpf, path->attached.fp_interface);
2203  break;
2204 
2206  if (FIB_NODE_INDEX_INVALID != path->fp_via_fib &&
2207  !fib_path_is_looped(path_index))
2208  {
2209  /*
2210  * there's unresolved due to constraints, and there's unresolved
2211  * due to ain't got no via. can't do nowt w'out via.
2212  */
2214  }
2215  break;
2216 
2218  case FIB_PATH_TYPE_SPECIAL:
2219  {
2220  /*
2221  * these path types may link to an adj, if that's what
2222  * the clinet gave
2223  */
2224  u32 rpf_sw_if_index;
2225 
2226  rpf_sw_if_index = dpo_get_urpf(&path->fp_dpo);
2227 
2228  if (~0 != rpf_sw_if_index)
2229  {
2230  fib_urpf_list_append(urpf, rpf_sw_if_index);
2231  }
2232  break;
2233  }
2234  case FIB_PATH_TYPE_DVR:
2235  fib_urpf_list_append(urpf, path->dvr.fp_interface);
2236  break;
2237  case FIB_PATH_TYPE_DEAG:
2238  case FIB_PATH_TYPE_RECEIVE:
2239  case FIB_PATH_TYPE_INTF_RX:
2244  /*
2245  * these path types don't link to an adj
2246  */
2247  break;
2248  }
2249 }
2250 
2251 void
2253  dpo_proto_t payload_proto,
2254  fib_mpls_lsp_mode_t mode,
2255  dpo_id_t *dpo)
2256 {
2257  fib_path_t *path;
2258 
2259  path = fib_path_get(path_index);
2260 
2261  ASSERT(path);
2262 
2263  switch (path->fp_type)
2264  {
2266  {
2267  dpo_id_t tmp = DPO_INVALID;
2268 
2269  dpo_copy(&tmp, dpo);
2270 
2271  mpls_disp_dpo_create(payload_proto, ~0, mode, &tmp, dpo);
2272  dpo_reset(&tmp);
2273  break;
2274  }
2275  case FIB_PATH_TYPE_DEAG:
2276  {
2277  dpo_id_t tmp = DPO_INVALID;
2278 
2279  dpo_copy(&tmp, dpo);
2280 
2281  mpls_disp_dpo_create(payload_proto,
2282  path->deag.fp_rpf_id,
2283  mode, &tmp, dpo);
2284  dpo_reset(&tmp);
2285  break;
2286  }
2287  case FIB_PATH_TYPE_RECEIVE:
2290  case FIB_PATH_TYPE_INTF_RX:
2293  case FIB_PATH_TYPE_SPECIAL:
2297  case FIB_PATH_TYPE_DVR:
2298  break;
2299  }
2300 }
2301 
2302 void
2305  dpo_id_t *dpo)
2306 {
2307  fib_path_t *path;
2308 
2309  path = fib_path_get(path_index);
2310 
2311  ASSERT(path);
2313 
2314  FIB_PATH_DBG(path, "contribute");
2315 
2316  /*
2317  * The DPO stored in the path was created when the path was resolved.
2318  * This then represents the path's 'native' protocol; IP.
2319  * For all others will need to go find something else.
2320  */
2321  if (fib_path_to_chain_type(path) == fct)
2322  {
2323  dpo_copy(dpo, &path->fp_dpo);
2324  }
2325  else
2326  {
2327  switch (path->fp_type)
2328  {
2330  switch (fct)
2331  {
2340  {
2341  adj_index_t ai;
2342 
2343  /*
2344  * get a appropriate link type adj.
2345  */
2347  path,
2349  dpo_set(dpo, DPO_ADJACENCY,
2351  adj_unlock(ai);
2352 
2353  break;
2354  }
2356  break;
2357  }
2358  break;
2360  switch (fct)
2361  {
2369  fib_path_recursive_adj_update(path, fct, dpo);
2370  break;
2373  ASSERT(0);
2374  break;
2375  }
2376  break;
2378  switch (fct)
2379  {
2382  break;
2391  ASSERT(0);
2392  break;
2393  }
2394  break;
2396  switch (fct)
2397  {
2399  fib_path_bier_fmask_update(path, dpo);
2400  break;
2409  ASSERT(0);
2410  break;
2411  }
2412  break;
2414  bier_imp_contribute_forwarding(path->bier_imp.fp_bier_imp,
2416  dpo);
2417  break;
2418  case FIB_PATH_TYPE_DEAG:
2419  switch (fct)
2420  {
2427  dpo);
2428  break;
2432  dpo_copy(dpo, &path->fp_dpo);
2433  break;
2437  break;
2440  ASSERT(0);
2441  break;
2442  }
2443  break;
2445  dpo_copy(dpo, &path->exclusive.fp_ex_dpo);
2446  break;
2448  switch (fct)
2449  {
2457  {
2458  adj_index_t ai;
2459 
2460  /*
2461  * get a appropriate link type adj.
2462  */
2464  path,
2466  dpo_set(dpo, DPO_ADJACENCY,
2468  adj_unlock(ai);
2469  break;
2470  }
2473  {
2474  adj_index_t ai;
2475 
2476  /*
2477  * Create the adj needed for sending IP multicast traffic
2478  */
2481  path->attached.fp_interface);
2482  dpo_set(dpo, DPO_ADJACENCY,
2484  ai);
2485  adj_unlock(ai);
2486  }
2487  break;
2488  }
2489  break;
2490  case FIB_PATH_TYPE_INTF_RX:
2491  /*
2492  * Create the adj needed for sending IP multicast traffic
2493  */
2495  path->attached.fp_interface,
2496  dpo);
2497  break;
2499  udp_encap_contribute_forwarding(path->udp_encap.fp_udp_encap_id,
2500  path->fp_nh_proto,
2501  dpo);
2502  break;
2503  case FIB_PATH_TYPE_RECEIVE:
2504  case FIB_PATH_TYPE_SPECIAL:
2505  case FIB_PATH_TYPE_DVR:
2506  dpo_copy(dpo, &path->fp_dpo);
2507  break;
2508  }
2509  }
2510 }
2511 
2515  load_balance_path_t *hash_key)
2516 {
2517  load_balance_path_t *mnh;
2518  fib_path_t *path;
2519 
2520  path = fib_path_get(path_index);
2521 
2522  ASSERT(path);
2523 
2524  if (fib_path_is_resolved(path_index))
2525  {
2526  vec_add2(hash_key, mnh, 1);
2527 
2528  mnh->path_weight = path->fp_weight;
2529  mnh->path_index = path_index;
2530  fib_path_contribute_forwarding(path_index, fct, &mnh->path_dpo);
2531  }
2532 
2533  return (hash_key);
2534 }
2535 
2536 int
2538 {
2539  fib_path_t *path;
2540 
2541  path = fib_path_get(path_index);
2542 
2543  return ((FIB_PATH_TYPE_RECURSIVE == path->fp_type) &&
2546 }
2547 
2548 int
2550 {
2551  fib_path_t *path;
2552 
2553  path = fib_path_get(path_index);
2554 
2555  return (FIB_PATH_TYPE_EXCLUSIVE == path->fp_type);
2556 }
2557 
2558 int
2560 {
2561  fib_path_t *path;
2562 
2563  path = fib_path_get(path_index);
2564 
2565  return (FIB_PATH_TYPE_DEAG == path->fp_type);
2566 }
2567 
2568 int
2570 {
2571  fib_path_t *path;
2572 
2573  path = fib_path_get(path_index);
2574 
2575  return (dpo_id_is_valid(&path->fp_dpo) &&
2577  !fib_path_is_looped(path_index) &&
2579 }
2580 
2581 int
2583 {
2584  fib_path_t *path;
2585 
2586  path = fib_path_get(path_index);
2587 
2589 }
2590 
2593  fib_node_index_t path_index,
2594  void *ctx)
2595 {
2596  fib_route_path_encode_t **api_rpaths = ctx;
2597  fib_route_path_encode_t *api_rpath;
2598  fib_path_t *path;
2599 
2600  path = fib_path_get(path_index);
2601  if (!path)
2602  return (FIB_PATH_LIST_WALK_CONTINUE);
2603  vec_add2(*api_rpaths, api_rpath, 1);
2604  api_rpath->rpath.frp_weight = path->fp_weight;
2605  api_rpath->rpath.frp_preference = path->fp_preference;
2606  api_rpath->rpath.frp_proto = path->fp_nh_proto;
2607  api_rpath->rpath.frp_sw_if_index = ~0;
2608  api_rpath->rpath.frp_fib_index = 0;
2609  api_rpath->dpo = path->fp_dpo;
2610 
2611  switch (path->fp_type)
2612  {
2613  case FIB_PATH_TYPE_RECEIVE:
2614  api_rpath->rpath.frp_addr = path->receive.fp_addr;
2615  api_rpath->rpath.frp_sw_if_index = path->receive.fp_interface;
2616  break;
2618  api_rpath->rpath.frp_sw_if_index = path->attached.fp_interface;
2619  break;
2621  api_rpath->rpath.frp_sw_if_index = path->attached_next_hop.fp_interface;
2622  api_rpath->rpath.frp_addr = path->attached_next_hop.fp_nh;
2623  break;
2625  api_rpath->rpath.frp_bier_fmask = path->bier_fmask.fp_bier_fmask;
2626  break;
2627  case FIB_PATH_TYPE_SPECIAL:
2628  break;
2629  case FIB_PATH_TYPE_DEAG:
2630  api_rpath->rpath.frp_fib_index = path->deag.fp_tbl_id;
2631  break;
2633  api_rpath->rpath.frp_addr = path->recursive.fp_nh.fp_ip;
2634  api_rpath->rpath.frp_fib_index = path->recursive.fp_tbl_id;
2635  break;
2636  case FIB_PATH_TYPE_DVR:
2637  api_rpath->rpath.frp_sw_if_index = path->dvr.fp_interface;
2638  api_rpath->rpath.frp_flags |= FIB_ROUTE_PATH_DVR;
2639  break;
2641  api_rpath->rpath.frp_udp_encap_id = path->udp_encap.fp_udp_encap_id;
2643  break;
2644  default:
2645  break;
2646  }
2647 
2648  return (FIB_PATH_LIST_WALK_CONTINUE);
2649 }
2650 
2653 {
2654  fib_path_t *path;
2655 
2656  path = fib_path_get(path_index);
2657 
2658  return (path->fp_nh_proto);
2659 }
2660 
2661 void
2663 {
2664  fib_node_register_type (FIB_NODE_TYPE_PATH, &fib_path_vft);
2665 }
2666 
2667 static clib_error_t *
2669  unformat_input_t * input,
2670  vlib_cli_command_t * cmd)
2671 {
2672  fib_node_index_t pi;
2673  fib_path_t *path;
2674 
2675  if (unformat (input, "%d", &pi))
2676  {
2677  /*
2678  * show one in detail
2679  */
2680  if (!pool_is_free_index(fib_path_pool, pi))
2681  {
2682  path = fib_path_get(pi);
2683  u8 *s = format(NULL, "%U", format_fib_path, pi, 1);
2684  s = format(s, "children:");
2686  vlib_cli_output (vm, "%s", s);
2687  vec_free(s);
2688  }
2689  else
2690  {
2691  vlib_cli_output (vm, "path %d invalid", pi);
2692  }
2693  }
2694  else
2695  {
2696  vlib_cli_output (vm, "FIB Paths");
2697  pool_foreach_index (pi, fib_path_pool,
2698  ({
2699  vlib_cli_output (vm, "%U", format_fib_path, pi, 0);
2700  }));
2701  }
2702 
2703  return (NULL);
2704 }
2705 
2706 VLIB_CLI_COMMAND (show_fib_path, static) = {
2707  .path = "show fib paths",
2708  .function = show_fib_path_command,
2709  .short_help = "show fib paths",
2710 };
int fib_path_is_resolved(fib_node_index_t path_index)
Definition: fib_path.c:2569
Contribute an object that is to be used to forward BIER packets.
Definition: fib_types.h:122
int fib_path_resolve(fib_node_index_t path_index)
Definition: fib_path.c:1838
Contribute an object that is to be used to forward IP6 packets.
Definition: fib_types.h:137
ip46_address_t frp_addr
The next-hop address.
Definition: fib_types.h:486
Recursive resolution source.
Definition: fib_entry.h:125
A path that resolves via a DVR DPO.
Definition: fib_types.h:381
void mpls_disp_dpo_create(dpo_proto_t payload_proto, fib_rpf_id_t rpf_id, fib_mpls_lsp_mode_t mode, const dpo_id_t *parent, dpo_id_t *dpo)
Create an MPLS label object.
Contribute an object that is to be used to forward IP6 packets.
Definition: fib_types.h:113
void receive_dpo_add_or_lock(dpo_proto_t proto, u32 sw_if_index, const ip46_address_t *nh_addr, dpo_id_t *dpo)
Definition: receive_dpo.c:56
static fib_path_t * fib_path_from_fib_node(fib_node_t *node)
Definition: fib_path.c:448
void bier_imp_contribute_forwarding(index_t bii, dpo_proto_t proto, dpo_id_t *dpo)
Definition: bier_imp.c:174
uword fib_path_hash(fib_node_index_t path_index)
Definition: fib_path.c:1488
fib_node_index_t path_index
The index of the FIB path.
Definition: load_balance.h:71
A representation of a fib path for fib_path_encode to convey the information to the caller...
Definition: fib_types.h:584
void fib_path_contribute_forwarding(fib_node_index_t path_index, fib_forward_chain_type_t fct, dpo_id_t *dpo)
Definition: fib_path.c:2303
index_t fp_bier_fmask
BIER FMask ID.
Definition: fib_path.c:297
void lookup_dpo_add_or_lock_w_table_id(u32 table_id, dpo_proto_t proto, lookup_cast_t cast, lookup_input_t input, lookup_table_t table_config, dpo_id_t *dpo)
Definition: lookup_dpo.c:159
mpls_eos_bit_t frp_eos
EOS bit for the resolving label.
Definition: fib_types.h:497
fib_path_oper_attribute_t_
Enurmeration of path operational (i.e.
Definition: fib_path.c:141
int fib_entry_is_resolved(fib_node_index_t fib_entry_index)
Return !0 is the entry is reoslved, i.e.
Definition: fib_entry.c:1444
index_t fib_path_get_resolving_index(fib_node_index_t path_index)
Definition: fib_path.c:2091
void fib_path_contribute_urpf(fib_node_index_t path_index, index_t urpf)
Contribute the path&#39;s adjacency to the list passed.
Definition: fib_path.c:2185
A representation of a path as described by a route producer.
Definition: fib_types.h:470
u8 * format_dpo_type(u8 *s, va_list *args)
format a DPO type
Definition: dpo.c:137
dpo_id_t path_dpo
ID of the Data-path object.
Definition: load_balance.h:66
struct fib_path_t_::@133::@147 intf_rx
int dpo_is_adj(const dpo_id_t *dpo)
Return TRUE is the DPO is any type of adjacency.
Definition: dpo.c:277
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
u8 * format_bier_table_id(u8 *s, va_list *ap)
Format a BIER table ID.
Definition: bier_types.c:193
#define FIB_PATH_OPER_ATTRIBUTES
Definition: fib_path.c:173
#define STRUCT_MARK_PTR(v, f)
Definition: clib.h:70
int fib_path_cmp(fib_node_index_t pi1, fib_node_index_t pi2)
Definition: fib_path.c:1628
A Drop path - resolve the path on the drop DPO.
Definition: fib_types.h:340
void bier_fmask_contribute_forwarding(index_t bfmi, dpo_id_t *dpo)
Definition: bier_fmask.c:120
struct fib_path_t_::@133::@141 bier_table
void fib_node_init(fib_node_t *node, fib_node_type_t type)
Definition: fib_node.c:185
index_t fp_bier_imp
The BIER imposition object this is part of the path&#39;s key, since the index_t of an imposition object ...
Definition: fib_path.c:311
u32 fib_entry_child_add(fib_node_index_t fib_entry_index, fib_node_type_t child_type, fib_node_index_t child_index)
Definition: fib_entry.c:527
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 NULL
Definition: clib.h:57
A path that resolves via a BIER impostion object.
Definition: fib_types.h:373
struct fib_path_t_::@133::@138 attached
void fib_path_module_init(void)
Definition: fib_path.c:2662
int fib_path_is_exclusive(fib_node_index_t path_index)
Definition: fib_path.c:2549
void bier_imp_lock(index_t bii)
Definition: bier_imp.c:48
enum fib_node_back_walk_rc_t_ fib_node_back_walk_rc_t
Return code from a back walk function.
void fib_entry_contribute_forwarding(fib_node_index_t fib_entry_index, fib_forward_chain_type_t fct, dpo_id_t *dpo)
Definition: fib_entry.c:419
static void fib_path_bier_fmask_update(fib_path_t *path, dpo_id_t *dpo)
Definition: fib_path.c:825
index_t frp_bier_imp
A path via a BIER imposition object.
Definition: fib_types.h:542
void bier_table_ecmp_unlock(index_t bti)
Definition: bier_table.c:462
u32 mpls_label_t
A label value only, i.e.
Definition: packet.h:24
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
void load_balance_map_path_state_change(fib_node_index_t path_index)
the state of a path has changed (it has no doubt gone down).
void fib_entry_child_remove(fib_node_index_t fib_entry_index, u32 sibling_index)
Definition: fib_entry.c:538
fib_node_index_t fp_tbl_id
The FIB table index in which to find the next-hop.
Definition: fib_path.c:286
void dpo_copy(dpo_id_t *dst, const dpo_id_t *src)
atomic copy a data-plane object.
Definition: dpo.c:261
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:41
u32 dpo_get_urpf(const dpo_id_t *dpo)
Get a uRPF interface for the DPO.
Definition: dpo.c:381
#define STRUCT_MARK(mark)
Definition: clib.h:69
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:562
struct fib_path_t_::@133::@149 dvr
A path that resolves via a BIER [ECMP] Table.
Definition: fib_types.h:369
The path is resolved.
Definition: fib_path.c:153
format_function_t format_ip46_address
Definition: format.h:61
Contribute an object that is to be used to forward IP4 packets.
Definition: fib_types.h:109
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:64
void fib_node_deinit(fib_node_t *node)
Definition: fib_node.c:197
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
const fib_prefix_t * fib_entry_get_prefix(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:1622
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
dpo_proto_t frp_proto
The protocol of the address below.
Definition: fib_types.h:475
bier_table_id_t frp_bier_tbl
A path that resolves via a BIER Table.
Definition: fib_types.h:536
A path that result in received traffic being recieved/recirculated so that it appears to have arrived...
Definition: fib_types.h:349
dpo_id_t fp_ex_dpo
The user provided &#39;exclusive&#39; DPO.
Definition: fib_path.c:329
int fib_path_is_looped(fib_node_index_t path_index)
Definition: fib_path.c:2582
Definition: fib_entry.h:277
The ID of a table.
Definition: bier_types.h:394
void adj_child_remove(adj_index_t adj_index, u32 sibling_index)
Remove a child dependent.
Definition: adj.c:288
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:228
struct fib_path_t_::@133::@137 attached_next_hop
The path has become a permanent drop.
Definition: fib_path.c:161
int fib_path_cmp_for_sort(void *v1, void *v2)
Definition: fib_path.c:1601
#define ip46_address_cmp(ip46_1, ip46_2)
Definition: ip6_packet.h:92
unsigned char u8
Definition: types.h:56
#define pool_len(p)
Number of elements in pool vector.
Definition: pool.h:140
ip46_address_t fp_ip
The next-hop.
Definition: fib_path.c:270
load_balance_path_t * fib_path_append_nh_for_multipath_hash(fib_node_index_t path_index, fib_forward_chain_type_t fct, load_balance_path_t *hash_key)
Definition: fib_path.c:2513
struct fib_path_t_::@133::@139 recursive
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
const dpo_id_t * drop_dpo_get(dpo_proto_t proto)
Definition: drop_dpo.c:25
fib_rpf_id_t frp_rpf_id
The RPF-ID.
Definition: fib_types.h:509
A local path with a RPF-ID => multicast traffic.
Definition: fib_types.h:353
#define FIB_PATH_TYPES
Definition: fib_path.c:117
memset(h->entries, 0, sizeof(h->entries[0])*entries)
fib_path_type_t fp_type
The type of the path.
Definition: fib_path.c:223
u32 frp_sw_if_index
The interface.
Definition: fib_types.h:505
mpls_eos_bit_t fp_eos
The EOS bit of the resolving label.
Definition: fib_path.c:279
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:407
static const adj_index_t fib_path_attached_next_hop_get_adj(fib_path_t *path, vnet_link_t link)
Definition: fib_path.c:635
void bier_table_contribute_forwarding(index_t bti, dpo_id_t *dpo)
Definition: bier_table.c:728
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
Recursion constraint of via a host prefix.
Definition: fib_types.h:324
struct fib_path_t_::@133::@148 udp_encap
fib_node_index_t fib_path_copy(fib_node_index_t path_index, fib_node_index_t path_list_index)
Definition: fib_path.c:1434
u8 * format_bier_imp(u8 *s, va_list *args)
Definition: bier_imp.c:137
void bier_fmask_child_remove(fib_node_index_t bfmi, u32 sibling_index)
Definition: bier_fmask.c:152
Aggregrate type for a prefix.
Definition: fib_types.h:203
fib_path_cfg_flags_t fp_cfg_flags
Configuration Flags.
Definition: fib_path.c:218
void fib_entry_contribute_urpf(fib_node_index_t entry_index, index_t urpf)
Contribute the set of Adjacencies that this entry forwards with to build the uRPF list of its childre...
Definition: fib_entry.c:373
struct fib_path_t_::@133::@146 receive
void fib_show_memory_usage(const char *name, u32 in_use_elts, u32 allocd_elts, size_t size_elt)
Show the memory usage for a type.
Definition: fib_node.c:220
fib_node_t fp_node
A path is a node in the FIB graph.
Definition: fib_path.c:202
interface receive.
Definition: fib_path.c:81
void adj_unlock(adj_index_t adj_index)
Release a reference counting lock on the adjacency.
Definition: adj.c:252
A path via a UDP encap object.
Definition: fib_types.h:361
dpo_id_t fp_dpo
The Data-path objects through which this path resolves for IP.
Definition: fib_path.c:392
struct fib_path_t_::@133::@145 exclusive
unsigned int u32
Definition: types.h:88
#define FIB_PATH_CFG_ATTRIBUTES
Definition: fib_path.h:97
Contribute an object that is to be used to forward Ethernet packets.
Definition: fib_types.h:141
struct fib_path_t_::@133::@140 bier_fmask
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
fib_protocol_t dpo_proto_to_fib(dpo_proto_t dpo_proto)
Definition: fib_types.c:253
int load_balance_is_drop(const dpo_id_t *dpo)
Definition: load_balance.c:236
u16 fib_path_get_weight(fib_node_index_t path_index)
Definition: fib_path.c:2138
enum lookup_cast_t_ lookup_cast_t
Switch to use the packet&#39;s source or destination address for lookup.
void fib_urpf_list_append(index_t ui, u32 sw_if_index)
Append another interface to the list.
static void fib_path_attached_next_hop_set(fib_path_t *path)
Definition: fib_path.c:662
fib_node_index_t fib_path_create_special(fib_node_index_t pl_index, dpo_proto_t nh_proto, fib_path_cfg_flags_t flags, const dpo_id_t *dpo)
Definition: fib_path.c:1388
Definition: fib_entry.h:275
fib_rpf_id_t fp_rpf_id
The RPF-ID to tag the packets with.
Definition: fib_path.c:321
void bier_disp_table_contribute_forwarding(index_t bdti, dpo_id_t *dpo)
index_t frp_bier_fmask
Resolving via a BIER Fmask.
Definition: fib_types.h:552
u8 * format_fib_path(u8 *s, va_list *args)
Definition: fib_path.c:455
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
u32 fp_sibling
the index of this path in the parent&#39;s child list.
Definition: fib_path.c:397
Contribute an object that is to be used to forward end-of-stack MPLS packets.
Definition: fib_types.h:129
fib_node_bw_reason_flag_t fnbw_reason
The reason/trigger for the backwalk.
Definition: fib_node.h:206
format_function_t format_mpls_eos_bit
Definition: mpls.h:67
format_function_t format_vnet_sw_interface_name
#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
int adj_is_up(adj_index_t ai)
Return true if the adjacency is &#39;UP&#39;, i.e.
Definition: adj.c:427
dpo_proto_t fp_nh_proto
The protocol of the next-hop, i.e.
Definition: fib_path.c:230
struct fib_path_t_ fib_path_t
A FIB path.
dpo_type_t dpoi_type
the type
Definition: dpo.h:172
int vnet_sw_interface_is_p2p(vnet_main_t *vnm, u32 sw_if_index)
Definition: interface.c:1173
long ctx[MAX_CONNS]
Definition: main.c:144
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
adj_index_t fib_path_get_adj(fib_node_index_t path_index)
Definition: fib_path.c:2123
enum fib_mpls_lsp_mode_t_ fib_mpls_lsp_mode_t
MPLS LSP mode - only valid at the head and tail.
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:274
index_t fp_via_bier_tbl
the resolving bier-table
Definition: fib_path.c:382
Recursion constraint of via an attahced prefix.
Definition: fib_types.h:328
void lookup_dpo_add_or_lock_w_fib_index(fib_node_index_t fib_index, dpo_proto_t proto, lookup_cast_t cast, lookup_input_t input, lookup_table_t table_config, dpo_id_t *dpo)
Definition: lookup_dpo.c:133
void fib_path_stack_mpls_disp(fib_node_index_t path_index, dpo_proto_t payload_proto, fib_mpls_lsp_mode_t mode, dpo_id_t *dpo)
Definition: fib_path.c:2252
fib_node_type_t fn_type
The node&#39;s type.
Definition: fib_node.h:293
enum fib_path_cfg_attribute_t_ fib_path_cfg_attribute_t
Given a route of the form; q.r.s.t/Y via <interface> <next-hop>
An node in the FIB graph.
Definition: fib_node.h:289
dpo_id_t dpo
Exclusive DPO.
Definition: fib_types.h:530
void fib_table_unlock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Take a reference counting lock on the table.
Definition: fib_table.c:1236
static fib_path_t * fib_path_pool
Definition: fib_path.c:410
static fib_path_t * fib_path_get(fib_node_index_t index)
Definition: fib_path.c:430
ip46_address_t fp_nh
The next-hop.
Definition: fib_path.c:252
void dvr_dpo_add_or_lock(u32 sw_if_index, dpo_proto_t dproto, dpo_id_t *dpo)
Definition: dvr_dpo.c:87
u32 flags
Definition: vhost_user.h:115
u32 fib_entry_get_resolving_interface(fib_node_index_t entry_index)
Definition: fib_entry.c:1409
fib_path_oper_flags_t_
Path flags from the attributes.
Definition: fib_path.c:187
fib_node_index_t fib_table_entry_special_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags)
Add a &#39;special&#39; entry to the FIB.
Definition: fib_table.c:388
#define FOR_EACH_FIB_PATH_OPER_ATTRIBUTE(_item)
Definition: fib_path.c:179
#define MPLS_FIB_DEFAULT_TABLE_ID
Definition: mpls_fib.h:28
The path forms part of a recursive loop.
Definition: fib_path.c:149
vnet_link_t fib_forw_chain_type_to_link_type(fib_forward_chain_type_t fct)
Convert from a chain type to the adjacency&#39;s link type.
Definition: fib_types.c:359
fib_node_list_t fn_children
Vector of nodes that depend upon/use/share this node.
Definition: fib_node.h:303
vlib_main_t * vm
Definition: buffer.c:294
int bier_table_id_cmp(const bier_table_id_t *btid1, const bier_table_id_t *btid2)
Compare to BIER table IDs for equality.
Definition: bier_types.c:112
via a DVR.
Definition: fib_path.c:105
u8 * fib_path_format(fib_node_index_t pi, u8 *s)
Definition: fib_path.c:612
void udp_encap_lock(index_t uei)
Definition: udp_encap.c:152
Contribute an object that is to be used to forward NSH packets.
Definition: fib_types.h:147
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:339
u32 fp_udp_encap_id
The UDP Encap object this path resolves through.
Definition: fib_path.c:351
static void fib_path_last_lock_gone(fib_node_t *node)
Definition: fib_path.c:629
static fib_node_index_t fib_path_get_index(fib_path_t *path)
Definition: fib_path.c:436
A FIB path.
Definition: fib_path.c:198
int fib_entry_recursive_loop_detect(fib_node_index_t entry_index, fib_node_index_t **entry_indicies)
Definition: fib_entry.c:1358
fib_node_get_t fnv_get
Definition: fib_node.h:277
enum fib_path_oper_flags_t_ fib_path_oper_flags_t
Path flags from the attributes.
index_t fp_via_bier_fmask
the resolving bier-fmask
Definition: fib_path.c:386
u32 fib_path_get_rpf_id(fib_node_index_t path_index)
Definition: fib_path.c:2162
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:30
void interface_rx_dpo_add_or_lock(dpo_proto_t proto, u32 sw_if_index, dpo_id_t *dpo)
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:271
Don&#39;t resolve the path, use the DPO the client provides.
Definition: fib_types.h:344
u32 adj_index_t
An index for adjacencies.
Definition: adj_types.h:30
void fib_prefix_from_ip46_addr(const ip46_address_t *addr, fib_prefix_t *pfx)
Host prefix from ip.
Definition: fib_types.c:80
static void fib_path_memory_show(void)
Definition: fib_path.c:1197
The path is attached, despite what the next-hop may say.
Definition: fib_path.c:157
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_prefix_from_mpls_label(mpls_label_t label, mpls_eos_bit_t eos, fib_prefix_t *prf)
Big train switch; FIB debugs on or off.
Definition: fib_types.c:94
static fib_node_back_walk_rc_t fib_path_back_walk_notify(fib_node_t *node, fib_node_back_walk_ctx_t *ctx)
Definition: fib_path.c:962
Path resolves via a UDP encap object.
Definition: fib_path.c:85
enum lookup_input_t_ lookup_input_t
Switch to use the packet&#39;s source or destination address for lookup.
void fib_table_lock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Release a reference counting lock on the table.
Definition: fib_table.c:1265
Context passed between object during a back walk.
Definition: fib_node.h:202
u32 fib_rpf_id_t
An RPF-ID is numerical value that is used RPF validate.
Definition: fib_types.h:391
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:155
u32 fp_pl_index
The index of the path-list to which this path belongs.
Definition: fib_path.c:207
static void fib_path_recursive_adj_update(fib_path_t *path, fib_forward_chain_type_t fct, dpo_id_t *dpo)
Definition: fib_path.c:720
static const adj_index_t fib_path_attached_get_adj(fib_path_t *path, vnet_link_t link)
Definition: fib_path.c:692
#define ASSERT(truth)
int fib_path_is_deag(fib_node_index_t path_index)
Definition: fib_path.c:2559
vnet_link_t dpo_proto_to_link(dpo_proto_t dp)
format a DPO protocol
Definition: dpo.c:117
fib_node_index_t fp_via_fib
the resolving via fib.
Definition: fib_path.c:378
static int fib_path_is_permanent_drop(fib_path_t *path)
Definition: fib_path.c:850
fib_path_list_walk_rc_t fib_path_encode(fib_node_index_t path_list_index, fib_node_index_t path_index, void *ctx)
Definition: fib_path.c:2592
enum vnet_link_t_ vnet_link_t
Link Type: A description of the protocol of packets on the link.
index_t bier_table_ecmp_create_and_lock(const bier_table_id_t *btid)
Definition: bier_table.c:456
ip46_address_t fp_addr
The next-hop.
Definition: fib_path.c:339
static fib_forward_chain_type_t fib_path_to_chain_type(const fib_path_t *path)
Definition: fib_path.c:936
u8 frp_preference
A path preference.
Definition: fib_types.h:563
bier_table_id_t fp_bier_tbl
The BIER table&#39;s ID.
Definition: fib_path.c:303
uword hash_memory(void *p, word n_bytes, uword state)
Definition: hash.c:224
A deag path using the packet&#39;s source not destination address.
Definition: fib_types.h:357
enum fib_forward_chain_type_t_ fib_forward_chain_type_t
FIB output chain type.
fib_route_path_flags_t frp_flags
flags on the path
Definition: fib_types.h:567
u32 fp_interface
The interface.
Definition: fib_path.c:256
static clib_error_t * show_fib_path_command(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: fib_path.c:2668
int dpo_cmp(const dpo_id_t *dpo1, const dpo_id_t *dpo2)
Compare two Data-path objects.
Definition: dpo.c:248
A path that resolves via a BIER F-Mask.
Definition: fib_types.h:365
u8 * format_dpo_id(u8 *s, va_list *args)
Format a DPO_id_t oject
Definition: dpo.c:147
A path that resolves via another table.
Definition: fib_types.h:377
u32 entries
static uword vnet_sw_interface_is_admin_up(vnet_main_t *vnm, u32 sw_if_index)
format_function_t format_mpls_unicast_label
Definition: mpls.h:69
static void fib_path_unresolve(fib_path_t *path)
Definition: fib_path.c:862
mpls_label_t frp_local_label
The MPLS local Label to reursively resolve through.
Definition: fib_types.h:493
dpo_proto_t fib_path_get_proto(fib_node_index_t path_index)
Definition: fib_path.c:2652
fib_path_oper_flags_t fp_oper_flags
Memebers in this last section represent information that is dervied during resolution.
Definition: fib_path.c:371
int fib_path_is_recursive_constrained(fib_node_index_t path_index)
Definition: fib_path.c:2537
void fib_path_list_back_walk(fib_node_index_t path_list_index, fib_node_back_walk_ctx_t *ctx)
Attached-nexthop.
Definition: fib_path.c:57
typedef udp_encap
UDP Encap object.
Definition: udp.api:39
enum fib_path_list_walk_rc_t_ fib_path_list_walk_rc_t
return code to control pat-hlist walk
u32 fib_path_get_resolving_interface(fib_node_index_t path_index)
Definition: fib_path.c:2055
struct fib_path_t_::@133::@143 deag
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
A for-us/local path.
Definition: fib_types.h:332
u32 path_weight
weight for the path.
Definition: load_balance.h:76
u32 adj_child_add(adj_index_t adj_index, fib_node_type_t child_type, fib_node_index_t child_index)
Add a child dependent to an adjacency.
Definition: adj.c:271
u16 fib_path_get_preference(fib_node_index_t path_index)
Definition: fib_path.c:2150
u64 uword
Definition: types.h:112
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:195
#define FIB_PATH_DBG(_p, _fmt, _args...)
Definition: fib_path.c:426
adj_index_t adj_glean_add_or_lock(fib_protocol_t proto, vnet_link_t linkt, u32 sw_if_index, const ip46_address_t *nh_addr)
Glean Adjacency.
Definition: adj_glean.c:50
fib_node_index_t fib_path_create(fib_node_index_t pl_index, const fib_route_path_t *rpath)
Definition: fib_path.c:1249
u8 fp_weight
UCMP [unnormalised] weigth.
Definition: fib_path.c:235
One path from an [EU]CMP set that the client wants to add to a load-balance object.
Definition: load_balance.h:62
enum fib_path_cfg_flags_t_ fib_path_cfg_flags_t
Path config flags from the attributes.
struct fib_path_t_::@133::@142 bier_imp
u8 * format_dpo_proto(u8 *s, va_list *args)
format a DPO protocol
Definition: dpo.c:177
int fib_path_recursive_loop_detect(fib_node_index_t path_index, fib_node_index_t **entry_indicies)
Definition: fib_path.c:1753
A FIB graph nodes virtual function table.
Definition: fib_node.h:276
static fib_path_cfg_flags_t fib_path_route_flags_to_cfg_flags(const fib_route_path_t *rpath)
Definition: fib_path.c:1216
int dpo_is_drop(const dpo_id_t *dpo)
The Drop DPO will drop all packets, no questions asked.
Definition: drop_dpo.c:33
adj_index_t adj_mcast_add_or_lock(fib_protocol_t proto, vnet_link_t link_type, u32 sw_if_index)
Mcast Adjacency.
Definition: adj_mcast.c:51
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:231
mpls_label_t fp_local_label
The local label to resolve through.
Definition: fib_path.c:275
#define vec_foreach(var, vec)
Vector iterator.
fib_route_path_t rpath
Definition: fib_types.h:585
fib_path_type_t_
Enurmeration of path types.
Definition: fib_path.c:49
Contribute an object that is to be used to forward non-end-of-stack MPLS packets. ...
Definition: fib_types.h:118
Attached path.
Definition: fib_types.h:336
void udp_encap_unlock(index_t uei)
Definition: udp_encap.c:165
#define pool_foreach_index(i, v, body)
Iterate pool by index.
Definition: pool.h:488
u8 * fib_node_children_format(fib_node_list_t list, u8 *s)
Definition: fib_node.c:176
u8 fp_preference
A path preference.
Definition: fib_path.c:242
u8 frp_weight
[un]equal cost path weight
Definition: fib_types.h:557
fib_source_t fib_entry_get_best_source(fib_node_index_t entry_index)
Definition: fib_entry.c:1419
u32 frp_udp_encap_id
UDP encap ID.
Definition: fib_types.h:547
#define ip46_address_is_zero(ip46)
Definition: ip6_packet.h:93
Contribute an object that is to be used to forward IP4 packets.
Definition: fib_types.h:133
u32 bier_fmask_child_add(fib_node_index_t bfmi, fib_node_type_t child_type, fib_node_index_t child_index)
Definition: bier_fmask.c:141
void bier_imp_unlock(index_t bii)
Definition: bier_imp.c:110
u32 frp_fib_index
The FIB index to lookup the nexthop Only valid for recursive paths.
Definition: fib_types.h:516
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:725
fib_forward_chain_type_t fib_forw_chain_type_from_dpo_proto(dpo_proto_t proto)
Convert from a payload-protocol to a chain type.
Definition: fib_types.c:321
void fib_path_destroy(fib_node_index_t path_index)
Definition: fib_path.c:1467
#define FOR_EACH_FIB_PATH_CFG_ATTRIBUTE(_item)
Definition: fib_path.h:109
static int fib_path_cmp_i(const fib_path_t *path1, const fib_path_t *path2)
Definition: fib_path.c:1506
const ip46_address_t zero_addr
Definition: lookup.c:318
int fib_path_cmp_w_route_path(fib_node_index_t path_index, const fib_route_path_t *rpath)
Definition: fib_path.c:1640
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
void udp_encap_contribute_forwarding(index_t uei, dpo_proto_t proto, dpo_id_t *dpo)
Definition: udp_encap.c:134
static fib_node_t * fib_path_get_node(fib_node_index_t index)
Definition: fib_path.c:442
enum mpls_eos_bit_t_ mpls_eos_bit_t
index_t fp_bier_fib
The BIER FIB the fmask is in.
Definition: fib_path.c:290
fib_entry_flag_t fib_entry_get_flags(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:276
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128