Dump routes (VPP-500)
[vpp.git] / vnet / vnet / fib / fib_path.c
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>
22 #include <vnet/dpo/load_balance_map.h>
23 #include <vnet/dpo/lookup_dpo.h>
24
25 #include <vnet/adj/adj.h>
26
27 #include <vnet/fib/fib_path.h>
28 #include <vnet/fib/fib_node.h>
29 #include <vnet/fib/fib_table.h>
30 #include <vnet/fib/fib_entry.h>
31 #include <vnet/fib/fib_path_list.h>
32 #include <vnet/fib/fib_internal.h>
33 #include <vnet/fib/fib_urpf_list.h>
34
35 /**
36  * Enurmeration of path types
37  */
38 typedef enum fib_path_type_t_ {
39     /**
40      * Marker. Add new types after this one.
41      */
42     FIB_PATH_TYPE_FIRST = 0,
43     /**
44      * Attached-nexthop. An interface and a nexthop are known.
45      */
46     FIB_PATH_TYPE_ATTACHED_NEXT_HOP = FIB_PATH_TYPE_FIRST,
47     /**
48      * attached. Only the interface is known.
49      */
50     FIB_PATH_TYPE_ATTACHED,
51     /**
52      * recursive. Only the next-hop is known.
53      */
54     FIB_PATH_TYPE_RECURSIVE,
55     /**
56      * special. nothing is known. so we drop.
57      */
58     FIB_PATH_TYPE_SPECIAL,
59     /**
60      * exclusive. user provided adj.
61      */
62     FIB_PATH_TYPE_EXCLUSIVE,
63     /**
64      * deag. Link to a lookup adj in the next table
65      */
66     FIB_PATH_TYPE_DEAG,
67     /**
68      * receive. it's for-us.
69      */
70     FIB_PATH_TYPE_RECEIVE,
71     /**
72      * Marker. Add new types before this one, then update it.
73      */
74     FIB_PATH_TYPE_LAST = FIB_PATH_TYPE_RECEIVE,
75 } __attribute__ ((packed)) fib_path_type_t;
76
77 /**
78  * The maximum number of path_types
79  */
80 #define FIB_PATH_TYPE_MAX (FIB_PATH_TYPE_LAST + 1)
81
82 #define FIB_PATH_TYPES {                                        \
83     [FIB_PATH_TYPE_ATTACHED_NEXT_HOP] = "attached-nexthop",     \
84     [FIB_PATH_TYPE_ATTACHED]          = "attached",             \
85     [FIB_PATH_TYPE_RECURSIVE]         = "recursive",            \
86     [FIB_PATH_TYPE_SPECIAL]           = "special",              \
87     [FIB_PATH_TYPE_EXCLUSIVE]         = "exclusive",            \
88     [FIB_PATH_TYPE_DEAG]              = "deag",                 \
89     [FIB_PATH_TYPE_RECEIVE]           = "receive",              \
90 }
91
92 #define FOR_EACH_FIB_PATH_TYPE(_item) \
93     for (_item = FIB_PATH_TYPE_FIRST; _item <= FIB_PATH_TYPE_LAST; _item++)
94
95 /**
96  * Enurmeration of path operational (i.e. derived) attributes
97  */
98 typedef enum fib_path_oper_attribute_t_ {
99     /**
100      * Marker. Add new types after this one.
101      */
102     FIB_PATH_OPER_ATTRIBUTE_FIRST = 0,
103     /**
104      * The path forms part of a recursive loop.
105      */
106     FIB_PATH_OPER_ATTRIBUTE_RECURSIVE_LOOP = FIB_PATH_OPER_ATTRIBUTE_FIRST,
107     /**
108      * The path is resolved
109      */
110     FIB_PATH_OPER_ATTRIBUTE_RESOLVED,
111     /**
112      * The path has become a permanent drop.
113      */
114     FIB_PATH_OPER_ATTRIBUTE_DROP,
115     /**
116      * Marker. Add new types before this one, then update it.
117      */
118     FIB_PATH_OPER_ATTRIBUTE_LAST = FIB_PATH_OPER_ATTRIBUTE_DROP,
119 } __attribute__ ((packed)) fib_path_oper_attribute_t;
120
121 /**
122  * The maximum number of path operational attributes
123  */
124 #define FIB_PATH_OPER_ATTRIBUTE_MAX (FIB_PATH_OPER_ATTRIBUTE_LAST + 1)
125
126 #define FIB_PATH_OPER_ATTRIBUTES {                                      \
127     [FIB_PATH_OPER_ATTRIBUTE_RECURSIVE_LOOP] = "recursive-loop",        \
128     [FIB_PATH_OPER_ATTRIBUTE_RESOLVED]       = "resolved",              \
129     [FIB_PATH_OPER_ATTRIBUTE_DROP]           = "drop",                  \
130 }
131
132 #define FOR_EACH_FIB_PATH_OPER_ATTRIBUTE(_item) \
133     for (_item = FIB_PATH_OPER_ATTRIBUTE_FIRST; \
134          _item <= FIB_PATH_OPER_ATTRIBUTE_LAST; \
135          _item++)
136
137 /**
138  * Path flags from the attributes
139  */
140 typedef enum fib_path_oper_flags_t_ {
141     FIB_PATH_OPER_FLAG_NONE = 0,
142     FIB_PATH_OPER_FLAG_RECURSIVE_LOOP = (1 << FIB_PATH_OPER_ATTRIBUTE_RECURSIVE_LOOP),
143     FIB_PATH_OPER_FLAG_DROP = (1 << FIB_PATH_OPER_ATTRIBUTE_DROP),
144     FIB_PATH_OPER_FLAG_RESOLVED = (1 << FIB_PATH_OPER_ATTRIBUTE_RESOLVED),
145 } __attribute__ ((packed)) fib_path_oper_flags_t;
146
147 /**
148  * A FIB path
149  */
150 typedef struct fib_path_t_ {
151     /**
152      * A path is a node in the FIB graph.
153      */
154     fib_node_t fp_node;
155
156     /**
157      * The index of the path-list to which this path belongs
158      */
159     u32 fp_pl_index;
160
161     /**
162      * This marks the start of the memory area used to hash
163      * the path
164      */
165     STRUCT_MARK(path_hash_start);
166
167     /**
168      * Configuration Flags
169      */
170     fib_path_cfg_flags_t fp_cfg_flags;
171
172     /**
173      * The type of the path. This is the selector for the union
174      */
175     fib_path_type_t fp_type;
176
177     /**
178      * The protocol of the next-hop, i.e. the address family of the
179      * next-hop's address. We can't derive this from the address itself
180      * since the address can be all zeros
181      */
182     fib_protocol_t fp_nh_proto;
183
184     /**
185      * UCMP [unnormalised] weigt
186      */
187     u32 fp_weight;
188
189     /**
190      * per-type union of the data required to resolve the path
191      */
192     union {
193         struct {
194             /**
195              * The next-hop
196              */
197             ip46_address_t fp_nh;
198             /**
199              * The interface
200              */
201             u32 fp_interface;
202         } attached_next_hop;
203         struct {
204             /**
205              * The interface
206              */
207             u32 fp_interface;
208         } attached;
209         struct {
210             /**
211              * The next-hop
212              */
213             ip46_address_t fp_nh;
214             /**
215              * The FIB table index in which to find the next-hop.
216              * This needs to be fixed. We should lookup the adjacencies in
217              * a separate table of adjacencies, rather than from the FIB.
218              * Two reasons I can think of:
219              *   - consider:
220              *       int ip addr Gig0 10.0.0.1/24
221              *       ip route 10.0.0.2/32 via Gig1 192.168.1.2
222              *       ip route 1.1.1.1/32 via Gig0 10.0.0.2
223              *     this is perfectly valid.
224              *     Packets addressed to 10.0.0.2 should be sent via Gig1.
225              *     Packets address to 1.1.1.1 should be sent via Gig0.
226              *    when we perform the adj resolution from the FIB for the path
227              *    "via Gig0 10.0.0.2" the lookup will result in the route via Gig1
228              *    and so we will pick up the adj via Gig1 - which was not what the
229              *    operator wanted.
230              *  - we can only return link-type IPv4 and so not the link-type MPLS.
231              *    more on this in a later commit.
232              *
233              * The table ID should only belong to a recursive path and indicate
234              * which FIB should be used to resolve the next-hop.
235              */
236             fib_node_index_t fp_tbl_id;
237         } recursive;
238         struct {
239             /**
240              * The FIN index in which to perfom the next lookup
241              */
242             fib_node_index_t fp_tbl_id;
243         } deag;
244         struct {
245         } special;
246         struct {
247             /**
248              * The user provided 'exclusive' DPO
249              */
250             dpo_id_t fp_ex_dpo;
251         } exclusive;
252         struct {
253             /**
254              * The interface on which the local address is configured
255              */
256             u32 fp_interface;
257             /**
258              * The next-hop
259              */
260             ip46_address_t fp_addr;
261         } receive;
262     };
263     STRUCT_MARK(path_hash_end);
264
265     /**
266      * Memebers in this last section represent information that is
267      * dervied during resolution. It should not be copied to new paths
268      * nor compared.
269      */
270
271     /**
272      * Operational Flags
273      */
274     fib_path_oper_flags_t fp_oper_flags;
275
276     /**
277      * the resolving via fib. not part of the union, since it it not part
278      * of the path's hash.
279      */
280     fib_node_index_t fp_via_fib;
281
282     /**
283      * The Data-path objects through which this path resolves for IP.
284      */
285     dpo_id_t fp_dpo;
286
287     /**
288      * the index of this path in the parent's child list.
289      */
290     u32 fp_sibling;
291 } fib_path_t;
292
293 /*
294  * Array of strings/names for the path types and attributes
295  */
296 static const char *fib_path_type_names[] = FIB_PATH_TYPES;
297 static const char *fib_path_oper_attribute_names[] = FIB_PATH_OPER_ATTRIBUTES;
298 static const char *fib_path_cfg_attribute_names[]  = FIB_PATH_CFG_ATTRIBUTES;
299
300 /*
301  * The memory pool from which we allocate all the paths
302  */
303 static fib_path_t *fib_path_pool;
304
305 /*
306  * Debug macro
307  */
308 #ifdef FIB_DEBUG
309 #define FIB_PATH_DBG(_p, _fmt, _args...)                        \
310 {                                                               \
311     u8 *_tmp = NULL;                                            \
312     _tmp = fib_path_format(fib_path_get_index(_p), _tmp);       \
313     clib_warning("path:[%d:%s]:" _fmt,                          \
314                  fib_path_get_index(_p), _tmp,                  \
315                  ##_args);                                      \
316     vec_free(_tmp);                                             \
317 }
318 #else
319 #define FIB_PATH_DBG(_p, _fmt, _args...)
320 #endif
321
322 static fib_path_t *
323 fib_path_get (fib_node_index_t index)
324 {
325     return (pool_elt_at_index(fib_path_pool, index));
326 }
327
328 static fib_node_index_t 
329 fib_path_get_index (fib_path_t *path)
330 {
331     return (path - fib_path_pool);
332 }
333
334 static fib_node_t *
335 fib_path_get_node (fib_node_index_t index)
336 {
337     return ((fib_node_t*)fib_path_get(index));
338 }
339
340 static fib_path_t*
341 fib_path_from_fib_node (fib_node_t *node)
342 {
343 #if CLIB_DEBUG > 0
344     ASSERT(FIB_NODE_TYPE_PATH == node->fn_type);
345 #endif
346     return ((fib_path_t*)node);
347 }
348
349 u8 *
350 format_fib_path (u8 * s, va_list * args)
351 {
352     fib_path_t *path = va_arg (*args, fib_path_t *);
353     vnet_main_t * vnm = vnet_get_main();
354     fib_path_oper_attribute_t oattr;
355     fib_path_cfg_attribute_t cattr;
356
357     s = format (s, "      index:%d ", fib_path_get_index(path));
358     s = format (s, "pl-index:%d ", path->fp_pl_index);
359     s = format (s, "%U ", format_fib_protocol, path->fp_nh_proto);
360     s = format (s, "weight=%d ", path->fp_weight);
361     s = format (s, "%s: ", fib_path_type_names[path->fp_type]);
362     if (FIB_PATH_OPER_FLAG_NONE != path->fp_oper_flags) {
363         s = format(s, " oper-flags:");
364         FOR_EACH_FIB_PATH_OPER_ATTRIBUTE(oattr) {
365             if ((1<<oattr) & path->fp_oper_flags) {
366                 s = format (s, "%s,", fib_path_oper_attribute_names[oattr]);
367             }
368         }
369     }
370     if (FIB_PATH_CFG_FLAG_NONE != path->fp_cfg_flags) {
371         s = format(s, " cfg-flags:");
372         FOR_EACH_FIB_PATH_CFG_ATTRIBUTE(cattr) {
373             if ((1<<cattr) & path->fp_cfg_flags) {
374                 s = format (s, "%s,", fib_path_cfg_attribute_names[cattr]);
375             }
376         }
377     }
378     s = format(s, "\n       ");
379
380     switch (path->fp_type)
381     {
382     case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
383         s = format (s, "%U", format_ip46_address,
384                     &path->attached_next_hop.fp_nh,
385                     IP46_TYPE_ANY);
386         if (path->fp_oper_flags & FIB_PATH_OPER_FLAG_DROP)
387         {
388             s = format (s, " if_index:%d", path->attached_next_hop.fp_interface);
389         }
390         else
391         {
392             s = format (s, " %U",
393                         format_vnet_sw_interface_name,
394                         vnm,
395                         vnet_get_sw_interface(
396                             vnm,
397                             path->attached_next_hop.fp_interface));
398             if (vnet_sw_interface_is_p2p(vnet_get_main(),
399                                          path->attached_next_hop.fp_interface))
400             {
401                 s = format (s, " (p2p)");
402             }
403         }
404         if (!dpo_id_is_valid(&path->fp_dpo))
405         {
406             s = format(s, "\n          unresolved");
407         }
408         else
409         {
410             s = format(s, "\n          %U",
411                        format_dpo_id,
412                        &path->fp_dpo, 13);
413         }
414         break;
415     case FIB_PATH_TYPE_ATTACHED:
416         if (path->fp_oper_flags & FIB_PATH_OPER_FLAG_DROP)
417         {
418             s = format (s, " if_index:%d", path->attached_next_hop.fp_interface);
419         }
420         else
421         {
422             s = format (s, " %U",
423                         format_vnet_sw_interface_name,
424                         vnm,
425                         vnet_get_sw_interface(
426                             vnm,
427                             path->attached.fp_interface));
428         }
429         break;
430     case FIB_PATH_TYPE_RECURSIVE:
431         s = format (s, "via %U",
432                     format_ip46_address,
433                     &path->recursive.fp_nh,
434                     IP46_TYPE_ANY);
435         s = format (s, " in fib:%d", path->recursive.fp_tbl_id, path->fp_via_fib); 
436         s = format (s, " via-fib:%d", path->fp_via_fib); 
437         s = format (s, " via-dpo:[%U:%d]",
438                     format_dpo_type, path->fp_dpo.dpoi_type, 
439                     path->fp_dpo.dpoi_index);
440
441         break;
442     case FIB_PATH_TYPE_RECEIVE:
443     case FIB_PATH_TYPE_SPECIAL:
444     case FIB_PATH_TYPE_DEAG:
445     case FIB_PATH_TYPE_EXCLUSIVE:
446         if (dpo_id_is_valid(&path->fp_dpo))
447         {
448             s = format(s, "%U", format_dpo_id,
449                        &path->fp_dpo, 2);
450         }
451         break;
452     }
453     return (s);
454 }
455
456 u8 *
457 fib_path_format (fib_node_index_t pi, u8 *s)
458 {
459     fib_path_t *path;
460
461     path = fib_path_get(pi);
462     ASSERT(NULL != path);
463
464     return (format (s, "%U", format_fib_path, path));
465 }
466
467 u8 *
468 fib_path_adj_format (fib_node_index_t pi,
469                      u32 indent,
470                      u8 *s)
471 {
472     fib_path_t *path;
473
474     path = fib_path_get(pi);
475     ASSERT(NULL != path);
476
477     if (!dpo_id_is_valid(&path->fp_dpo))
478     {
479         s = format(s, " unresolved");
480     }
481     else
482     {
483         s = format(s, "%U", format_dpo_id,
484                    &path->fp_dpo, 2);
485     }
486
487     return (s);
488 }
489
490 /*
491  * fib_path_last_lock_gone
492  *
493  * We don't share paths, we share path lists, so the [un]lock functions
494  * are no-ops
495  */
496 static void
497 fib_path_last_lock_gone (fib_node_t *node)
498 {
499     ASSERT(0);
500 }
501
502 static const adj_index_t
503 fib_path_attached_next_hop_get_adj (fib_path_t *path,
504                                     vnet_link_t link)
505 {
506     if (vnet_sw_interface_is_p2p(vnet_get_main(),
507                                  path->attached_next_hop.fp_interface))
508     {
509         /*
510          * if the interface is p2p then the adj for the specific
511          * neighbour on that link will never exist. on p2p links
512          * the subnet address (the attached route) links to the
513          * auto-adj (see below), we want that adj here too.
514          */
515         return (adj_nbr_add_or_lock(path->fp_nh_proto,
516                                     link,
517                                     &zero_addr,
518                                     path->attached_next_hop.fp_interface));
519     }
520     else
521     {
522         return (adj_nbr_add_or_lock(path->fp_nh_proto,
523                                     link,
524                                     &path->attached_next_hop.fp_nh,
525                                     path->attached_next_hop.fp_interface));
526     }
527 }
528
529 static void
530 fib_path_attached_next_hop_set (fib_path_t *path)
531 {
532     /*
533      * resolve directly via the adjacnecy discribed by the
534      * interface and next-hop
535      */
536     if (!vnet_sw_interface_is_admin_up(vnet_get_main(),
537                                       path->attached_next_hop.fp_interface))
538     {
539         path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
540     }
541
542     dpo_set(&path->fp_dpo,
543             DPO_ADJACENCY,
544             fib_proto_to_dpo(path->fp_nh_proto),
545             fib_path_attached_next_hop_get_adj(
546                  path,
547                  fib_proto_to_link(path->fp_nh_proto)));
548
549     /*
550      * become a child of the adjacency so we receive updates
551      * when its rewrite changes
552      */
553     path->fp_sibling = adj_child_add(path->fp_dpo.dpoi_index,
554                                      FIB_NODE_TYPE_PATH,
555                                      fib_path_get_index(path));
556 }
557
558 /*
559  * create of update the paths recursive adj
560  */
561 static void
562 fib_path_recursive_adj_update (fib_path_t *path,
563                                fib_forward_chain_type_t fct,
564                                dpo_id_t *dpo)
565 {
566     dpo_id_t via_dpo = DPO_INVALID;
567
568     /*
569      * get the DPO to resolve through from the via-entry
570      */
571     fib_entry_contribute_forwarding(path->fp_via_fib,
572                                     fct,
573                                     &via_dpo);
574
575
576     /*
577      * hope for the best - clear if restrictions apply.
578      */
579     path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED;
580
581     /*
582      * Validate any recursion constraints and over-ride the via
583      * adj if not met
584      */
585     if (path->fp_oper_flags & FIB_PATH_OPER_FLAG_RECURSIVE_LOOP)
586     {
587         path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
588         dpo_copy(&via_dpo, drop_dpo_get(fib_proto_to_dpo(path->fp_nh_proto)));
589     }
590     else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RESOLVE_HOST)
591     {
592         /*
593          * the via FIB must be a host route.
594          * note the via FIB just added will always be a host route
595          * since it is an RR source added host route. So what we need to
596          * check is whether the route has other sources. If it does then
597          * some other source has added it as a host route. If it doesn't
598          * then it was added only here and inherits forwarding from a cover.
599          * the cover is not a host route.
600          * The RR source is the lowest priority source, so we check if it
601          * is the best. if it is there are no other sources.
602          */
603         if (fib_entry_get_best_source(path->fp_via_fib) >= FIB_SOURCE_RR)
604         {
605             path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
606             dpo_copy(&via_dpo, drop_dpo_get(fib_proto_to_dpo(path->fp_nh_proto)));
607
608             /*
609              * PIC edge trigger. let the load-balance maps know
610              */
611             load_balance_map_path_state_change(fib_path_get_index(path));
612         }
613     }
614     else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RESOLVE_ATTACHED)
615     {
616         /*
617          * RR source entries inherit the flags from the cover, so
618          * we can check the via directly
619          */
620         if (!(FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(path->fp_via_fib)))
621         {
622             path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
623             dpo_copy(&via_dpo, drop_dpo_get(fib_proto_to_dpo(path->fp_nh_proto)));
624
625             /*
626              * PIC edge trigger. let the load-balance maps know
627              */
628             load_balance_map_path_state_change(fib_path_get_index(path));
629         }
630     }
631
632     /*
633      * update the path's contributed DPO
634      */
635     dpo_copy(dpo, &via_dpo);
636
637     FIB_PATH_DBG(path, "recursive update: %U",
638                  fib_get_lookup_main(path->fp_nh_proto),
639                  &path->fp_dpo, 2);
640
641     dpo_reset(&via_dpo);
642 }
643
644 /*
645  * fib_path_is_permanent_drop
646  *
647  * Return !0 if the path is configured to permanently drop,
648  * despite other attributes.
649  */
650 static int
651 fib_path_is_permanent_drop (fib_path_t *path)
652 {
653     return ((path->fp_cfg_flags & FIB_PATH_CFG_FLAG_DROP) ||
654             (path->fp_oper_flags & FIB_PATH_OPER_FLAG_DROP));
655 }
656
657 /*
658  * fib_path_unresolve
659  *
660  * Remove our dependency on the resolution target
661  */
662 static void
663 fib_path_unresolve (fib_path_t *path)
664 {
665     /*
666      * the forced drop path does not need unresolving
667      */
668     if (fib_path_is_permanent_drop(path))
669     {
670         return;
671     }
672
673     switch (path->fp_type)
674     {
675     case FIB_PATH_TYPE_RECURSIVE:
676         if (FIB_NODE_INDEX_INVALID != path->fp_via_fib)
677         {
678             fib_prefix_t pfx;
679
680             fib_prefix_from_ip46_addr(&path->recursive.fp_nh, &pfx);
681             fib_entry_child_remove(path->fp_via_fib,
682                                    path->fp_sibling);
683             fib_table_entry_special_remove(path->recursive.fp_tbl_id,
684                                            &pfx,
685                                            FIB_SOURCE_RR);
686             path->fp_via_fib = FIB_NODE_INDEX_INVALID;
687         }
688         break;
689     case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
690     case FIB_PATH_TYPE_ATTACHED:
691         adj_child_remove(path->fp_dpo.dpoi_index,
692                          path->fp_sibling);
693         adj_unlock(path->fp_dpo.dpoi_index);
694         break;
695     case FIB_PATH_TYPE_EXCLUSIVE:
696         dpo_reset(&path->exclusive.fp_ex_dpo);
697         break;
698     case FIB_PATH_TYPE_SPECIAL:
699     case FIB_PATH_TYPE_RECEIVE:
700     case FIB_PATH_TYPE_DEAG:
701         /*
702          * these hold only the path's DPO, which is reset below.
703          */
704         break;
705     }
706
707     /*
708      * release the adj we were holding and pick up the
709      * drop just in case.
710      */
711     dpo_reset(&path->fp_dpo);
712     path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
713
714     return;
715 }
716
717 static fib_forward_chain_type_t
718 fib_path_proto_to_chain_type (fib_protocol_t proto)
719 {
720     switch (proto)
721     {
722     case FIB_PROTOCOL_IP4:
723         return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
724     case FIB_PROTOCOL_IP6:
725         return (FIB_FORW_CHAIN_TYPE_UNICAST_IP6);
726     case FIB_PROTOCOL_MPLS:
727         return (FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS);
728     }
729     return (FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
730 }
731
732 /*
733  * fib_path_back_walk_notify
734  *
735  * A back walk has reach this path.
736  */
737 static fib_node_back_walk_rc_t
738 fib_path_back_walk_notify (fib_node_t *node,
739                            fib_node_back_walk_ctx_t *ctx)
740 {
741     fib_path_t *path;
742
743     path = fib_path_from_fib_node(node);
744
745     switch (path->fp_type)
746     {
747     case FIB_PATH_TYPE_RECURSIVE:
748         if (FIB_NODE_BW_REASON_FLAG_EVALUATE & ctx->fnbw_reason)
749         {
750             /*
751              * modify the recursive adjacency to use the new forwarding
752              * of the via-fib.
753              * this update is visible to packets in flight in the DP.
754              */
755             fib_path_recursive_adj_update(
756                 path,
757                 fib_path_proto_to_chain_type(path->fp_nh_proto),
758                 &path->fp_dpo);
759         }
760         if ((FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE & ctx->fnbw_reason) ||
761             (FIB_NODE_BW_REASON_FLAG_ADJ_DOWN   & ctx->fnbw_reason))
762         {
763             /*
764              * ADJ updates (complete<->incomplete) do not need to propagate to
765              * recursive entries.
766              * The only reason its needed as far back as here, is that the adj
767              * and the incomplete adj are a different DPO type, so the LBs need
768              * to re-stack.
769              * If this walk was quashed in the fib_entry, then any non-fib_path
770              * children (like tunnels that collapse out the LB when they stack)
771              * would not see the update.
772              */
773             return (FIB_NODE_BACK_WALK_CONTINUE);
774         }
775         break;
776     case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
777         /*
778 FIXME comment
779          * ADJ_UPDATE backwalk pass silently through here and up to
780          * the path-list when the multipath adj collapse occurs.
781          * The reason we do this is that the assumtption is that VPP
782          * runs in an environment where the Control-Plane is remote
783          * and hence reacts slowly to link up down. In order to remove
784          * this down link from the ECMP set quickly, we back-walk.
785          * VPP also has dedicated CPUs, so we are not stealing resources
786          * from the CP to do so.
787          */
788         if (FIB_NODE_BW_REASON_FLAG_INTERFACE_UP & ctx->fnbw_reason)
789         {
790             path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED;
791         }
792         if (FIB_NODE_BW_REASON_FLAG_INTERFACE_DOWN & ctx->fnbw_reason)
793         {
794             path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
795         }
796         if (FIB_NODE_BW_REASON_FLAG_INTERFACE_DELETE & ctx->fnbw_reason)
797         {
798             /*
799              * The interface this path resolves through has been deleted.
800              * This will leave the path in a permanent drop state. The route
801              * needs to be removed and readded (and hence the path-list deleted)
802              * before it can forward again.
803              */
804             fib_path_unresolve(path);
805             path->fp_oper_flags |= FIB_PATH_OPER_FLAG_DROP;
806         }
807         if (FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE & ctx->fnbw_reason)
808         {
809             /*
810              * restack the DPO to pick up the correct DPO sub-type
811              */
812             adj_index_t ai;
813
814             if (vnet_sw_interface_is_admin_up(vnet_get_main(),
815                                               path->attached_next_hop.fp_interface))
816             {
817                 path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED;
818             }
819
820             ai = fib_path_attached_next_hop_get_adj(
821                      path,
822                      fib_proto_to_link(path->fp_nh_proto));
823
824             dpo_set(&path->fp_dpo, DPO_ADJACENCY,
825                     fib_proto_to_dpo(path->fp_nh_proto),
826                     ai);
827             adj_unlock(ai);
828         }
829         if (FIB_NODE_BW_REASON_FLAG_ADJ_DOWN & ctx->fnbw_reason)
830         {
831             /*
832              * the adj has gone down. the path is no longer resolved.
833              */
834             path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
835         }
836         break;
837     case FIB_PATH_TYPE_ATTACHED:
838         /*
839          * FIXME; this could schedule a lower priority walk, since attached
840          * routes are not usually in ECMP configurations so the backwalk to
841          * the FIB entry does not need to be high priority
842          */
843         if (FIB_NODE_BW_REASON_FLAG_INTERFACE_UP & ctx->fnbw_reason)
844         {
845             path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED;
846         }
847         if (FIB_NODE_BW_REASON_FLAG_INTERFACE_DOWN & ctx->fnbw_reason)
848         {
849             path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
850         }
851         if (FIB_NODE_BW_REASON_FLAG_INTERFACE_DELETE & ctx->fnbw_reason)
852         {
853             fib_path_unresolve(path);
854             path->fp_oper_flags |= FIB_PATH_OPER_FLAG_DROP;
855         }
856         break;
857     case FIB_PATH_TYPE_DEAG:
858         /*
859          * FIXME When VRF delete is allowed this will need a poke.
860          */
861     case FIB_PATH_TYPE_SPECIAL:
862     case FIB_PATH_TYPE_RECEIVE:
863     case FIB_PATH_TYPE_EXCLUSIVE:
864         /*
865          * these path types have no parents. so to be
866          * walked from one is unexpected.
867          */
868         ASSERT(0);
869         break;
870     }
871
872     /*
873      * propagate the backwalk further to the path-list
874      */
875     fib_path_list_back_walk(path->fp_pl_index, ctx);
876
877     return (FIB_NODE_BACK_WALK_CONTINUE);
878 }
879
880 static void
881 fib_path_memory_show (void)
882 {
883     fib_show_memory_usage("Path",
884                           pool_elts(fib_path_pool),
885                           pool_len(fib_path_pool),
886                           sizeof(fib_path_t));
887 }
888
889 /*
890  * The FIB path's graph node virtual function table
891  */
892 static const fib_node_vft_t fib_path_vft = {
893     .fnv_get = fib_path_get_node,
894     .fnv_last_lock = fib_path_last_lock_gone,
895     .fnv_back_walk = fib_path_back_walk_notify,
896     .fnv_mem_show = fib_path_memory_show,
897 };
898
899 static fib_path_cfg_flags_t
900 fib_path_route_flags_to_cfg_flags (const fib_route_path_t *rpath)
901 {
902     fib_path_cfg_flags_t cfg_flags = FIB_PATH_CFG_FLAG_NONE;
903
904     if (rpath->frp_flags & FIB_ROUTE_PATH_RESOLVE_VIA_HOST)
905         cfg_flags |= FIB_PATH_CFG_FLAG_RESOLVE_HOST;
906     if (rpath->frp_flags & FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED)
907         cfg_flags |= FIB_PATH_CFG_FLAG_RESOLVE_ATTACHED;
908
909     return (cfg_flags);
910 }
911
912 /*
913  * fib_path_create
914  *
915  * Create and initialise a new path object.
916  * return the index of the path.
917  */
918 fib_node_index_t
919 fib_path_create (fib_node_index_t pl_index,
920                  fib_protocol_t nh_proto,
921                  fib_path_cfg_flags_t flags,
922                  const fib_route_path_t *rpath)
923 {
924     fib_path_t *path;
925
926     pool_get(fib_path_pool, path);
927     memset(path, 0, sizeof(*path));
928
929     fib_node_init(&path->fp_node,
930                   FIB_NODE_TYPE_PATH);
931
932     dpo_reset(&path->fp_dpo);
933     path->fp_pl_index = pl_index;
934     path->fp_nh_proto = nh_proto;
935     path->fp_via_fib = FIB_NODE_INDEX_INVALID;
936     path->fp_weight = rpath->frp_weight;
937     path->fp_cfg_flags = flags;
938     path->fp_cfg_flags |= fib_path_route_flags_to_cfg_flags(rpath);
939
940     /*
941      * deduce the path's tpye from the parementers and save what is needed.
942      */
943     if (~0 != rpath->frp_sw_if_index)
944     {
945         if (flags & FIB_PATH_CFG_FLAG_LOCAL)
946         {
947             path->fp_type = FIB_PATH_TYPE_RECEIVE;
948             path->receive.fp_interface = rpath->frp_sw_if_index;
949             path->receive.fp_addr = rpath->frp_addr;
950         }
951         else
952         {
953             if (ip46_address_is_zero(&rpath->frp_addr))
954             {
955                 path->fp_type = FIB_PATH_TYPE_ATTACHED;
956                 path->attached.fp_interface = rpath->frp_sw_if_index;
957             }
958             else
959             {
960                 path->fp_type = FIB_PATH_TYPE_ATTACHED_NEXT_HOP;
961                 path->attached_next_hop.fp_interface = rpath->frp_sw_if_index;
962                 path->attached_next_hop.fp_nh = rpath->frp_addr;
963             }
964         }
965     }
966     else
967     {
968         if (ip46_address_is_zero(&rpath->frp_addr))
969         {
970             if (~0 == rpath->frp_fib_index)
971             {
972                 path->fp_type = FIB_PATH_TYPE_SPECIAL;
973             }
974             else
975             {
976                 path->fp_type = FIB_PATH_TYPE_DEAG;
977                 path->deag.fp_tbl_id = rpath->frp_fib_index;
978             }           
979         }
980         else
981         {
982             path->fp_type = FIB_PATH_TYPE_RECURSIVE;
983             path->recursive.fp_nh = rpath->frp_addr;
984             path->recursive.fp_tbl_id = rpath->frp_fib_index;
985         }
986     }
987
988     FIB_PATH_DBG(path, "create");
989
990     return (fib_path_get_index(path));
991 }
992
993 /*
994  * fib_path_create_special
995  *
996  * Create and initialise a new path object.
997  * return the index of the path.
998  */
999 fib_node_index_t
1000 fib_path_create_special (fib_node_index_t pl_index,
1001                          fib_protocol_t nh_proto,
1002                          fib_path_cfg_flags_t flags,
1003                          const dpo_id_t *dpo)
1004 {
1005     fib_path_t *path;
1006
1007     pool_get(fib_path_pool, path);
1008     memset(path, 0, sizeof(*path));
1009
1010     fib_node_init(&path->fp_node,
1011                   FIB_NODE_TYPE_PATH);
1012     dpo_reset(&path->fp_dpo);
1013
1014     path->fp_pl_index = pl_index;
1015     path->fp_weight = 1;
1016     path->fp_nh_proto = nh_proto;
1017     path->fp_via_fib = FIB_NODE_INDEX_INVALID;
1018     path->fp_cfg_flags = flags;
1019
1020     if (FIB_PATH_CFG_FLAG_DROP & flags)
1021     {
1022         path->fp_type = FIB_PATH_TYPE_SPECIAL;
1023     }
1024     else if (FIB_PATH_CFG_FLAG_LOCAL & flags)
1025     {
1026         path->fp_type = FIB_PATH_TYPE_RECEIVE;
1027         path->attached.fp_interface = FIB_NODE_INDEX_INVALID;
1028     }
1029     else
1030     {
1031         path->fp_type = FIB_PATH_TYPE_EXCLUSIVE;
1032         ASSERT(NULL != dpo);
1033         dpo_copy(&path->exclusive.fp_ex_dpo, dpo);
1034     }
1035
1036     return (fib_path_get_index(path));
1037 }
1038
1039 /*
1040  * fib_path_copy
1041  *
1042  * Copy a path. return index of new path.
1043  */
1044 fib_node_index_t
1045 fib_path_copy (fib_node_index_t path_index,
1046                fib_node_index_t path_list_index)
1047 {
1048     fib_path_t *path, *orig_path;
1049
1050     pool_get(fib_path_pool, path);
1051
1052     orig_path = fib_path_get(path_index);
1053     ASSERT(NULL != orig_path);
1054
1055     memcpy(path, orig_path, sizeof(*path));
1056
1057     FIB_PATH_DBG(path, "create-copy:%d", path_index);
1058
1059     /*
1060      * reset the dynamic section
1061      */
1062     fib_node_init(&path->fp_node, FIB_NODE_TYPE_PATH);
1063     path->fp_oper_flags     = FIB_PATH_OPER_FLAG_NONE;
1064     path->fp_pl_index  = path_list_index;
1065     path->fp_via_fib   = FIB_NODE_INDEX_INVALID;
1066     memset(&path->fp_dpo, 0, sizeof(path->fp_dpo));
1067     dpo_reset(&path->fp_dpo);
1068
1069     return (fib_path_get_index(path));
1070 }
1071
1072 /*
1073  * fib_path_destroy
1074  *
1075  * destroy a path that is no longer required
1076  */
1077 void
1078 fib_path_destroy (fib_node_index_t path_index)
1079 {
1080     fib_path_t *path;
1081
1082     path = fib_path_get(path_index);
1083
1084     ASSERT(NULL != path);
1085     FIB_PATH_DBG(path, "destroy");
1086
1087     fib_path_unresolve(path);
1088
1089     fib_node_deinit(&path->fp_node);
1090     pool_put(fib_path_pool, path);
1091 }
1092
1093 /*
1094  * fib_path_destroy
1095  *
1096  * destroy a path that is no longer required
1097  */
1098 uword
1099 fib_path_hash (fib_node_index_t path_index)
1100 {
1101     fib_path_t *path;
1102
1103     path = fib_path_get(path_index);
1104
1105     return (hash_memory(STRUCT_MARK_PTR(path, path_hash_start),
1106                         (STRUCT_OFFSET_OF(fib_path_t, path_hash_end) -
1107                          STRUCT_OFFSET_OF(fib_path_t, path_hash_start)),
1108                         0));
1109 }
1110
1111 /*
1112  * fib_path_cmp_i
1113  *
1114  * Compare two paths for equivalence.
1115  */
1116 static int
1117 fib_path_cmp_i (const fib_path_t *path1,
1118                 const fib_path_t *path2)
1119 {
1120     int res;
1121
1122     res = 1;
1123
1124     /*
1125      * paths of different types and protocol are not equal.
1126      * different weights only are the same path.
1127      */
1128     if (path1->fp_type != path2->fp_type)
1129     {
1130         res = (path1->fp_type - path2->fp_type);
1131     }
1132     if (path1->fp_nh_proto != path2->fp_nh_proto)
1133     {
1134         res = (path1->fp_nh_proto - path2->fp_nh_proto);
1135     }
1136     else
1137     {
1138         /*
1139          * both paths are of the same type.
1140          * consider each type and its attributes in turn.
1141          */
1142         switch (path1->fp_type)
1143         {
1144         case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
1145             res = ip46_address_cmp(&path1->attached_next_hop.fp_nh,
1146                                    &path2->attached_next_hop.fp_nh);
1147             if (0 == res) {
1148                 res = vnet_sw_interface_compare(
1149                           vnet_get_main(),
1150                           path1->attached_next_hop.fp_interface,
1151                           path2->attached_next_hop.fp_interface);
1152             }
1153             break;
1154         case FIB_PATH_TYPE_ATTACHED:
1155             res = vnet_sw_interface_compare(
1156                       vnet_get_main(),
1157                       path1->attached.fp_interface,
1158                       path2->attached.fp_interface);
1159             break;
1160         case FIB_PATH_TYPE_RECURSIVE:
1161             res = ip46_address_cmp(&path1->recursive.fp_nh,
1162                                    &path2->recursive.fp_nh);
1163  
1164             if (0 == res)
1165             {
1166                 res = (path1->recursive.fp_tbl_id - path2->recursive.fp_tbl_id);
1167             }
1168             break;
1169         case FIB_PATH_TYPE_DEAG:
1170             res = (path1->deag.fp_tbl_id - path2->deag.fp_tbl_id);
1171             break;
1172         case FIB_PATH_TYPE_SPECIAL:
1173         case FIB_PATH_TYPE_RECEIVE:
1174         case FIB_PATH_TYPE_EXCLUSIVE:
1175             res = 0;
1176             break;
1177         }
1178     }
1179     return (res);
1180 }
1181
1182 /*
1183  * fib_path_cmp_for_sort
1184  *
1185  * Compare two paths for equivalence. Used during path sorting.
1186  * As usual 0 means equal.
1187  */
1188 int
1189 fib_path_cmp_for_sort (void * v1,
1190                        void * v2)
1191 {
1192     fib_node_index_t *pi1 = v1, *pi2 = v2;
1193     fib_path_t *path1, *path2;
1194
1195     path1 = fib_path_get(*pi1);
1196     path2 = fib_path_get(*pi2);
1197
1198     return (fib_path_cmp_i(path1, path2));
1199 }
1200
1201 /*
1202  * fib_path_cmp
1203  *
1204  * Compare two paths for equivalence.
1205  */
1206 int
1207 fib_path_cmp (fib_node_index_t pi1,
1208               fib_node_index_t pi2)
1209 {
1210     fib_path_t *path1, *path2;
1211
1212     path1 = fib_path_get(pi1);
1213     path2 = fib_path_get(pi2);
1214
1215     return (fib_path_cmp_i(path1, path2));
1216 }
1217
1218 int
1219 fib_path_cmp_w_route_path (fib_node_index_t path_index,
1220                            const fib_route_path_t *rpath)
1221 {
1222     fib_path_t *path;
1223     int res;
1224
1225     path = fib_path_get(path_index);
1226
1227     res = 1;
1228
1229     if (path->fp_weight != rpath->frp_weight)
1230     {
1231         res = (path->fp_weight - rpath->frp_weight);
1232     }
1233     else
1234     {
1235         /*
1236          * both paths are of the same type.
1237          * consider each type and its attributes in turn.
1238          */
1239         switch (path->fp_type)
1240         {
1241         case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
1242             res = ip46_address_cmp(&path->attached_next_hop.fp_nh,
1243                                    &rpath->frp_addr);
1244             if (0 == res)
1245             {
1246                 res = vnet_sw_interface_compare(
1247                           vnet_get_main(),
1248                           path->attached_next_hop.fp_interface,
1249                           rpath->frp_sw_if_index);
1250             }
1251             break;
1252         case FIB_PATH_TYPE_ATTACHED:
1253             res = vnet_sw_interface_compare(
1254                       vnet_get_main(),
1255                       path->attached.fp_interface,
1256                       rpath->frp_sw_if_index);
1257             break;
1258         case FIB_PATH_TYPE_RECURSIVE:
1259             res = ip46_address_cmp(&path->recursive.fp_nh,
1260                                    &rpath->frp_addr);
1261  
1262             if (0 == res)
1263             {
1264                 res = (path->recursive.fp_tbl_id - rpath->frp_fib_index);
1265             }
1266             break;
1267         case FIB_PATH_TYPE_DEAG:
1268             res = (path->deag.fp_tbl_id - rpath->frp_fib_index);
1269             break;
1270         case FIB_PATH_TYPE_SPECIAL:
1271         case FIB_PATH_TYPE_RECEIVE:
1272         case FIB_PATH_TYPE_EXCLUSIVE:
1273             res = 0;
1274             break;
1275         }
1276     }
1277     return (res);
1278 }
1279
1280 /*
1281  * fib_path_recursive_loop_detect
1282  *
1283  * A forward walk of the FIB object graph to detect for a cycle/loop. This
1284  * walk is initiated when an entry is linking to a new path list or from an old.
1285  * The entry vector passed contains all the FIB entrys that are children of this
1286  * path (it is all the entries encountered on the walk so far). If this vector
1287  * contains the entry this path resolve via, then a loop is about to form.
1288  * The loop must be allowed to form, since we need the dependencies in place
1289  * so that we can track when the loop breaks.
1290  * However, we MUST not produce a loop in the forwarding graph (else packets
1291  * would loop around the switch path until the loop breaks), so we mark recursive
1292  * paths as looped so that they do not contribute forwarding information.
1293  * By marking the path as looped, an etry such as;
1294  *    X/Y
1295  *     via a.a.a.a (looped)
1296  *     via b.b.b.b (not looped)
1297  * can still forward using the info provided by b.b.b.b only
1298  */
1299 int
1300 fib_path_recursive_loop_detect (fib_node_index_t path_index,
1301                                 fib_node_index_t **entry_indicies)
1302 {
1303     fib_path_t *path;
1304
1305     path = fib_path_get(path_index);
1306
1307     /*
1308      * the forced drop path is never looped, cos it is never resolved.
1309      */
1310     if (fib_path_is_permanent_drop(path))
1311     {
1312         return (0);
1313     }
1314
1315     switch (path->fp_type)
1316     {
1317     case FIB_PATH_TYPE_RECURSIVE:
1318     {
1319         fib_node_index_t *entry_index, *entries;
1320         int looped = 0;
1321         entries = *entry_indicies;
1322
1323         vec_foreach(entry_index, entries) {
1324             if (*entry_index == path->fp_via_fib)
1325             {
1326                 /*
1327                  * the entry that is about to link to this path-list (or
1328                  * one of this path-list's children) is the same entry that
1329                  * this recursive path resolves through. this is a cycle.
1330                  * abort the walk.
1331                  */
1332                 looped = 1;
1333                 break;
1334             }
1335         }
1336
1337         if (looped)
1338         {
1339             FIB_PATH_DBG(path, "recursive loop formed");
1340             path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RECURSIVE_LOOP;
1341
1342             dpo_copy(&path->fp_dpo,
1343                     drop_dpo_get(fib_proto_to_dpo(path->fp_nh_proto)));
1344         }
1345         else
1346         {
1347             /*
1348              * no loop here yet. keep forward walking the graph.
1349              */     
1350             if (fib_entry_recursive_loop_detect(path->fp_via_fib, entry_indicies))
1351             {
1352                 FIB_PATH_DBG(path, "recursive loop formed");
1353                 path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RECURSIVE_LOOP;
1354             }
1355             else
1356             {
1357                 FIB_PATH_DBG(path, "recursive loop cleared");
1358                 path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RECURSIVE_LOOP;
1359             }
1360         }
1361         break;
1362     }
1363     case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
1364     case FIB_PATH_TYPE_ATTACHED:
1365     case FIB_PATH_TYPE_SPECIAL:
1366     case FIB_PATH_TYPE_DEAG:
1367     case FIB_PATH_TYPE_RECEIVE:
1368     case FIB_PATH_TYPE_EXCLUSIVE:
1369         /*
1370          * these path types cannot be part of a loop, since they are the leaves
1371          * of the graph.
1372          */
1373         break;
1374     }
1375
1376     return (fib_path_is_looped(path_index));
1377 }
1378
1379 int
1380 fib_path_resolve (fib_node_index_t path_index)
1381 {
1382     fib_path_t *path;
1383
1384     path = fib_path_get(path_index);
1385
1386     /*
1387      * hope for the best.
1388      */
1389     path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED;
1390
1391     /*
1392      * the forced drop path resolves via the drop adj
1393      */
1394     if (fib_path_is_permanent_drop(path))
1395     {
1396         dpo_copy(&path->fp_dpo,
1397                  drop_dpo_get(fib_proto_to_dpo(path->fp_nh_proto)));
1398         path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
1399         return (fib_path_is_resolved(path_index));
1400     }
1401
1402     switch (path->fp_type)
1403     {
1404     case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
1405         fib_path_attached_next_hop_set(path);
1406         break;
1407     case FIB_PATH_TYPE_ATTACHED:
1408         /*
1409          * path->attached.fp_interface
1410          */
1411         if (!vnet_sw_interface_is_admin_up(vnet_get_main(),
1412                                            path->attached.fp_interface))
1413         {
1414             path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
1415         }
1416         if (vnet_sw_interface_is_p2p(vnet_get_main(),
1417                                      path->attached.fp_interface))
1418         {
1419             /*
1420              * point-2-point interfaces do not require a glean, since
1421              * there is nothing to ARP. Install a rewrite/nbr adj instead
1422              */
1423             dpo_set(&path->fp_dpo,
1424                     DPO_ADJACENCY,
1425                     fib_proto_to_dpo(path->fp_nh_proto),
1426                     adj_nbr_add_or_lock(
1427                         path->fp_nh_proto,
1428                         fib_proto_to_link(path->fp_nh_proto),
1429                         &zero_addr,
1430                         path->attached.fp_interface));
1431         }
1432         else
1433         {
1434             dpo_set(&path->fp_dpo,
1435                     DPO_ADJACENCY_GLEAN,
1436                     fib_proto_to_dpo(path->fp_nh_proto),
1437                     adj_glean_add_or_lock(path->fp_nh_proto,
1438                                           path->attached.fp_interface,
1439                                           NULL));
1440         }
1441         /*
1442          * become a child of the adjacency so we receive updates
1443          * when the interface state changes
1444          */
1445         path->fp_sibling = adj_child_add(path->fp_dpo.dpoi_index,
1446                                          FIB_NODE_TYPE_PATH,
1447                                          fib_path_get_index(path));
1448
1449         break;
1450     case FIB_PATH_TYPE_RECURSIVE:
1451     {
1452         /*
1453          * Create a RR source entry in the table for the address
1454          * that this path recurses through.
1455          * This resolve action is recursive, hence we may create
1456          * more paths in the process. more creates mean maybe realloc
1457          * of this path.
1458          */
1459         fib_node_index_t fei;
1460         fib_prefix_t pfx;
1461
1462         ASSERT(FIB_NODE_INDEX_INVALID == path->fp_via_fib);
1463
1464         fib_prefix_from_ip46_addr(&path->recursive.fp_nh, &pfx);
1465
1466         fei = fib_table_entry_special_add(path->recursive.fp_tbl_id,
1467                                           &pfx,
1468                                           FIB_SOURCE_RR,
1469                                           FIB_ENTRY_FLAG_NONE,
1470                                           ADJ_INDEX_INVALID);
1471
1472         path = fib_path_get(path_index);
1473         path->fp_via_fib = fei;
1474
1475         /*
1476          * become a dependent child of the entry so the path is 
1477          * informed when the forwarding for the entry changes.
1478          */
1479         path->fp_sibling = fib_entry_child_add(path->fp_via_fib,
1480                                                FIB_NODE_TYPE_PATH,
1481                                                fib_path_get_index(path));
1482
1483         /*
1484          * create and configure the IP DPO
1485          */
1486         fib_path_recursive_adj_update(
1487             path,
1488             fib_path_proto_to_chain_type(path->fp_nh_proto),
1489             &path->fp_dpo);
1490
1491         break;
1492     }
1493     case FIB_PATH_TYPE_SPECIAL:
1494         /*
1495          * Resolve via the drop
1496          */
1497         dpo_copy(&path->fp_dpo,
1498                  drop_dpo_get(fib_proto_to_dpo(path->fp_nh_proto)));
1499         break;
1500     case FIB_PATH_TYPE_DEAG:
1501         /*
1502          * Resolve via a lookup DPO.
1503          * FIXME. control plane should add routes with a table ID
1504          */
1505         lookup_dpo_add_or_lock_w_fib_index(path->deag.fp_tbl_id,
1506                                           fib_proto_to_dpo(path->fp_nh_proto),
1507                                           LOOKUP_INPUT_DST_ADDR,
1508                                           LOOKUP_TABLE_FROM_CONFIG,
1509                                           &path->fp_dpo);
1510         break;
1511     case FIB_PATH_TYPE_RECEIVE:
1512         /*
1513          * Resolve via a receive DPO.
1514          */
1515         receive_dpo_add_or_lock(fib_proto_to_dpo(path->fp_nh_proto),
1516                                 path->receive.fp_interface,
1517                                 &path->receive.fp_addr,
1518                                 &path->fp_dpo);
1519         break;
1520     case FIB_PATH_TYPE_EXCLUSIVE:
1521         /*
1522          * Resolve via the user provided DPO
1523          */
1524         dpo_copy(&path->fp_dpo, &path->exclusive.fp_ex_dpo);
1525         break;
1526     }
1527
1528     return (fib_path_is_resolved(path_index));
1529 }
1530
1531 u32
1532 fib_path_get_resolving_interface (fib_node_index_t path_index)
1533 {
1534     fib_path_t *path;
1535
1536     path = fib_path_get(path_index);
1537
1538     switch (path->fp_type)
1539     {
1540     case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
1541         return (path->attached_next_hop.fp_interface);
1542     case FIB_PATH_TYPE_ATTACHED:
1543         return (path->attached.fp_interface);
1544     case FIB_PATH_TYPE_RECEIVE:
1545         return (path->receive.fp_interface);
1546     case FIB_PATH_TYPE_RECURSIVE:
1547         return (fib_entry_get_resolving_interface(path->fp_via_fib));    
1548     case FIB_PATH_TYPE_SPECIAL:
1549     case FIB_PATH_TYPE_DEAG:
1550     case FIB_PATH_TYPE_EXCLUSIVE:
1551         break;
1552     }
1553     return (~0);
1554 }
1555
1556 adj_index_t
1557 fib_path_get_adj (fib_node_index_t path_index)
1558 {
1559     fib_path_t *path;
1560
1561     path = fib_path_get(path_index);
1562
1563     ASSERT(dpo_is_adj(&path->fp_dpo));
1564     if (dpo_is_adj(&path->fp_dpo))
1565     {
1566         return (path->fp_dpo.dpoi_index);
1567     }
1568     return (ADJ_INDEX_INVALID);
1569 }
1570
1571 int
1572 fib_path_get_weight (fib_node_index_t path_index)
1573 {
1574     fib_path_t *path;
1575
1576     path = fib_path_get(path_index);
1577
1578     ASSERT(path);
1579
1580     return (path->fp_weight);
1581 }
1582
1583 /**
1584  * @brief Contribute the path's adjacency to the list passed.
1585  * By calling this function over all paths, recursively, a child
1586  * can construct its full set of forwarding adjacencies, and hence its
1587  * uRPF list.
1588  */
1589 void
1590 fib_path_contribute_urpf (fib_node_index_t path_index,
1591                           index_t urpf)
1592 {
1593     fib_path_t *path;
1594
1595     if (!fib_path_is_resolved(path_index))
1596         return;
1597
1598     path = fib_path_get(path_index);
1599
1600     switch (path->fp_type)
1601     {
1602     case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
1603         fib_urpf_list_append(urpf, path->attached_next_hop.fp_interface);
1604         break;
1605
1606     case FIB_PATH_TYPE_ATTACHED:
1607         fib_urpf_list_append(urpf, path->attached.fp_interface);
1608         break;
1609
1610     case FIB_PATH_TYPE_RECURSIVE:
1611         fib_entry_contribute_urpf(path->fp_via_fib, urpf);
1612         break;
1613
1614     case FIB_PATH_TYPE_EXCLUSIVE:
1615     case FIB_PATH_TYPE_SPECIAL:
1616         /*
1617          * these path types may link to an adj, if that's what
1618          * the clinet gave
1619          */
1620         if (dpo_is_adj(&path->fp_dpo))
1621         {
1622             ip_adjacency_t *adj;
1623
1624             adj = adj_get(path->fp_dpo.dpoi_index);
1625
1626             fib_urpf_list_append(urpf, adj->rewrite_header.sw_if_index);
1627         }
1628         break;
1629
1630     case FIB_PATH_TYPE_DEAG:
1631     case FIB_PATH_TYPE_RECEIVE:
1632         /*
1633          * these path types don't link to an adj
1634          */
1635         break;
1636     }
1637 }
1638
1639 void
1640 fib_path_contribute_forwarding (fib_node_index_t path_index,
1641                                 fib_forward_chain_type_t fct,
1642                                 dpo_id_t *dpo)
1643 {
1644     fib_path_t *path;
1645
1646     path = fib_path_get(path_index);
1647
1648     ASSERT(path);
1649     ASSERT(FIB_FORW_CHAIN_TYPE_MPLS_EOS != fct);
1650
1651     FIB_PATH_DBG(path, "contribute");
1652
1653     /*
1654      * The DPO stored in the path was created when the path was resolved.
1655      * This then represents the path's 'native' protocol; IP.
1656      * For all others will need to go find something else.
1657      */
1658     if (fib_path_proto_to_chain_type(path->fp_nh_proto) == fct)
1659     {
1660         dpo_copy(dpo, &path->fp_dpo);
1661     }
1662     else
1663     {
1664         switch (path->fp_type)
1665         {
1666         case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
1667             switch (fct)
1668             {
1669             case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
1670             case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
1671             case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
1672             case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
1673             case FIB_FORW_CHAIN_TYPE_ETHERNET:
1674             {
1675                 adj_index_t ai;
1676
1677                 /*
1678                  * get a MPLS link type adj.
1679                  */
1680                 ai = fib_path_attached_next_hop_get_adj(
1681                          path,
1682                          fib_forw_chain_type_to_link_type(fct));
1683                 dpo_set(dpo, DPO_ADJACENCY,
1684                         fib_forw_chain_type_to_dpo_proto(fct), ai);
1685                 adj_unlock(ai);
1686
1687                 break;
1688             }
1689             }
1690             break;
1691         case FIB_PATH_TYPE_RECURSIVE:
1692             switch (fct)
1693             {
1694             case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
1695             case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
1696             case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
1697                 /*
1698                  * Assume that EOS and IP forwarding is the same.
1699                  * revisit for ieBGP
1700                  */
1701                 dpo_copy(dpo, &path->fp_dpo);
1702                 break;
1703             case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
1704                 fib_path_recursive_adj_update(path, fct, dpo);
1705                 break;
1706             case FIB_FORW_CHAIN_TYPE_ETHERNET:
1707                 ASSERT(0);
1708                 break;
1709             }
1710             break;
1711         case FIB_PATH_TYPE_DEAG:
1712             switch (fct)
1713             {
1714             case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
1715                 lookup_dpo_add_or_lock_w_table_id(MPLS_FIB_DEFAULT_TABLE_ID,
1716                                                   DPO_PROTO_MPLS,
1717                                                   LOOKUP_INPUT_DST_ADDR,
1718                                                   LOOKUP_TABLE_FROM_CONFIG,
1719                                                   dpo);
1720                 break;
1721             case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
1722             case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
1723             case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
1724                 dpo_copy(dpo, &path->fp_dpo);
1725                 break;          
1726             case FIB_FORW_CHAIN_TYPE_ETHERNET:
1727                 ASSERT(0);
1728                 break;
1729             }
1730             break;
1731         case FIB_PATH_TYPE_EXCLUSIVE:
1732             dpo_copy(dpo, &path->exclusive.fp_ex_dpo);
1733             break;
1734         case FIB_PATH_TYPE_ATTACHED:
1735         case FIB_PATH_TYPE_RECEIVE:
1736         case FIB_PATH_TYPE_SPECIAL:
1737             ASSERT(0);
1738             break;
1739         }
1740
1741     }
1742 }
1743
1744 load_balance_path_t *
1745 fib_path_append_nh_for_multipath_hash (fib_node_index_t path_index,
1746                                        fib_forward_chain_type_t fct,
1747                                        load_balance_path_t *hash_key)
1748 {
1749     load_balance_path_t *mnh;
1750     fib_path_t *path;
1751
1752     path = fib_path_get(path_index);
1753
1754     ASSERT(path);
1755
1756     if (fib_path_is_resolved(path_index))
1757     {
1758         vec_add2(hash_key, mnh, 1);
1759
1760         mnh->path_weight = path->fp_weight;
1761         mnh->path_index = path_index;
1762         fib_path_contribute_forwarding(path_index, fct, &mnh->path_dpo);
1763     }
1764
1765     return (hash_key);
1766 }
1767
1768 int
1769 fib_path_is_recursive (fib_node_index_t path_index)
1770 {
1771     fib_path_t *path;
1772
1773     path = fib_path_get(path_index);
1774
1775     return (FIB_PATH_TYPE_RECURSIVE == path->fp_type);
1776 }
1777
1778 int
1779 fib_path_is_exclusive (fib_node_index_t path_index)
1780 {
1781     fib_path_t *path;
1782
1783     path = fib_path_get(path_index);
1784
1785     return (FIB_PATH_TYPE_EXCLUSIVE == path->fp_type);
1786 }
1787
1788 int
1789 fib_path_is_deag (fib_node_index_t path_index)
1790 {
1791     fib_path_t *path;
1792
1793     path = fib_path_get(path_index);
1794
1795     return (FIB_PATH_TYPE_DEAG == path->fp_type);
1796 }
1797
1798 int
1799 fib_path_is_resolved (fib_node_index_t path_index)
1800 {
1801     fib_path_t *path;
1802
1803     path = fib_path_get(path_index);
1804
1805     return (dpo_id_is_valid(&path->fp_dpo) &&
1806             (path->fp_oper_flags & FIB_PATH_OPER_FLAG_RESOLVED) &&
1807             !fib_path_is_looped(path_index) &&
1808             !fib_path_is_permanent_drop(path));
1809 }
1810
1811 int
1812 fib_path_is_looped (fib_node_index_t path_index)
1813 {
1814     fib_path_t *path;
1815
1816     path = fib_path_get(path_index);
1817
1818     return (path->fp_oper_flags & FIB_PATH_OPER_FLAG_RECURSIVE_LOOP);
1819 }
1820
1821 int
1822 fib_path_encode (fib_node_index_t path_list_index,
1823                  fib_node_index_t path_index,
1824                  void *ctx)
1825 {
1826     fib_route_path_encode_t **api_rpaths = ctx;
1827     fib_route_path_encode_t *api_rpath;
1828     fib_path_t *path;
1829
1830     path = fib_path_get(path_index);
1831     if (!path)
1832       return (0);
1833     vec_add2(*api_rpaths, api_rpath, 1);
1834     api_rpath->rpath.frp_weight = path->fp_weight;
1835     api_rpath->rpath.frp_proto = path->fp_nh_proto;
1836     api_rpath->rpath.frp_sw_if_index = ~0;
1837     api_rpath->dpo = path->exclusive.fp_ex_dpo;
1838     switch (path->fp_type)
1839       {
1840       case FIB_PATH_TYPE_RECEIVE:
1841         api_rpath->rpath.frp_addr = path->receive.fp_addr;
1842         api_rpath->rpath.frp_sw_if_index = path->receive.fp_interface;
1843         break;
1844       case FIB_PATH_TYPE_ATTACHED:
1845         api_rpath->rpath.frp_sw_if_index = path->attached.fp_interface;
1846         break;
1847       case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
1848         api_rpath->rpath.frp_sw_if_index = path->attached_next_hop.fp_interface;
1849         api_rpath->rpath.frp_addr = path->attached_next_hop.fp_nh;
1850         break;
1851       case FIB_PATH_TYPE_SPECIAL:
1852         break;
1853       case FIB_PATH_TYPE_DEAG:
1854         break;
1855       case FIB_PATH_TYPE_RECURSIVE:
1856         api_rpath->rpath.frp_addr = path->recursive.fp_nh;
1857         break;
1858       default:
1859         break;
1860       }
1861     return (1);
1862 }
1863
1864 void
1865 fib_path_module_init (void)
1866 {
1867     fib_node_register_type (FIB_NODE_TYPE_PATH, &fib_path_vft);
1868 }
1869
1870 static clib_error_t *
1871 show_fib_path_command (vlib_main_t * vm,
1872                         unformat_input_t * input,
1873                         vlib_cli_command_t * cmd)
1874 {
1875     fib_node_index_t pi;
1876     fib_path_t *path;
1877
1878     if (unformat (input, "%d", &pi))
1879     {
1880         /*
1881          * show one in detail
1882          */
1883         if (!pool_is_free_index(fib_path_pool, pi))
1884         {
1885             path = fib_path_get(pi);
1886             u8 *s = fib_path_format(pi, NULL);
1887             s = format(s, "children:");
1888             s = fib_node_children_format(path->fp_node.fn_children, s);
1889             vlib_cli_output (vm, "%s", s);
1890             vec_free(s);
1891         }
1892         else
1893         {
1894             vlib_cli_output (vm, "path %d invalid", pi);
1895         }
1896     }
1897     else
1898     {
1899         vlib_cli_output (vm, "FIB Paths");
1900         pool_foreach(path, fib_path_pool,
1901         ({
1902             vlib_cli_output (vm, "%U", format_fib_path, path);
1903         }));
1904     }
1905
1906     return (NULL);
1907 }
1908
1909 VLIB_CLI_COMMAND (show_fib_path, static) = {
1910   .path = "show fib paths",
1911   .function = show_fib_path_command,
1912   .short_help = "show fib paths",
1913 };