FD.io VPP  v17.04.2-2-ga8f93f8
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>
24 
25 #include <vnet/adj/adj.h>
26 #include <vnet/adj/adj_mcast.h>
27 
28 #include <vnet/fib/fib_path.h>
29 #include <vnet/fib/fib_node.h>
30 #include <vnet/fib/fib_table.h>
31 #include <vnet/fib/fib_entry.h>
32 #include <vnet/fib/fib_path_list.h>
33 #include <vnet/fib/fib_internal.h>
34 #include <vnet/fib/fib_urpf_list.h>
35 
36 /**
37  * Enurmeration of path types
38  */
39 typedef enum fib_path_type_t_ {
40  /**
41  * Marker. Add new types after this one.
42  */
44  /**
45  * Attached-nexthop. An interface and a nexthop are known.
46  */
48  /**
49  * attached. Only the interface is known.
50  */
52  /**
53  * recursive. Only the next-hop is known.
54  */
56  /**
57  * special. nothing is known. so we drop.
58  */
60  /**
61  * exclusive. user provided adj.
62  */
64  /**
65  * deag. Link to a lookup adj in the next table
66  */
68  /**
69  * receive. it's for-us.
70  */
72  /**
73  * Marker. Add new types before this one, then update it.
74  */
76 } __attribute__ ((packed)) fib_path_type_t;
77 
78 /**
79  * The maximum number of path_types
80  */
81 #define FIB_PATH_TYPE_MAX (FIB_PATH_TYPE_LAST + 1)
82 
83 #define FIB_PATH_TYPES { \
84  [FIB_PATH_TYPE_ATTACHED_NEXT_HOP] = "attached-nexthop", \
85  [FIB_PATH_TYPE_ATTACHED] = "attached", \
86  [FIB_PATH_TYPE_RECURSIVE] = "recursive", \
87  [FIB_PATH_TYPE_SPECIAL] = "special", \
88  [FIB_PATH_TYPE_EXCLUSIVE] = "exclusive", \
89  [FIB_PATH_TYPE_DEAG] = "deag", \
90  [FIB_PATH_TYPE_RECEIVE] = "receive", \
91 }
92 
93 #define FOR_EACH_FIB_PATH_TYPE(_item) \
94  for (_item = FIB_PATH_TYPE_FIRST; _item <= FIB_PATH_TYPE_LAST; _item++)
95 
96 /**
97  * Enurmeration of path operational (i.e. derived) attributes
98  */
100  /**
101  * Marker. Add new types after this one.
102  */
104  /**
105  * The path forms part of a recursive loop.
106  */
108  /**
109  * The path is resolved
110  */
112  /**
113  * The path is attached, despite what the next-hop may say.
114  */
116  /**
117  * The path has become a permanent drop.
118  */
120  /**
121  * Marker. Add new types before this one, then update it.
122  */
124 } __attribute__ ((packed)) fib_path_oper_attribute_t;
125 
126 /**
127  * The maximum number of path operational attributes
128  */
129 #define FIB_PATH_OPER_ATTRIBUTE_MAX (FIB_PATH_OPER_ATTRIBUTE_LAST + 1)
130 
131 #define FIB_PATH_OPER_ATTRIBUTES { \
132  [FIB_PATH_OPER_ATTRIBUTE_RECURSIVE_LOOP] = "recursive-loop", \
133  [FIB_PATH_OPER_ATTRIBUTE_RESOLVED] = "resolved", \
134  [FIB_PATH_OPER_ATTRIBUTE_DROP] = "drop", \
135 }
136 
137 #define FOR_EACH_FIB_PATH_OPER_ATTRIBUTE(_item) \
138  for (_item = FIB_PATH_OPER_ATTRIBUTE_FIRST; \
139  _item <= FIB_PATH_OPER_ATTRIBUTE_LAST; \
140  _item++)
141 
142 /**
143  * Path flags from the attributes
144  */
151 } __attribute__ ((packed)) fib_path_oper_flags_t;
152 
153 /**
154  * A FIB path
155  */
156 typedef struct fib_path_t_ {
157  /**
158  * A path is a node in the FIB graph.
159  */
161 
162  /**
163  * The index of the path-list to which this path belongs
164  */
166 
167  /**
168  * This marks the start of the memory area used to hash
169  * the path
170  */
171  STRUCT_MARK(path_hash_start);
172 
173  /**
174  * Configuration Flags
175  */
177 
178  /**
179  * The type of the path. This is the selector for the union
180  */
181  fib_path_type_t fp_type;
182 
183  /**
184  * The protocol of the next-hop, i.e. the address family of the
185  * next-hop's address. We can't derive this from the address itself
186  * since the address can be all zeros
187  */
189 
190  /**
191  * UCMP [unnormalised] weigt
192  */
194 
195  /**
196  * per-type union of the data required to resolve the path
197  */
198  union {
199  struct {
200  /**
201  * The next-hop
202  */
203  ip46_address_t fp_nh;
204  /**
205  * The interface
206  */
208  } attached_next_hop;
209  struct {
210  /**
211  * The interface
212  */
213  u32 fp_interface;
214  } attached;
215  struct {
216  union
217  {
218  /**
219  * The next-hop
220  */
221  ip46_address_t fp_ip;
222  /**
223  * The local label to resolve through.
224  */
226  } fp_nh;
227  /**
228  * The FIB table index in which to find the next-hop.
229  * This needs to be fixed. We should lookup the adjacencies in
230  * a separate table of adjacencies, rather than from the FIB.
231  * Two reasons I can think of:
232  * - consider:
233  * int ip addr Gig0 10.0.0.1/24
234  * ip route 10.0.0.2/32 via Gig1 192.168.1.2
235  * ip route 1.1.1.1/32 via Gig0 10.0.0.2
236  * this is perfectly valid.
237  * Packets addressed to 10.0.0.2 should be sent via Gig1.
238  * Packets address to 1.1.1.1 should be sent via Gig0.
239  * when we perform the adj resolution from the FIB for the path
240  * "via Gig0 10.0.0.2" the lookup will result in the route via Gig1
241  * and so we will pick up the adj via Gig1 - which was not what the
242  * operator wanted.
243  * - we can only return link-type IPv4 and so not the link-type MPLS.
244  * more on this in a later commit.
245  *
246  * The table ID should only belong to a recursive path and indicate
247  * which FIB should be used to resolve the next-hop.
248  */
250  } recursive;
251  struct {
252  /**
253  * The FIB index in which to perfom the next lookup
254  */
255  fib_node_index_t fp_tbl_id;
256  } deag;
257  struct {
258  } special;
259  struct {
260  /**
261  * The user provided 'exclusive' DPO
262  */
264  } exclusive;
265  struct {
266  /**
267  * The interface on which the local address is configured
268  */
269  u32 fp_interface;
270  /**
271  * The next-hop
272  */
273  ip46_address_t fp_addr;
274  } receive;
275  };
276  STRUCT_MARK(path_hash_end);
277 
278  /**
279  * Memebers in this last section represent information that is
280  * dervied during resolution. It should not be copied to new paths
281  * nor compared.
282  */
283 
284  /**
285  * Operational Flags
286  */
287  fib_path_oper_flags_t fp_oper_flags;
288 
289  /**
290  * the resolving via fib. not part of the union, since it it not part
291  * of the path's hash.
292  */
294 
295  /**
296  * The Data-path objects through which this path resolves for IP.
297  */
299 
300  /**
301  * the index of this path in the parent's child list.
302  */
304 } fib_path_t;
305 
306 /*
307  * Array of strings/names for the path types and attributes
308  */
309 static const char *fib_path_type_names[] = FIB_PATH_TYPES;
310 static const char *fib_path_oper_attribute_names[] = FIB_PATH_OPER_ATTRIBUTES;
311 static const char *fib_path_cfg_attribute_names[] = FIB_PATH_CFG_ATTRIBUTES;
312 
313 /*
314  * The memory pool from which we allocate all the paths
315  */
317 
318 /*
319  * Debug macro
320  */
321 #ifdef FIB_DEBUG
322 #define FIB_PATH_DBG(_p, _fmt, _args...) \
323 { \
324  u8 *_tmp = NULL; \
325  _tmp = fib_path_format(fib_path_get_index(_p), _tmp); \
326  clib_warning("path:[%d:%s]:" _fmt, \
327  fib_path_get_index(_p), _tmp, \
328  ##_args); \
329  vec_free(_tmp); \
330 }
331 #else
332 #define FIB_PATH_DBG(_p, _fmt, _args...)
333 #endif
334 
335 static fib_path_t *
337 {
338  return (pool_elt_at_index(fib_path_pool, index));
339 }
340 
341 static fib_node_index_t
343 {
344  return (path - fib_path_pool);
345 }
346 
347 static fib_node_t *
349 {
350  return ((fib_node_t*)fib_path_get(index));
351 }
352 
353 static fib_path_t*
355 {
356 #if CLIB_DEBUG > 0
358 #endif
359  return ((fib_path_t*)node);
360 }
361 
362 u8 *
363 format_fib_path (u8 * s, va_list * args)
364 {
365  fib_path_t *path = va_arg (*args, fib_path_t *);
366  vnet_main_t * vnm = vnet_get_main();
367  fib_path_oper_attribute_t oattr;
369 
370  s = format (s, " index:%d ", fib_path_get_index(path));
371  s = format (s, "pl-index:%d ", path->fp_pl_index);
372  s = format (s, "%U ", format_fib_protocol, path->fp_nh_proto);
373  s = format (s, "weight=%d ", path->fp_weight);
374  s = format (s, "%s: ", fib_path_type_names[path->fp_type]);
375  if (FIB_PATH_OPER_FLAG_NONE != path->fp_oper_flags) {
376  s = format(s, " oper-flags:");
378  if ((1<<oattr) & path->fp_oper_flags) {
379  s = format (s, "%s,", fib_path_oper_attribute_names[oattr]);
380  }
381  }
382  }
383  if (FIB_PATH_CFG_FLAG_NONE != path->fp_cfg_flags) {
384  s = format(s, " cfg-flags:");
386  if ((1<<cattr) & path->fp_cfg_flags) {
387  s = format (s, "%s,", fib_path_cfg_attribute_names[cattr]);
388  }
389  }
390  }
391  s = format(s, "\n ");
392 
393  switch (path->fp_type)
394  {
396  s = format (s, "%U", format_ip46_address,
397  &path->attached_next_hop.fp_nh,
398  IP46_TYPE_ANY);
400  {
401  s = format (s, " if_index:%d", path->attached_next_hop.fp_interface);
402  }
403  else
404  {
405  s = format (s, " %U",
407  vnm,
409  vnm,
410  path->attached_next_hop.fp_interface));
412  path->attached_next_hop.fp_interface))
413  {
414  s = format (s, " (p2p)");
415  }
416  }
417  if (!dpo_id_is_valid(&path->fp_dpo))
418  {
419  s = format(s, "\n unresolved");
420  }
421  else
422  {
423  s = format(s, "\n %U",
425  &path->fp_dpo, 13);
426  }
427  break;
430  {
431  s = format (s, " if_index:%d", path->attached_next_hop.fp_interface);
432  }
433  else
434  {
435  s = format (s, " %U",
437  vnm,
439  vnm,
440  path->attached.fp_interface));
441  }
442  break;
444  if (FIB_PROTOCOL_MPLS == path->fp_nh_proto)
445  {
446  s = format (s, "via %U",
448  path->recursive.fp_nh.fp_local_label);
449  }
450  else
451  {
452  s = format (s, "via %U",
454  &path->recursive.fp_nh.fp_ip,
455  IP46_TYPE_ANY);
456  }
457  s = format (s, " in fib:%d",
458  path->recursive.fp_tbl_id,
459  path->fp_via_fib);
460  s = format (s, " via-fib:%d", path->fp_via_fib);
461  s = format (s, " via-dpo:[%U:%d]",
463  path->fp_dpo.dpoi_index);
464 
465  break;
468  case FIB_PATH_TYPE_DEAG:
470  if (dpo_id_is_valid(&path->fp_dpo))
471  {
472  s = format(s, "%U", format_dpo_id,
473  &path->fp_dpo, 2);
474  }
475  break;
476  }
477  return (s);
478 }
479 
480 u8 *
482 {
483  fib_path_t *path;
484 
485  path = fib_path_get(pi);
486  ASSERT(NULL != path);
487 
488  return (format (s, "%U", format_fib_path, path));
489 }
490 
491 u8 *
493  u32 indent,
494  u8 *s)
495 {
496  fib_path_t *path;
497 
498  path = fib_path_get(pi);
499  ASSERT(NULL != path);
500 
501  if (!dpo_id_is_valid(&path->fp_dpo))
502  {
503  s = format(s, " unresolved");
504  }
505  else
506  {
507  s = format(s, "%U", format_dpo_id,
508  &path->fp_dpo, 2);
509  }
510 
511  return (s);
512 }
513 
514 /*
515  * fib_path_last_lock_gone
516  *
517  * We don't share paths, we share path lists, so the [un]lock functions
518  * are no-ops
519  */
520 static void
522 {
523  ASSERT(0);
524 }
525 
526 static const adj_index_t
528  vnet_link_t link)
529 {
531  path->attached_next_hop.fp_interface))
532  {
533  /*
534  * if the interface is p2p then the adj for the specific
535  * neighbour on that link will never exist. on p2p links
536  * the subnet address (the attached route) links to the
537  * auto-adj (see below), we want that adj here too.
538  */
539  return (adj_nbr_add_or_lock(path->fp_nh_proto,
540  link,
541  &zero_addr,
542  path->attached_next_hop.fp_interface));
543  }
544  else
545  {
546  return (adj_nbr_add_or_lock(path->fp_nh_proto,
547  link,
548  &path->attached_next_hop.fp_nh,
549  path->attached_next_hop.fp_interface));
550  }
551 }
552 
553 static void
555 {
556  /*
557  * resolve directly via the adjacnecy discribed by the
558  * interface and next-hop
559  */
561  path->attached_next_hop.fp_interface))
562  {
564  }
565 
566  dpo_set(&path->fp_dpo,
570  path,
572 
573  /*
574  * become a child of the adjacency so we receive updates
575  * when its rewrite changes
576  */
579  fib_path_get_index(path));
580 }
581 
582 /*
583  * create of update the paths recursive adj
584  */
585 static void
588  dpo_id_t *dpo)
589 {
590  dpo_id_t via_dpo = DPO_INVALID;
591 
592  /*
593  * get the DPO to resolve through from the via-entry
594  */
596  fct,
597  &via_dpo);
598 
599 
600  /*
601  * hope for the best - clear if restrictions apply.
602  */
604 
605  /*
606  * Validate any recursion constraints and over-ride the via
607  * adj if not met
608  */
610  {
613  }
615  {
616  /*
617  * the via FIB must be a host route.
618  * note the via FIB just added will always be a host route
619  * since it is an RR source added host route. So what we need to
620  * check is whether the route has other sources. If it does then
621  * some other source has added it as a host route. If it doesn't
622  * then it was added only here and inherits forwarding from a cover.
623  * the cover is not a host route.
624  * The RR source is the lowest priority source, so we check if it
625  * is the best. if it is there are no other sources.
626  */
628  {
631 
632  /*
633  * PIC edge trigger. let the load-balance maps know
634  */
636  }
637  }
639  {
640  /*
641  * RR source entries inherit the flags from the cover, so
642  * we can check the via directly
643  */
645  {
648 
649  /*
650  * PIC edge trigger. let the load-balance maps know
651  */
653  }
654  }
655 
656  /*
657  * update the path's contributed DPO
658  */
659  dpo_copy(dpo, &via_dpo);
660 
661  FIB_PATH_DBG(path, "recursive update: %U",
662  fib_get_lookup_main(path->fp_nh_proto),
663  &path->fp_dpo, 2);
664 
665  dpo_reset(&via_dpo);
666 }
667 
668 /*
669  * fib_path_is_permanent_drop
670  *
671  * Return !0 if the path is configured to permanently drop,
672  * despite other attributes.
673  */
674 static int
676 {
677  return ((path->fp_cfg_flags & FIB_PATH_CFG_FLAG_DROP) ||
679 }
680 
681 /*
682  * fib_path_unresolve
683  *
684  * Remove our dependency on the resolution target
685  */
686 static void
688 {
689  /*
690  * the forced drop path does not need unresolving
691  */
692  if (fib_path_is_permanent_drop(path))
693  {
694  return;
695  }
696 
697  switch (path->fp_type)
698  {
700  if (FIB_NODE_INDEX_INVALID != path->fp_via_fib)
701  {
702  fib_prefix_t pfx;
703 
704  fib_entry_get_prefix(path->fp_via_fib, &pfx);
706  path->fp_sibling);
708  &pfx,
709  FIB_SOURCE_RR);
711  }
712  break;
716  path->fp_sibling);
718  break;
720  dpo_reset(&path->exclusive.fp_ex_dpo);
721  break;
724  case FIB_PATH_TYPE_DEAG:
725  /*
726  * these hold only the path's DPO, which is reset below.
727  */
728  break;
729  }
730 
731  /*
732  * release the adj we were holding and pick up the
733  * drop just in case.
734  */
735  dpo_reset(&path->fp_dpo);
737 
738  return;
739 }
740 
743 {
744  switch (proto)
745  {
746  case FIB_PROTOCOL_IP4:
748  case FIB_PROTOCOL_IP6:
750  case FIB_PROTOCOL_MPLS:
752  }
754 }
755 
756 /*
757  * fib_path_back_walk_notify
758  *
759  * A back walk has reach this path.
760  */
764 {
765  fib_path_t *path;
766 
767  path = fib_path_from_fib_node(node);
768 
769  switch (path->fp_type)
770  {
773  {
774  /*
775  * modify the recursive adjacency to use the new forwarding
776  * of the via-fib.
777  * this update is visible to packets in flight in the DP.
778  */
780  path,
782  &path->fp_dpo);
783  }
786  {
787  /*
788  * ADJ updates (complete<->incomplete) do not need to propagate to
789  * recursive entries.
790  * The only reason its needed as far back as here, is that the adj
791  * and the incomplete adj are a different DPO type, so the LBs need
792  * to re-stack.
793  * If this walk was quashed in the fib_entry, then any non-fib_path
794  * children (like tunnels that collapse out the LB when they stack)
795  * would not see the update.
796  */
798  }
799  break;
801  /*
802 FIXME comment
803  * ADJ_UPDATE backwalk pass silently through here and up to
804  * the path-list when the multipath adj collapse occurs.
805  * The reason we do this is that the assumtption is that VPP
806  * runs in an environment where the Control-Plane is remote
807  * and hence reacts slowly to link up down. In order to remove
808  * this down link from the ECMP set quickly, we back-walk.
809  * VPP also has dedicated CPUs, so we are not stealing resources
810  * from the CP to do so.
811  */
813  {
815  {
816  /*
817  * alreday resolved. no need to walk back again
818  */
820  }
822  }
824  {
826  {
827  /*
828  * alreday unresolved. no need to walk back again
829  */
831  }
833  }
835  {
836  /*
837  * The interface this path resolves through has been deleted.
838  * This will leave the path in a permanent drop state. The route
839  * needs to be removed and readded (and hence the path-list deleted)
840  * before it can forward again.
841  */
842  fib_path_unresolve(path);
844  }
846  {
847  /*
848  * restack the DPO to pick up the correct DPO sub-type
849  */
850  uword if_is_up;
851  adj_index_t ai;
852 
854  vnet_get_main(),
855  path->attached_next_hop.fp_interface);
856 
857  if (if_is_up)
858  {
860  }
861 
863  path,
865 
866  dpo_set(&path->fp_dpo, DPO_ADJACENCY,
868  ai);
869  adj_unlock(ai);
870 
871  if (!if_is_up)
872  {
873  /*
874  * If the interface is not up there is no reason to walk
875  * back to children. if we did they would only evalute
876  * that this path is unresolved and hence it would
877  * not contribute the adjacency - so it would be wasted
878  * CPU time.
879  */
881  }
882  }
884  {
886  {
887  /*
888  * alreday unresolved. no need to walk back again
889  */
891  }
892  /*
893  * the adj has gone down. the path is no longer resolved.
894  */
896  }
897  break;
899  /*
900  * FIXME; this could schedule a lower priority walk, since attached
901  * routes are not usually in ECMP configurations so the backwalk to
902  * the FIB entry does not need to be high priority
903  */
905  {
907  }
909  {
911  }
913  {
914  fib_path_unresolve(path);
916  }
917  break;
918  case FIB_PATH_TYPE_DEAG:
919  /*
920  * FIXME When VRF delete is allowed this will need a poke.
921  */
925  /*
926  * these path types have no parents. so to be
927  * walked from one is unexpected.
928  */
929  ASSERT(0);
930  break;
931  }
932 
933  /*
934  * propagate the backwalk further to the path-list
935  */
937 
939 }
940 
941 static void
943 {
944  fib_show_memory_usage("Path",
945  pool_elts(fib_path_pool),
946  pool_len(fib_path_pool),
947  sizeof(fib_path_t));
948 }
949 
950 /*
951  * The FIB path's graph node virtual function table
952  */
953 static const fib_node_vft_t fib_path_vft = {
955  .fnv_last_lock = fib_path_last_lock_gone,
956  .fnv_back_walk = fib_path_back_walk_notify,
957  .fnv_mem_show = fib_path_memory_show,
958 };
959 
962 {
964 
966  cfg_flags |= FIB_PATH_CFG_FLAG_RESOLVE_HOST;
969  if (rpath->frp_flags & FIB_ROUTE_PATH_LOCAL)
970  cfg_flags |= FIB_PATH_CFG_FLAG_LOCAL;
971  if (rpath->frp_flags & FIB_ROUTE_PATH_ATTACHED)
972  cfg_flags |= FIB_PATH_CFG_FLAG_ATTACHED;
973 
974  return (cfg_flags);
975 }
976 
977 /*
978  * fib_path_create
979  *
980  * Create and initialise a new path object.
981  * return the index of the path.
982  */
985  fib_protocol_t nh_proto,
987  const fib_route_path_t *rpath)
988 {
989  fib_path_t *path;
990 
991  pool_get(fib_path_pool, path);
992  memset(path, 0, sizeof(*path));
993 
994  fib_node_init(&path->fp_node,
996 
997  dpo_reset(&path->fp_dpo);
998  path->fp_pl_index = pl_index;
999  path->fp_nh_proto = nh_proto;
1001  path->fp_weight = rpath->frp_weight;
1002  if (0 == path->fp_weight)
1003  {
1004  /*
1005  * a weight of 0 is a meaningless value. We could either reject it, and thus force
1006  * clients to always use 1, or we can accept it and fixup approrpiately.
1007  */
1008  path->fp_weight = 1;
1009  }
1010  path->fp_cfg_flags = flags;
1012 
1013  /*
1014  * deduce the path's tpye from the parementers and save what is needed.
1015  */
1017  {
1019  path->receive.fp_interface = rpath->frp_sw_if_index;
1020  path->receive.fp_addr = rpath->frp_addr;
1021  }
1022  else if (~0 != rpath->frp_sw_if_index)
1023  {
1024  if (ip46_address_is_zero(&rpath->frp_addr))
1025  {
1027  path->attached.fp_interface = rpath->frp_sw_if_index;
1028  }
1029  else
1030  {
1032  path->attached_next_hop.fp_interface = rpath->frp_sw_if_index;
1033  path->attached_next_hop.fp_nh = rpath->frp_addr;
1034  }
1035  }
1036  else
1037  {
1038  if (ip46_address_is_zero(&rpath->frp_addr))
1039  {
1040  if (~0 == rpath->frp_fib_index)
1041  {
1043  }
1044  else
1045  {
1046  path->fp_type = FIB_PATH_TYPE_DEAG;
1047  path->deag.fp_tbl_id = rpath->frp_fib_index;
1048  }
1049  }
1050  else
1051  {
1053  if (FIB_PROTOCOL_MPLS == path->fp_nh_proto)
1054  {
1055  path->recursive.fp_nh.fp_local_label = rpath->frp_local_label;
1056  }
1057  else
1058  {
1059  path->recursive.fp_nh.fp_ip = rpath->frp_addr;
1060  }
1061  path->recursive.fp_tbl_id = rpath->frp_fib_index;
1062  }
1063  }
1064 
1065  FIB_PATH_DBG(path, "create");
1066 
1067  return (fib_path_get_index(path));
1068 }
1069 
1070 /*
1071  * fib_path_create_special
1072  *
1073  * Create and initialise a new path object.
1074  * return the index of the path.
1075  */
1078  fib_protocol_t nh_proto,
1080  const dpo_id_t *dpo)
1081 {
1082  fib_path_t *path;
1083 
1084  pool_get(fib_path_pool, path);
1085  memset(path, 0, sizeof(*path));
1086 
1087  fib_node_init(&path->fp_node,
1089  dpo_reset(&path->fp_dpo);
1090 
1091  path->fp_pl_index = pl_index;
1092  path->fp_weight = 1;
1093  path->fp_nh_proto = nh_proto;
1095  path->fp_cfg_flags = flags;
1096 
1097  if (FIB_PATH_CFG_FLAG_DROP & flags)
1098  {
1100  }
1101  else if (FIB_PATH_CFG_FLAG_LOCAL & flags)
1102  {
1104  path->attached.fp_interface = FIB_NODE_INDEX_INVALID;
1105  }
1106  else
1107  {
1109  ASSERT(NULL != dpo);
1110  dpo_copy(&path->exclusive.fp_ex_dpo, dpo);
1111  }
1112 
1113  return (fib_path_get_index(path));
1114 }
1115 
1116 /*
1117  * fib_path_copy
1118  *
1119  * Copy a path. return index of new path.
1120  */
1123  fib_node_index_t path_list_index)
1124 {
1125  fib_path_t *path, *orig_path;
1126 
1127  pool_get(fib_path_pool, path);
1128 
1129  orig_path = fib_path_get(path_index);
1130  ASSERT(NULL != orig_path);
1131 
1132  memcpy(path, orig_path, sizeof(*path));
1133 
1134  FIB_PATH_DBG(path, "create-copy:%d", path_index);
1135 
1136  /*
1137  * reset the dynamic section
1138  */
1141  path->fp_pl_index = path_list_index;
1143  memset(&path->fp_dpo, 0, sizeof(path->fp_dpo));
1144  dpo_reset(&path->fp_dpo);
1145 
1146  return (fib_path_get_index(path));
1147 }
1148 
1149 /*
1150  * fib_path_destroy
1151  *
1152  * destroy a path that is no longer required
1153  */
1154 void
1156 {
1157  fib_path_t *path;
1158 
1159  path = fib_path_get(path_index);
1160 
1161  ASSERT(NULL != path);
1162  FIB_PATH_DBG(path, "destroy");
1163 
1164  fib_path_unresolve(path);
1165 
1166  fib_node_deinit(&path->fp_node);
1167  pool_put(fib_path_pool, path);
1168 }
1169 
1170 /*
1171  * fib_path_destroy
1172  *
1173  * destroy a path that is no longer required
1174  */
1175 uword
1177 {
1178  fib_path_t *path;
1179 
1180  path = fib_path_get(path_index);
1181 
1182  return (hash_memory(STRUCT_MARK_PTR(path, path_hash_start),
1183  (STRUCT_OFFSET_OF(fib_path_t, path_hash_end) -
1184  STRUCT_OFFSET_OF(fib_path_t, path_hash_start)),
1185  0));
1186 }
1187 
1188 /*
1189  * fib_path_cmp_i
1190  *
1191  * Compare two paths for equivalence.
1192  */
1193 static int
1195  const fib_path_t *path2)
1196 {
1197  int res;
1198 
1199  res = 1;
1200 
1201  /*
1202  * paths of different types and protocol are not equal.
1203  * different weights only are the same path.
1204  */
1205  if (path1->fp_type != path2->fp_type)
1206  {
1207  res = (path1->fp_type - path2->fp_type);
1208  }
1209  else if (path1->fp_nh_proto != path2->fp_nh_proto)
1210  {
1211  res = (path1->fp_nh_proto - path2->fp_nh_proto);
1212  }
1213  else
1214  {
1215  /*
1216  * both paths are of the same type.
1217  * consider each type and its attributes in turn.
1218  */
1219  switch (path1->fp_type)
1220  {
1222  res = ip46_address_cmp(&path1->attached_next_hop.fp_nh,
1223  &path2->attached_next_hop.fp_nh);
1224  if (0 == res) {
1226  vnet_get_main(),
1227  path1->attached_next_hop.fp_interface,
1228  path2->attached_next_hop.fp_interface);
1229  }
1230  break;
1233  vnet_get_main(),
1234  path1->attached.fp_interface,
1235  path2->attached.fp_interface);
1236  break;
1238  res = ip46_address_cmp(&path1->recursive.fp_nh,
1239  &path2->recursive.fp_nh);
1240 
1241  if (0 == res)
1242  {
1243  res = (path1->recursive.fp_tbl_id - path2->recursive.fp_tbl_id);
1244  }
1245  break;
1246  case FIB_PATH_TYPE_DEAG:
1247  res = (path1->deag.fp_tbl_id - path2->deag.fp_tbl_id);
1248  break;
1249  case FIB_PATH_TYPE_SPECIAL:
1250  case FIB_PATH_TYPE_RECEIVE:
1252  res = 0;
1253  break;
1254  }
1255  }
1256  return (res);
1257 }
1258 
1259 /*
1260  * fib_path_cmp_for_sort
1261  *
1262  * Compare two paths for equivalence. Used during path sorting.
1263  * As usual 0 means equal.
1264  */
1265 int
1267  void * v2)
1268 {
1269  fib_node_index_t *pi1 = v1, *pi2 = v2;
1270  fib_path_t *path1, *path2;
1271 
1272  path1 = fib_path_get(*pi1);
1273  path2 = fib_path_get(*pi2);
1274 
1275  return (fib_path_cmp_i(path1, path2));
1276 }
1277 
1278 /*
1279  * fib_path_cmp
1280  *
1281  * Compare two paths for equivalence.
1282  */
1283 int
1285  fib_node_index_t pi2)
1286 {
1287  fib_path_t *path1, *path2;
1288 
1289  path1 = fib_path_get(pi1);
1290  path2 = fib_path_get(pi2);
1291 
1292  return (fib_path_cmp_i(path1, path2));
1293 }
1294 
1295 int
1297  const fib_route_path_t *rpath)
1298 {
1299  fib_path_t *path;
1300  int res;
1301 
1302  path = fib_path_get(path_index);
1303 
1304  res = 1;
1305 
1306  if (path->fp_weight != rpath->frp_weight)
1307  {
1308  res = (path->fp_weight - rpath->frp_weight);
1309  }
1310  else
1311  {
1312  /*
1313  * both paths are of the same type.
1314  * consider each type and its attributes in turn.
1315  */
1316  switch (path->fp_type)
1317  {
1319  res = ip46_address_cmp(&path->attached_next_hop.fp_nh,
1320  &rpath->frp_addr);
1321  if (0 == res)
1322  {
1324  vnet_get_main(),
1325  path->attached_next_hop.fp_interface,
1326  rpath->frp_sw_if_index);
1327  }
1328  break;
1331  vnet_get_main(),
1332  path->attached.fp_interface,
1333  rpath->frp_sw_if_index);
1334  break;
1336  if (FIB_PROTOCOL_MPLS == path->fp_nh_proto)
1337  {
1338  res = path->recursive.fp_nh.fp_local_label - rpath->frp_local_label;
1339  }
1340  else
1341  {
1342  res = ip46_address_cmp(&path->recursive.fp_nh.fp_ip,
1343  &rpath->frp_addr);
1344  }
1345 
1346  if (0 == res)
1347  {
1348  res = (path->recursive.fp_tbl_id - rpath->frp_fib_index);
1349  }
1350  break;
1351  case FIB_PATH_TYPE_DEAG:
1352  res = (path->deag.fp_tbl_id - rpath->frp_fib_index);
1353  break;
1354  case FIB_PATH_TYPE_SPECIAL:
1355  case FIB_PATH_TYPE_RECEIVE:
1357  res = 0;
1358  break;
1359  }
1360  }
1361  return (res);
1362 }
1363 
1364 /*
1365  * fib_path_recursive_loop_detect
1366  *
1367  * A forward walk of the FIB object graph to detect for a cycle/loop. This
1368  * walk is initiated when an entry is linking to a new path list or from an old.
1369  * The entry vector passed contains all the FIB entrys that are children of this
1370  * path (it is all the entries encountered on the walk so far). If this vector
1371  * contains the entry this path resolve via, then a loop is about to form.
1372  * The loop must be allowed to form, since we need the dependencies in place
1373  * so that we can track when the loop breaks.
1374  * However, we MUST not produce a loop in the forwarding graph (else packets
1375  * would loop around the switch path until the loop breaks), so we mark recursive
1376  * paths as looped so that they do not contribute forwarding information.
1377  * By marking the path as looped, an etry such as;
1378  * X/Y
1379  * via a.a.a.a (looped)
1380  * via b.b.b.b (not looped)
1381  * can still forward using the info provided by b.b.b.b only
1382  */
1383 int
1385  fib_node_index_t **entry_indicies)
1386 {
1387  fib_path_t *path;
1388 
1389  path = fib_path_get(path_index);
1390 
1391  /*
1392  * the forced drop path is never looped, cos it is never resolved.
1393  */
1394  if (fib_path_is_permanent_drop(path))
1395  {
1396  return (0);
1397  }
1398 
1399  switch (path->fp_type)
1400  {
1402  {
1403  fib_node_index_t *entry_index, *entries;
1404  int looped = 0;
1405  entries = *entry_indicies;
1406 
1407  vec_foreach(entry_index, entries) {
1408  if (*entry_index == path->fp_via_fib)
1409  {
1410  /*
1411  * the entry that is about to link to this path-list (or
1412  * one of this path-list's children) is the same entry that
1413  * this recursive path resolves through. this is a cycle.
1414  * abort the walk.
1415  */
1416  looped = 1;
1417  break;
1418  }
1419  }
1420 
1421  if (looped)
1422  {
1423  FIB_PATH_DBG(path, "recursive loop formed");
1425 
1426  dpo_copy(&path->fp_dpo,
1428  }
1429  else
1430  {
1431  /*
1432  * no loop here yet. keep forward walking the graph.
1433  */
1434  if (fib_entry_recursive_loop_detect(path->fp_via_fib, entry_indicies))
1435  {
1436  FIB_PATH_DBG(path, "recursive loop formed");
1438  }
1439  else
1440  {
1441  FIB_PATH_DBG(path, "recursive loop cleared");
1443  }
1444  }
1445  break;
1446  }
1449  case FIB_PATH_TYPE_SPECIAL:
1450  case FIB_PATH_TYPE_DEAG:
1451  case FIB_PATH_TYPE_RECEIVE:
1453  /*
1454  * these path types cannot be part of a loop, since they are the leaves
1455  * of the graph.
1456  */
1457  break;
1458  }
1459 
1460  return (fib_path_is_looped(path_index));
1461 }
1462 
1463 int
1465 {
1466  fib_path_t *path;
1467 
1468  path = fib_path_get(path_index);
1469 
1470  /*
1471  * hope for the best.
1472  */
1474 
1475  /*
1476  * the forced drop path resolves via the drop adj
1477  */
1478  if (fib_path_is_permanent_drop(path))
1479  {
1480  dpo_copy(&path->fp_dpo,
1483  return (fib_path_is_resolved(path_index));
1484  }
1485 
1486  switch (path->fp_type)
1487  {
1490  break;
1492  /*
1493  * path->attached.fp_interface
1494  */
1496  path->attached.fp_interface))
1497  {
1499  }
1501  path->attached.fp_interface))
1502  {
1503  /*
1504  * point-2-point interfaces do not require a glean, since
1505  * there is nothing to ARP. Install a rewrite/nbr adj instead
1506  */
1507  dpo_set(&path->fp_dpo,
1508  DPO_ADJACENCY,
1511  path->fp_nh_proto,
1513  &zero_addr,
1514  path->attached.fp_interface));
1515  }
1516  else
1517  {
1518  dpo_set(&path->fp_dpo,
1522  path->attached.fp_interface,
1523  NULL));
1524  }
1525  /*
1526  * become a child of the adjacency so we receive updates
1527  * when the interface state changes
1528  */
1529  path->fp_sibling = adj_child_add(path->fp_dpo.dpoi_index,
1531  fib_path_get_index(path));
1532 
1533  break;
1535  {
1536  /*
1537  * Create a RR source entry in the table for the address
1538  * that this path recurses through.
1539  * This resolve action is recursive, hence we may create
1540  * more paths in the process. more creates mean maybe realloc
1541  * of this path.
1542  */
1543  fib_node_index_t fei;
1544  fib_prefix_t pfx;
1545 
1547 
1548  if (FIB_PROTOCOL_MPLS == path->fp_nh_proto)
1549  {
1550  fib_prefix_from_mpls_label(path->recursive.fp_nh.fp_local_label, &pfx);
1551  }
1552  else
1553  {
1554  fib_prefix_from_ip46_addr(&path->recursive.fp_nh.fp_ip, &pfx);
1555  }
1556 
1557  fei = fib_table_entry_special_add(path->recursive.fp_tbl_id,
1558  &pfx,
1559  FIB_SOURCE_RR,
1561 
1562  path = fib_path_get(path_index);
1563  path->fp_via_fib = fei;
1564 
1565  /*
1566  * become a dependent child of the entry so the path is
1567  * informed when the forwarding for the entry changes.
1568  */
1571  fib_path_get_index(path));
1572 
1573  /*
1574  * create and configure the IP DPO
1575  */
1577  path,
1579  &path->fp_dpo);
1580 
1581  break;
1582  }
1583  case FIB_PATH_TYPE_SPECIAL:
1584  /*
1585  * Resolve via the drop
1586  */
1587  dpo_copy(&path->fp_dpo,
1589  break;
1590  case FIB_PATH_TYPE_DEAG:
1591  /*
1592  * Resolve via a lookup DPO.
1593  * FIXME. control plane should add routes with a table ID
1594  */
1595  lookup_dpo_add_or_lock_w_fib_index(path->deag.fp_tbl_id,
1599  &path->fp_dpo);
1600  break;
1601  case FIB_PATH_TYPE_RECEIVE:
1602  /*
1603  * Resolve via a receive DPO.
1604  */
1606  path->receive.fp_interface,
1607  &path->receive.fp_addr,
1608  &path->fp_dpo);
1609  break;
1611  /*
1612  * Resolve via the user provided DPO
1613  */
1614  dpo_copy(&path->fp_dpo, &path->exclusive.fp_ex_dpo);
1615  break;
1616  }
1617 
1618  return (fib_path_is_resolved(path_index));
1619 }
1620 
1621 u32
1623 {
1624  fib_path_t *path;
1625 
1626  path = fib_path_get(path_index);
1627 
1628  switch (path->fp_type)
1629  {
1631  return (path->attached_next_hop.fp_interface);
1633  return (path->attached.fp_interface);
1634  case FIB_PATH_TYPE_RECEIVE:
1635  return (path->receive.fp_interface);
1637  if (fib_path_is_resolved(path_index))
1638  {
1640  }
1641  break;
1642  case FIB_PATH_TYPE_SPECIAL:
1643  case FIB_PATH_TYPE_DEAG:
1645  break;
1646  }
1647  return (~0);
1648 }
1649 
1652 {
1653  fib_path_t *path;
1654 
1655  path = fib_path_get(path_index);
1656 
1657  ASSERT(dpo_is_adj(&path->fp_dpo));
1658  if (dpo_is_adj(&path->fp_dpo))
1659  {
1660  return (path->fp_dpo.dpoi_index);
1661  }
1662  return (ADJ_INDEX_INVALID);
1663 }
1664 
1665 int
1667 {
1668  fib_path_t *path;
1669 
1670  path = fib_path_get(path_index);
1671 
1672  ASSERT(path);
1673 
1674  return (path->fp_weight);
1675 }
1676 
1677 /**
1678  * @brief Contribute the path's adjacency to the list passed.
1679  * By calling this function over all paths, recursively, a child
1680  * can construct its full set of forwarding adjacencies, and hence its
1681  * uRPF list.
1682  */
1683 void
1685  index_t urpf)
1686 {
1687  fib_path_t *path;
1688 
1689  if (!fib_path_is_resolved(path_index))
1690  return;
1691 
1692  path = fib_path_get(path_index);
1693 
1694  switch (path->fp_type)
1695  {
1697  fib_urpf_list_append(urpf, path->attached_next_hop.fp_interface);
1698  break;
1699 
1701  fib_urpf_list_append(urpf, path->attached.fp_interface);
1702  break;
1703 
1705  if (FIB_NODE_INDEX_INVALID != path->fp_via_fib &&
1706  !fib_path_is_looped(path_index))
1707  {
1708  /*
1709  * there's unresolved due to constraints, and there's unresolved
1710  * due to ain't got no via. can't do nowt w'out via.
1711  */
1713  }
1714  break;
1715 
1717  case FIB_PATH_TYPE_SPECIAL:
1718  /*
1719  * these path types may link to an adj, if that's what
1720  * the clinet gave
1721  */
1722  if (dpo_is_adj(&path->fp_dpo))
1723  {
1724  ip_adjacency_t *adj;
1725 
1726  adj = adj_get(path->fp_dpo.dpoi_index);
1727 
1728  fib_urpf_list_append(urpf, adj->rewrite_header.sw_if_index);
1729  }
1730  break;
1731 
1732  case FIB_PATH_TYPE_DEAG:
1733  case FIB_PATH_TYPE_RECEIVE:
1734  /*
1735  * these path types don't link to an adj
1736  */
1737  break;
1738  }
1739 }
1740 
1741 void
1744  dpo_id_t *dpo)
1745 {
1746  fib_path_t *path;
1747 
1748  path = fib_path_get(path_index);
1749 
1750  ASSERT(path);
1752 
1753  FIB_PATH_DBG(path, "contribute");
1754 
1755  /*
1756  * The DPO stored in the path was created when the path was resolved.
1757  * This then represents the path's 'native' protocol; IP.
1758  * For all others will need to go find something else.
1759  */
1760  if (fib_path_proto_to_chain_type(path->fp_nh_proto) == fct)
1761  {
1762  dpo_copy(dpo, &path->fp_dpo);
1763  }
1764  else
1765  {
1766  switch (path->fp_type)
1767  {
1769  switch (fct)
1770  {
1777  {
1778  adj_index_t ai;
1779 
1780  /*
1781  * get a appropriate link type adj.
1782  */
1784  path,
1786  dpo_set(dpo, DPO_ADJACENCY,
1788  adj_unlock(ai);
1789 
1790  break;
1791  }
1794  break;
1795  }
1796  break;
1798  switch (fct)
1799  {
1804  fib_path_recursive_adj_update(path, fct, dpo);
1805  break;
1810  ASSERT(0);
1811  break;
1812  }
1813  break;
1814  case FIB_PATH_TYPE_DEAG:
1815  switch (fct)
1816  {
1822  dpo);
1823  break;
1827  dpo_copy(dpo, &path->fp_dpo);
1828  break;
1833  ASSERT(0);
1834  break;
1835  }
1836  break;
1838  dpo_copy(dpo, &path->exclusive.fp_ex_dpo);
1839  break;
1841  switch (fct)
1842  {
1849  break;
1852  {
1853  adj_index_t ai;
1854 
1855  /*
1856  * Create the adj needed for sending IP multicast traffic
1857  */
1860  path->attached.fp_interface);
1863  ai);
1864  adj_unlock(ai);
1865  }
1866  break;
1867  }
1868  break;
1869  case FIB_PATH_TYPE_RECEIVE:
1870  case FIB_PATH_TYPE_SPECIAL:
1871  dpo_copy(dpo, &path->fp_dpo);
1872  break;
1873  }
1874  }
1875 }
1876 
1880  load_balance_path_t *hash_key)
1881 {
1882  load_balance_path_t *mnh;
1883  fib_path_t *path;
1884 
1885  path = fib_path_get(path_index);
1886 
1887  ASSERT(path);
1888 
1889  if (fib_path_is_resolved(path_index))
1890  {
1891  vec_add2(hash_key, mnh, 1);
1892 
1893  mnh->path_weight = path->fp_weight;
1894  mnh->path_index = path_index;
1895  fib_path_contribute_forwarding(path_index, fct, &mnh->path_dpo);
1896  }
1897 
1898  return (hash_key);
1899 }
1900 
1901 int
1903 {
1904  fib_path_t *path;
1905 
1906  path = fib_path_get(path_index);
1907 
1908  return (FIB_PATH_TYPE_RECURSIVE == path->fp_type);
1909 }
1910 
1911 int
1913 {
1914  fib_path_t *path;
1915 
1916  path = fib_path_get(path_index);
1917 
1918  return (FIB_PATH_TYPE_EXCLUSIVE == path->fp_type);
1919 }
1920 
1921 int
1923 {
1924  fib_path_t *path;
1925 
1926  path = fib_path_get(path_index);
1927 
1928  return (FIB_PATH_TYPE_DEAG == path->fp_type);
1929 }
1930 
1931 int
1933 {
1934  fib_path_t *path;
1935 
1936  path = fib_path_get(path_index);
1937 
1938  return (dpo_id_is_valid(&path->fp_dpo) &&
1940  !fib_path_is_looped(path_index) &&
1942 }
1943 
1944 int
1946 {
1947  fib_path_t *path;
1948 
1949  path = fib_path_get(path_index);
1950 
1952 }
1953 
1954 int
1956  fib_node_index_t path_index,
1957  void *ctx)
1958 {
1959  fib_route_path_encode_t **api_rpaths = ctx;
1960  fib_route_path_encode_t *api_rpath;
1961  fib_path_t *path;
1962 
1963  path = fib_path_get(path_index);
1964  if (!path)
1965  return (0);
1966  vec_add2(*api_rpaths, api_rpath, 1);
1967  api_rpath->rpath.frp_weight = path->fp_weight;
1968  api_rpath->rpath.frp_proto = path->fp_nh_proto;
1969  api_rpath->rpath.frp_sw_if_index = ~0;
1970  api_rpath->dpo = path->exclusive.fp_ex_dpo;
1971  switch (path->fp_type)
1972  {
1973  case FIB_PATH_TYPE_RECEIVE:
1974  api_rpath->rpath.frp_addr = path->receive.fp_addr;
1975  api_rpath->rpath.frp_sw_if_index = path->receive.fp_interface;
1976  break;
1978  api_rpath->rpath.frp_sw_if_index = path->attached.fp_interface;
1979  break;
1981  api_rpath->rpath.frp_sw_if_index = path->attached_next_hop.fp_interface;
1982  api_rpath->rpath.frp_addr = path->attached_next_hop.fp_nh;
1983  break;
1984  case FIB_PATH_TYPE_SPECIAL:
1985  break;
1986  case FIB_PATH_TYPE_DEAG:
1987  break;
1989  api_rpath->rpath.frp_addr = path->recursive.fp_nh.fp_ip;
1990  break;
1991  default:
1992  break;
1993  }
1994  return (1);
1995 }
1996 
1999 {
2000  fib_path_t *path;
2001 
2002  path = fib_path_get(path_index);
2003 
2004  return (path->fp_nh_proto);
2005 }
2006 
2007 void
2009 {
2010  fib_node_register_type (FIB_NODE_TYPE_PATH, &fib_path_vft);
2011 }
2012 
2013 static clib_error_t *
2015  unformat_input_t * input,
2016  vlib_cli_command_t * cmd)
2017 {
2018  fib_node_index_t pi;
2019  fib_path_t *path;
2020 
2021  if (unformat (input, "%d", &pi))
2022  {
2023  /*
2024  * show one in detail
2025  */
2026  if (!pool_is_free_index(fib_path_pool, pi))
2027  {
2028  path = fib_path_get(pi);
2029  u8 *s = fib_path_format(pi, NULL);
2030  s = format(s, "children:");
2032  vlib_cli_output (vm, "%s", s);
2033  vec_free(s);
2034  }
2035  else
2036  {
2037  vlib_cli_output (vm, "path %d invalid", pi);
2038  }
2039  }
2040  else
2041  {
2042  vlib_cli_output (vm, "FIB Paths");
2043  pool_foreach(path, fib_path_pool,
2044  ({
2045  vlib_cli_output (vm, "%U", format_fib_path, path);
2046  }));
2047  }
2048 
2049  return (NULL);
2050 }
2051 
2052 VLIB_CLI_COMMAND (show_fib_path, static) = {
2053  .path = "show fib paths",
2054  .function = show_fib_path_command,
2055  .short_help = "show fib paths",
2056 };
int fib_path_is_resolved(fib_node_index_t path_index)
Definition: fib_path.c:1932
fib_protocol_t frp_proto
The protocol of the address below.
Definition: fib_types.h:313
int fib_path_resolve(fib_node_index_t path_index)
Definition: fib_path.c:1464
Contribute an object that is to be used to forward IP6 packets.
Definition: fib_types.h:105
ip46_address_t frp_addr
The next-hop address.
Definition: fib_types.h:322
Recursive resolution source.
Definition: fib_entry.h:109
Contribute an object that is to be used to forward IP6 packets.
Definition: fib_types.h:85
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:354
uword fib_path_hash(fib_node_index_t path_index)
Definition: fib_path.c:1176
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:358
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:1742
fib_protocol_t fib_path_get_proto(fib_node_index_t path_index)
Definition: fib_path.c:1998
fib_path_oper_attribute_t_
Enurmeration of path operational (i.e.
Definition: fib_path.c:99
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:1684
A representation of a path as described by a route producer.
Definition: fib_types.h:308
u8 * format_dpo_type(u8 *s, va_list *args)
format a DPO type
Definition: dpo.c:111
dpo_id_t path_dpo
ID of the Data-path object.
Definition: load_balance.h:66
int dpo_is_adj(const dpo_id_t *dpo)
Return TRUE is the DPO is any type of adjacency.
Definition: dpo.c:240
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
adj_index_t adj_glean_add_or_lock(fib_protocol_t proto, u32 sw_if_index, const ip46_address_t *nh_addr)
Glean Adjacency.
Definition: adj_glean.c:50
#define FIB_PATH_OPER_ATTRIBUTES
Definition: fib_path.c:131
#define STRUCT_MARK_PTR(v, f)
Definition: clib.h:68
int fib_path_cmp(fib_node_index_t pi1, fib_node_index_t pi2)
Definition: fib_path.c:1284
void fib_node_init(fib_node_t *node, fib_node_type_t type)
Definition: fib_node.c:183
void lookup_dpo_add_or_lock_w_table_id(u32 table_id, dpo_proto_t proto, lookup_input_t input, lookup_table_t table_config, dpo_id_t *dpo)
Definition: lookup_dpo.c:130
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:472
static int dpo_id_is_valid(const dpo_id_t *dpoi)
Return true if the DPO object is valid, i.e.
Definition: dpo.h:185
void fib_entry_get_prefix(fib_node_index_t fib_entry_index, fib_prefix_t *pfx)
Definition: fib_entry.c:1456
#define NULL
Definition: clib.h:55
IP unicast adjacency.
Definition: lookup.h:193
void fib_path_module_init(void)
Definition: fib_path.c:2008
int fib_path_is_exclusive(fib_node_index_t path_index)
Definition: fib_path.c:1912
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:391
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:317
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:483
fib_node_index_t fp_tbl_id
The FIB table index in which to find the next-hop.
Definition: fib_path.c:249
void dpo_copy(dpo_id_t *dst, const dpo_id_t *src)
atomic copy a data-plane object.
Definition: dpo.c:224
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
word vnet_sw_interface_compare(vnet_main_t *vnm, uword sw_if_index0, uword sw_if_index1)
Definition: interface.c:1112
void lookup_dpo_add_or_lock_w_fib_index(fib_node_index_t fib_index, dpo_proto_t proto, lookup_input_t input, lookup_table_t table_config, dpo_id_t *dpo)
Definition: lookup_dpo.c:116
#define STRUCT_MARK(mark)
Definition: clib.h:67
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:561
The path is resolved.
Definition: fib_path.c:111
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:81
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:62
void fib_node_deinit(fib_node_t *node)
Definition: fib_node.c:198
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
u8 * fib_path_adj_format(fib_node_index_t pi, u32 indent, u8 *s)
Definition: fib_path.c:492
dpo_id_t fp_ex_dpo
The user provided &#39;exclusive&#39; DPO.
Definition: fib_path.c:263
int fib_path_is_looped(fib_node_index_t path_index)
Definition: fib_path.c:1945
Definition: fib_entry.h:229
void adj_child_remove(adj_index_t adj_index, u32 sibling_index)
Remove a child dependent.
Definition: adj.c:251
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
The path has become a permanent drop.
Definition: fib_path.c:119
int fib_path_cmp_for_sort(void *v1, void *v2)
Definition: fib_path.c:1266
#define ip46_address_cmp(ip46_1, ip46_2)
Definition: ip6_packet.h:80
#define pool_len(p)
Number of elements in pool vector.
Definition: pool.h:121
ip46_address_t fp_ip
The next-hop.
Definition: fib_path.c:221
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
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:1878
void fib_node_register_type(fib_node_type_t type, const fib_node_vft_t *vft)
fib_node_register_type
Definition: fib_node.c:58
const dpo_id_t * drop_dpo_get(dpo_proto_t proto)
Definition: drop_dpo.c:25
#define FIB_PATH_TYPES
Definition: fib_path.c:83
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:128
fib_node_index_t fib_path_create(fib_node_index_t pl_index, fib_protocol_t nh_proto, fib_path_cfg_flags_t flags, const fib_route_path_t *rpath)
Definition: fib_path.c:984
fib_path_type_t fp_type
The type of the path.
Definition: fib_path.c:181
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:376
u32 frp_sw_if_index
The interface.
Definition: fib_types.h:334
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:388
static const adj_index_t fib_path_attached_next_hop_get_adj(fib_path_t *path, vnet_link_t link)
Definition: fib_path.c:527
Recursion constraint of via a host prefix.
Definition: fib_types.h:276
fib_node_index_t fib_path_create_special(fib_node_index_t pl_index, fib_protocol_t nh_proto, fib_path_cfg_flags_t flags, const dpo_id_t *dpo)
Definition: fib_path.c:1077
fib_node_index_t fib_path_copy(fib_node_index_t path_index, fib_node_index_t path_list_index)
Definition: fib_path.c:1122
Aggregrate type for a prefix.
Definition: fib_types.h:160
fib_path_cfg_flags_t fp_cfg_flags
Configuration Flags.
Definition: fib_path.c:176
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:375
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:221
fib_node_t fp_node
A path is a node in the FIB graph.
Definition: fib_path.c:160
void adj_unlock(adj_index_t adj_index)
Release a reference counting lock on the adjacency.
Definition: adj.c:215
dpo_id_t fp_dpo
The Data-path objects through which this path resolves for IP.
Definition: fib_path.c:298
#define FIB_PATH_CFG_ATTRIBUTES
Definition: fib_path.h:84
Contribute an object that is to be used to forward Ethernet packets.
Definition: fib_types.h:109
void fib_urpf_list_append(index_t ui, u32 sw_if_index)
Append another interface to the list.
void fib_prefix_from_mpls_label(mpls_label_t label, fib_prefix_t *prf)
Big train switch; FIB debugs on or off.
Definition: fib_types.c:68
static void fib_path_attached_next_hop_set(fib_path_t *path)
Definition: fib_path.c:554
Definition: fib_entry.h:227
u8 * format_fib_path(u8 *s, va_list *args)
Definition: fib_path.c:363
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:146
u32 fp_sibling
the index of this path in the parent&#39;s child list.
Definition: fib_path.c:303
Contribute an object that is to be used to forward end-of-stack MPLS packets.
Definition: fib_types.h:97
fib_node_bw_reason_flag_t fnbw_reason
The reason/trigger for the backwalk.
Definition: fib_node.h:194
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:397
struct fib_path_t_ fib_path_t
A FIB path.
dpo_type_t dpoi_type
the type
Definition: dpo.h:150
int vnet_sw_interface_is_p2p(vnet_main_t *vnm, u32 sw_if_index)
Definition: interface.c:1138
struct _unformat_input_t unformat_input_t
struct fib_path_t_::@97::@105 receive
fib_protocol_t fp_nh_proto
The protocol of the next-hop, i.e.
Definition: fib_path.c:188
adj_index_t fib_path_get_adj(fib_node_index_t path_index)
Definition: fib_path.c:1651
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:241
Recursion constraint of via an attahced prefix.
Definition: fib_types.h:280
u32 fp_weight
UCMP [unnormalised] weigt.
Definition: fib_path.c:193
fib_node_type_t fn_type
The node&#39;s type.
Definition: fib_node.h:282
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:277
static fib_path_t * fib_path_pool
Definition: fib_path.c:316
static fib_path_t * fib_path_get(fib_node_index_t index)
Definition: fib_path.c:336
ip46_address_t fp_nh
The next-hop.
Definition: fib_path.c:203
u32 fib_entry_get_resolving_interface(fib_node_index_t entry_index)
Definition: fib_entry.c:1321
fib_path_oper_flags_t_
Path flags from the attributes.
Definition: fib_path.c:145
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:369
#define FOR_EACH_FIB_PATH_OPER_ATTRIBUTE(_item)
Definition: fib_path.c:137
The path forms part of a recursive loop.
Definition: fib_path.c:107
vnet_link_t fib_forw_chain_type_to_link_type(fib_forward_chain_type_t fct)
Convert from a chain type to the adjacencies link type.
Definition: fib_types.c:290
fib_node_list_t fn_children
Vector of nodes that depend upon/use/share this node.
Definition: fib_node.h:294
int fib_path_is_recursive(fib_node_index_t path_index)
Definition: fib_path.c:1902
vlib_main_t * vm
Definition: buffer.c:276
u8 * fib_path_format(fib_node_index_t pi, u8 *s)
Definition: fib_path.c:481
Contribute an object that is to be used to forward NSH packets.
Definition: fib_types.h:115
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:340
#define MPLS_FIB_DEFAULT_TABLE_ID
Definition: mpls.h:33
u32 frp_weight
[un]equal cost path weight
Definition: fib_types.h:343
static void fib_path_last_lock_gone(fib_node_t *node)
Definition: fib_path.c:521
static fib_node_index_t fib_path_get_index(fib_path_t *path)
Definition: fib_path.c:342
A FIB path.
Definition: fib_path.c:156
struct fib_path_t_::@97::@102 deag
int fib_entry_recursive_loop_detect(fib_node_index_t entry_index, fib_node_index_t **entry_indicies)
Definition: fib_entry.c:1270
fib_node_get_t fnv_get
Definition: fib_node.h:265
enum fib_path_oper_flags_t_ fib_path_oper_flags_t
Path flags from the attributes.
int fib_path_encode(fib_node_index_t path_list_index, fib_node_index_t path_index, void *ctx)
Definition: fib_path.c:1955
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:28
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:238
u32 adj_index_t
An index for adjacencies.
Definition: adj_types.h:30
void fib_prefix_from_ip46_addr(const ip46_address_t *addr, fib_prefix_t *pfx)
Host prefix from ip.
Definition: fib_types.c:54
static void fib_path_memory_show(void)
Definition: fib_path.c:942
The path is attached, despite what the next-hop may say.
Definition: fib_path.c:115
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:157
struct fib_path_t_::@97::@104 exclusive
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:762
Context passed between object during a back walk.
Definition: fib_node.h:190
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
u32 fp_pl_index
The index of the path-list to which this path belongs.
Definition: fib_path.c:165
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:586
static fib_forward_chain_type_t fib_path_proto_to_chain_type(fib_protocol_t proto)
Definition: fib_path.c:742
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
int fib_path_is_deag(fib_node_index_t path_index)
Definition: fib_path.c:1922
fib_node_index_t fp_via_fib
the resolving via fib.
Definition: fib_path.c:293
static int fib_path_is_permanent_drop(fib_path_t *path)
Definition: fib_path.c:675
enum vnet_link_t_ vnet_link_t
Link Type: A description of the protocol of packets on the link.
ip46_address_t fp_addr
The next-hop.
Definition: fib_path.c:273
uword hash_memory(void *p, word n_bytes, uword state)
Definition: hash.c:214
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:347
u32 fp_interface
The interface.
Definition: fib_path.c:207
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:2014
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:220
int fib_path_get_weight(fib_node_index_t path_index)
Definition: fib_path.c:1666
u8 * format_dpo_id(u8 *s, va_list *args)
Format a DPO_id_t oject
Definition: dpo.c:121
u8 * format_fib_protocol(u8 *s, va_list ap)
Definition: fib_types.c:30
struct fib_path_t_::@97::@101 recursive
static uword vnet_sw_interface_is_admin_up(vnet_main_t *vnm, u32 sw_if_index)
u64 uword
Definition: types.h:112
format_function_t format_mpls_unicast_label
Definition: mpls.h:91
static void fib_path_unresolve(fib_path_t *path)
Definition: fib_path.c:687
mpls_label_t frp_local_label
The MPLS local Label to reursively resolve through.
Definition: fib_types.h:328
fib_path_oper_flags_t fp_oper_flags
Memebers in this last section represent information that is dervied during resolution.
Definition: fib_path.c:287
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:47
u32 fib_path_get_resolving_interface(fib_node_index_t path_index)
Definition: fib_path.c:1622
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:162
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:29
A for-us/local path.
Definition: fib_types.h:284
unsigned char u8
Definition: types.h:56
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:234
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:173
#define FIB_PATH_DBG(_p, _fmt, _args...)
Definition: fib_path.c:332
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.
int fib_path_recursive_loop_detect(fib_node_index_t path_index, fib_node_index_t **entry_indicies)
Definition: fib_path.c:1384
A FIB graph nodes virtual function table.
Definition: fib_node.h:264
struct fib_path_t_::@97::@100 attached
static fib_path_cfg_flags_t fib_path_route_flags_to_cfg_flags(const fib_route_path_t *rpath)
Definition: fib_path.c:961
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:216
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:194
mpls_label_t fp_local_label
The local label to resolve through.
Definition: fib_path.c:225
#define vec_foreach(var, vec)
Vector iterator.
fib_route_path_t rpath
Definition: fib_types.h:359
vnet_link_t fib_proto_to_link(fib_protocol_t proto)
Convert from a protocol to a link type.
Definition: fib_types.c:254
fib_path_type_t_
Enurmeration of path types.
Definition: fib_path.c:39
Contribute an object that is to be used to forward non-end-of-stack MPLS packets. ...
Definition: fib_types.h:90
Attached path.
Definition: fib_types.h:288
struct fib_path_t_::@97::@99 attached_next_hop
u32 flags
Definition: vhost-user.h:78
u8 * fib_node_children_format(fib_node_list_t list, u8 *s)
Definition: fib_node.c:174
fib_source_t fib_entry_get_best_source(fib_node_index_t entry_index)
Definition: fib_entry.c:1331
#define ip46_address_is_zero(ip46)
Definition: ip6_packet.h:81
Contribute an object that is to be used to forward IP4 packets.
Definition: fib_types.h:101
u32 frp_fib_index
The FIB index to lookup the nexthop Only valid for recursive paths.
Definition: fib_types.h:339
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:577
void fib_path_destroy(fib_node_index_t path_index)
Definition: fib_path.c:1155
#define FOR_EACH_FIB_PATH_CFG_ATTRIBUTE(_item)
Definition: fib_path.h:93
static int fib_path_cmp_i(const fib_path_t *path1, const fib_path_t *path2)
Definition: fib_path.c:1194
const ip46_address_t zero_addr
Definition: lookup.c:354
int fib_path_cmp_w_route_path(fib_node_index_t path_index, const fib_route_path_t *rpath)
Definition: fib_path.c:1296
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:971
static fib_node_t * fib_path_get_node(fib_node_index_t index)
Definition: fib_path.c:348
fib_entry_flag_t fib_entry_get_flags(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:278
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109