LCOV - code coverage report
Current view: top level - vnet/fib - fib_path.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 898 1027 87.4 %
Date: 2023-10-26 01:39:38 Functions: 47 49 95.9 %

          Line data    Source code
       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             : #include <vnet/dpo/interface_rx_dpo.h>
      25             : #include <vnet/dpo/mpls_disposition.h>
      26             : #include <vnet/dpo/dvr_dpo.h>
      27             : #include <vnet/dpo/ip_null_dpo.h>
      28             : #include <vnet/dpo/classify_dpo.h>
      29             : #include <vnet/dpo/pw_cw.h>
      30             : 
      31             : #include <vnet/adj/adj.h>
      32             : #include <vnet/adj/adj_mcast.h>
      33             : 
      34             : #include <vnet/fib/fib_path.h>
      35             : #include <vnet/fib/fib_node.h>
      36             : #include <vnet/fib/fib_table.h>
      37             : #include <vnet/fib/fib_entry.h>
      38             : #include <vnet/fib/fib_path_list.h>
      39             : #include <vnet/fib/fib_internal.h>
      40             : #include <vnet/fib/fib_urpf_list.h>
      41             : #include <vnet/fib/mpls_fib.h>
      42             : #include <vnet/fib/fib_path_ext.h>
      43             : #include <vnet/udp/udp_encap.h>
      44             : #include <vnet/bier/bier_fmask.h>
      45             : #include <vnet/bier/bier_table.h>
      46             : #include <vnet/bier/bier_imp.h>
      47             : #include <vnet/bier/bier_disp_table.h>
      48             : 
      49             : /**
      50             :  * Enurmeration of path types
      51             :  */
      52             : typedef enum fib_path_type_t_ {
      53             :     /**
      54             :      * Marker. Add new types after this one.
      55             :      */
      56             :     FIB_PATH_TYPE_FIRST = 0,
      57             :     /**
      58             :      * Attached-nexthop. An interface and a nexthop are known.
      59             :      */
      60             :     FIB_PATH_TYPE_ATTACHED_NEXT_HOP = FIB_PATH_TYPE_FIRST,
      61             :     /**
      62             :      * attached. Only the interface is known.
      63             :      */
      64             :     FIB_PATH_TYPE_ATTACHED,
      65             :     /**
      66             :      * recursive. Only the next-hop is known.
      67             :      */
      68             :     FIB_PATH_TYPE_RECURSIVE,
      69             :     /**
      70             :      * special. nothing is known. so we drop.
      71             :      */
      72             :     FIB_PATH_TYPE_SPECIAL,
      73             :     /**
      74             :      * exclusive. user provided adj.
      75             :      */
      76             :     FIB_PATH_TYPE_EXCLUSIVE,
      77             :     /**
      78             :      * deag. Link to a lookup adj in the next table
      79             :      */
      80             :     FIB_PATH_TYPE_DEAG,
      81             :     /**
      82             :      * interface receive.
      83             :      */
      84             :     FIB_PATH_TYPE_INTF_RX,
      85             :     /**
      86             :      * Path resolves via a UDP encap object.
      87             :      */
      88             :     FIB_PATH_TYPE_UDP_ENCAP,
      89             :     /**
      90             :      * receive. it's for-us.
      91             :      */
      92             :     FIB_PATH_TYPE_RECEIVE,
      93             :     /**
      94             :      * bier-imp. it's via a BIER imposition.
      95             :      */
      96             :     FIB_PATH_TYPE_BIER_IMP,
      97             :     /**
      98             :      * bier-fmask. it's via a BIER ECMP-table.
      99             :      */
     100             :     FIB_PATH_TYPE_BIER_TABLE,
     101             :     /**
     102             :      * bier-fmask. it's via a BIER f-mask.
     103             :      */
     104             :     FIB_PATH_TYPE_BIER_FMASK,
     105             :     /**
     106             :      * via a DVR.
     107             :      */
     108             :     FIB_PATH_TYPE_DVR,
     109             : } __attribute__ ((packed)) fib_path_type_t;
     110             : 
     111             : #define FIB_PATH_TYPES {                                        \
     112             :     [FIB_PATH_TYPE_ATTACHED_NEXT_HOP] = "attached-nexthop",   \
     113             :     [FIB_PATH_TYPE_ATTACHED]          = "attached",           \
     114             :     [FIB_PATH_TYPE_RECURSIVE]         = "recursive",          \
     115             :     [FIB_PATH_TYPE_SPECIAL]           = "special",            \
     116             :     [FIB_PATH_TYPE_EXCLUSIVE]         = "exclusive",          \
     117             :     [FIB_PATH_TYPE_DEAG]              = "deag",                       \
     118             :     [FIB_PATH_TYPE_INTF_RX]           = "intf-rx",            \
     119             :     [FIB_PATH_TYPE_UDP_ENCAP]         = "udp-encap",          \
     120             :     [FIB_PATH_TYPE_RECEIVE]           = "receive",            \
     121             :     [FIB_PATH_TYPE_BIER_IMP]          = "bier-imp",           \
     122             :     [FIB_PATH_TYPE_BIER_TABLE]        = "bier-table",         \
     123             :     [FIB_PATH_TYPE_BIER_FMASK]        = "bier-fmask",         \
     124             :     [FIB_PATH_TYPE_DVR]               = "dvr",                \
     125             : }
     126             : 
     127             : /**
     128             :  * Enurmeration of path operational (i.e. derived) attributes
     129             :  */
     130             : typedef enum fib_path_oper_attribute_t_ {
     131             :     /**
     132             :      * Marker. Add new types after this one.
     133             :      */
     134             :     FIB_PATH_OPER_ATTRIBUTE_FIRST = 0,
     135             :     /**
     136             :      * The path forms part of a recursive loop.
     137             :      */
     138             :     FIB_PATH_OPER_ATTRIBUTE_RECURSIVE_LOOP = FIB_PATH_OPER_ATTRIBUTE_FIRST,
     139             :     /**
     140             :      * The path is resolved
     141             :      */
     142             :     FIB_PATH_OPER_ATTRIBUTE_RESOLVED,
     143             :     /**
     144             :      * The path has become a permanent drop.
     145             :      */
     146             :     FIB_PATH_OPER_ATTRIBUTE_DROP,
     147             :     /**
     148             :      * Marker. Add new types before this one, then update it.
     149             :      */
     150             :     FIB_PATH_OPER_ATTRIBUTE_LAST = FIB_PATH_OPER_ATTRIBUTE_DROP,
     151             : } __attribute__ ((packed)) fib_path_oper_attribute_t;
     152             : 
     153             : /**
     154             :  * The maximum number of path operational attributes
     155             :  */
     156             : #define FIB_PATH_OPER_ATTRIBUTE_MAX (FIB_PATH_OPER_ATTRIBUTE_LAST + 1)
     157             : 
     158             : #define FIB_PATH_OPER_ATTRIBUTES {                                      \
     159             :     [FIB_PATH_OPER_ATTRIBUTE_RECURSIVE_LOOP] = "recursive-loop",      \
     160             :     [FIB_PATH_OPER_ATTRIBUTE_RESOLVED]       = "resolved",            \
     161             :     [FIB_PATH_OPER_ATTRIBUTE_DROP]           = "drop",                        \
     162             : }
     163             : 
     164             : #define FOR_EACH_FIB_PATH_OPER_ATTRIBUTE(_item) \
     165             :     for (_item = FIB_PATH_OPER_ATTRIBUTE_FIRST; \
     166             :          _item <= FIB_PATH_OPER_ATTRIBUTE_LAST; \
     167             :          _item++)
     168             : 
     169             : /**
     170             :  * Path flags from the attributes
     171             :  */
     172             : typedef enum fib_path_oper_flags_t_ {
     173             :     FIB_PATH_OPER_FLAG_NONE = 0,
     174             :     FIB_PATH_OPER_FLAG_RECURSIVE_LOOP = (1 << FIB_PATH_OPER_ATTRIBUTE_RECURSIVE_LOOP),
     175             :     FIB_PATH_OPER_FLAG_DROP = (1 << FIB_PATH_OPER_ATTRIBUTE_DROP),
     176             :     FIB_PATH_OPER_FLAG_RESOLVED = (1 << FIB_PATH_OPER_ATTRIBUTE_RESOLVED),
     177             : } __attribute__ ((packed)) fib_path_oper_flags_t;
     178             : 
     179             : /**
     180             :  * A FIB path
     181             :  */
     182             : typedef struct fib_path_t_ {
     183             :     /**
     184             :      * A path is a node in the FIB graph.
     185             :      */
     186             :     fib_node_t fp_node;
     187             : 
     188             :     /**
     189             :      * The index of the path-list to which this path belongs
     190             :      */
     191             :     u32 fp_pl_index;
     192             : 
     193             :     /**
     194             :      * This marks the start of the memory area used to hash
     195             :      * the path
     196             :      */
     197             :     STRUCT_MARK(path_hash_start);
     198             : 
     199             :     /**
     200             :      * Configuration Flags
     201             :      */
     202             :     fib_path_cfg_flags_t fp_cfg_flags;
     203             : 
     204             :     /**
     205             :      * The type of the path. This is the selector for the union
     206             :      */
     207             :     fib_path_type_t fp_type;
     208             : 
     209             :     /**
     210             :      * The protocol of the next-hop, i.e. the address family of the
     211             :      * next-hop's address. We can't derive this from the address itself
     212             :      * since the address can be all zeros
     213             :      */
     214             :     dpo_proto_t fp_nh_proto;
     215             : 
     216             :     /**
     217             :      * UCMP [unnormalised] weigth
     218             :      */
     219             :     u8 fp_weight;
     220             : 
     221             :     /**
     222             :      * A path preference. 0 is the best.
     223             :      * Only paths of the best preference, that are 'up', are considered
     224             :      * for forwarding.
     225             :      */
     226             :     u8 fp_preference;
     227             : 
     228             :     /**
     229             :      * per-type union of the data required to resolve the path
     230             :      */
     231             :     union {
     232             :         struct {
     233             :             /**
     234             :              * The next-hop
     235             :              */
     236             :             ip46_address_t fp_nh;
     237             :             /**
     238             :              * The interface
     239             :              */
     240             :             u32 fp_interface;
     241             :         } attached_next_hop;
     242             :         struct {
     243             :             /**
     244             :              * The Connected local address
     245             :              */
     246             :             fib_prefix_t fp_connected;
     247             :             /**
     248             :              * The interface
     249             :              */
     250             :             u32 fp_interface;
     251             :         } attached;
     252             :         struct {
     253             :             union
     254             :             {
     255             :                 /**
     256             :                  * The next-hop
     257             :                  */
     258             :                 ip46_address_t fp_ip;
     259             :                 struct {
     260             :                     /**
     261             :                      * The local label to resolve through.
     262             :                      */
     263             :                     mpls_label_t fp_local_label;
     264             :                     /**
     265             :                      * The EOS bit of the resolving label
     266             :                      */
     267             :                     mpls_eos_bit_t fp_eos;
     268             :                 };
     269             :             } fp_nh;
     270             :             /**
     271             :              * The FIB table index in which to find the next-hop.
     272             :              */
     273             :             fib_node_index_t fp_tbl_id;
     274             :         } recursive;
     275             :         struct {
     276             :             /**
     277             :              * BIER FMask ID
     278             :              */
     279             :             index_t fp_bier_fmask;
     280             :         } bier_fmask;
     281             :         struct {
     282             :             /**
     283             :              * The BIER table's ID
     284             :              */
     285             :             bier_table_id_t fp_bier_tbl;
     286             :         } bier_table;
     287             :         struct {
     288             :             /**
     289             :              * The BIER imposition object
     290             :              * this is part of the path's key, since the index_t
     291             :              * of an imposition object is the object's key.
     292             :              */
     293             :             index_t fp_bier_imp;
     294             :         } bier_imp;
     295             :         struct {
     296             :             /**
     297             :              * The FIB index in which to perfom the next lookup
     298             :              */
     299             :             fib_node_index_t fp_tbl_id;
     300             :             /**
     301             :              * The RPF-ID to tag the packets with
     302             :              */
     303             :             fib_rpf_id_t fp_rpf_id;
     304             :         } deag;
     305             :         struct {
     306             :         } special;
     307             :         struct {
     308             :             /**
     309             :              * The user provided 'exclusive' DPO
     310             :              */
     311             :             dpo_id_t fp_ex_dpo;
     312             :         } exclusive;
     313             :         struct {
     314             :             /**
     315             :              * The interface on which the local address is configured
     316             :              */
     317             :             u32 fp_interface;
     318             :             /**
     319             :              * The next-hop
     320             :              */
     321             :             ip46_address_t fp_addr;
     322             :         } receive;
     323             :         struct {
     324             :             /**
     325             :              * The interface on which the packets will be input.
     326             :              */
     327             :             u32 fp_interface;
     328             :         } intf_rx;
     329             :         struct {
     330             :             /**
     331             :              * The UDP Encap object this path resolves through
     332             :              */
     333             :             u32 fp_udp_encap_id;
     334             :         } udp_encap;
     335             :         struct {
     336             :             /**
     337             :              * The UDP Encap object this path resolves through
     338             :              */
     339             :             u32 fp_classify_table_id;
     340             :         } classify;
     341             :         struct {
     342             :             /**
     343             :              * The interface
     344             :              */
     345             :             u32 fp_interface;
     346             :         } dvr;
     347             :     };
     348             :     STRUCT_MARK(path_hash_end);
     349             : 
     350             :     /**
     351             :      * Members in this last section represent information that is
     352             :      * dervied during resolution. It should not be copied to new paths
     353             :      * nor compared.
     354             :      */
     355             : 
     356             :     /**
     357             :      * Operational Flags
     358             :      */
     359             :     fib_path_oper_flags_t fp_oper_flags;
     360             : 
     361             :     union {
     362             :         /**
     363             :          * the resolving via fib. not part of the union, since it it not part
     364             :          * of the path's hash.
     365             :          */
     366             :         fib_node_index_t fp_via_fib;
     367             :         /**
     368             :          * the resolving bier-table
     369             :          */
     370             :         index_t fp_via_bier_tbl;
     371             :         /**
     372             :          * the resolving bier-fmask
     373             :          */
     374             :         index_t fp_via_bier_fmask;
     375             :     };
     376             : 
     377             :     /**
     378             :      * The Data-path objects through which this path resolves for IP.
     379             :      */
     380             :     dpo_id_t fp_dpo;
     381             : 
     382             :     /**
     383             :      * the index of this path in the parent's child list.
     384             :      */
     385             :     u32 fp_sibling;
     386             : } fib_path_t;
     387             : 
     388             : /*
     389             :  * Array of strings/names for the path types and attributes
     390             :  */
     391             : static const char *fib_path_type_names[] = FIB_PATH_TYPES;
     392             : static const char *fib_path_oper_attribute_names[] = FIB_PATH_OPER_ATTRIBUTES;
     393             : static const char *fib_path_cfg_attribute_names[]  = FIB_PATH_CFG_ATTRIBUTES;
     394             : 
     395             : /*
     396             :  * The memory pool from which we allocate all the paths
     397             :  */
     398             : static fib_path_t *fib_path_pool;
     399             : 
     400             : /**
     401             :  * the logger
     402             :  */
     403             : vlib_log_class_t fib_path_logger;
     404             : 
     405             : /*
     406             :  * Debug macro
     407             :  */
     408             : #define FIB_PATH_DBG(_p, _fmt, _args...)                                \
     409             : {                                                                       \
     410             :     vlib_log_debug (fib_path_logger,                                    \
     411             :                     "[%U]: " _fmt,                                      \
     412             :                     format_fib_path, fib_path_get_index(_p), 0,         \
     413             :                     FIB_PATH_FORMAT_FLAGS_ONE_LINE,                     \
     414             :                     ##_args);                                           \
     415             : }
     416             : 
     417             : static fib_path_t *
     418     2723610 : fib_path_get (fib_node_index_t index)
     419             : {
     420     2723610 :     return (pool_elt_at_index(fib_path_pool, index));
     421             : }
     422             : 
     423             : static fib_node_index_t 
     424      464340 : fib_path_get_index (fib_path_t *path)
     425             : {
     426      464340 :     return (path - fib_path_pool);
     427             : }
     428             : 
     429             : static fib_node_t *
     430       35998 : fib_path_get_node (fib_node_index_t index)
     431             : {
     432       35998 :     return ((fib_node_t*)fib_path_get(index));
     433             : }
     434             : 
     435             : static fib_path_t*
     436       35998 : fib_path_from_fib_node (fib_node_t *node)
     437             : {
     438       35998 :     ASSERT(FIB_NODE_TYPE_PATH == node->fn_type);
     439       35998 :     return ((fib_path_t*)node);
     440             : }
     441             : 
     442             : u8 *
     443         320 : format_fib_path (u8 * s, va_list * args)
     444             : {
     445         320 :     fib_node_index_t path_index = va_arg (*args, fib_node_index_t);
     446         320 :     u32 indent = va_arg (*args, u32);
     447         320 :     fib_format_path_flags_t flags =  va_arg (*args, fib_format_path_flags_t);
     448         320 :     vnet_main_t * vnm = vnet_get_main();
     449             :     fib_path_oper_attribute_t oattr;
     450             :     fib_path_cfg_attribute_t cattr;
     451             :     fib_path_t *path;
     452             :     const char *eol;
     453             : 
     454         320 :     if (flags & FIB_PATH_FORMAT_FLAGS_ONE_LINE)
     455             :     {
     456           0 :         eol = "";
     457             :     }
     458             :     else
     459             :     {
     460         320 :         eol = "\n";
     461             :     }
     462             : 
     463         320 :     path = fib_path_get(path_index);
     464             : 
     465         320 :     s = format (s, "%Upath:[%d] ", format_white_space, indent,
     466             :                 fib_path_get_index(path));
     467         320 :     s = format (s, "pl-index:%d ", path->fp_pl_index);
     468         320 :     s = format (s, "%U ", format_dpo_proto, path->fp_nh_proto);
     469         320 :     s = format (s, "weight=%d ", path->fp_weight);
     470         320 :     s = format (s, "pref=%d ", path->fp_preference);
     471         320 :     s = format (s, "%s: ", fib_path_type_names[path->fp_type]);
     472         320 :     if (FIB_PATH_OPER_FLAG_NONE != path->fp_oper_flags) {
     473         168 :         s = format(s, " oper-flags:");
     474         672 :         FOR_EACH_FIB_PATH_OPER_ATTRIBUTE(oattr) {
     475         504 :             if ((1<<oattr) & path->fp_oper_flags) {
     476         168 :                 s = format (s, "%s,", fib_path_oper_attribute_names[oattr]);
     477             :             }
     478             :         }
     479             :     }
     480         320 :     if (FIB_PATH_CFG_FLAG_NONE != path->fp_cfg_flags) {
     481         304 :         s = format(s, " cfg-flags:");
     482        4560 :         FOR_EACH_FIB_PATH_CFG_ATTRIBUTE(cattr) {
     483        4256 :             if ((1<<cattr) & path->fp_cfg_flags) {
     484         306 :                 s = format (s, "%s,", fib_path_cfg_attribute_names[cattr]);
     485             :             }
     486             :         }
     487             :     }
     488         320 :     if (!(flags & FIB_PATH_FORMAT_FLAGS_ONE_LINE))
     489         320 :         s = format(s, "\n%U", format_white_space, indent+2);
     490             : 
     491         320 :     switch (path->fp_type)
     492             :     {
     493           9 :     case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
     494           9 :         s = format (s, "%U", format_ip46_address,
     495             :                     &path->attached_next_hop.fp_nh,
     496             :                     IP46_TYPE_ANY);
     497           9 :         if (path->fp_oper_flags & FIB_PATH_OPER_FLAG_DROP)
     498             :         {
     499           0 :             s = format (s, " if_index:%d", path->attached_next_hop.fp_interface);
     500             :         }
     501             :         else
     502             :         {
     503           9 :             s = format (s, " %U",
     504             :                         format_vnet_sw_interface_name,
     505             :                         vnm,
     506             :                         vnet_get_sw_interface(
     507             :                             vnm,
     508             :                             path->attached_next_hop.fp_interface));
     509           9 :             if (vnet_sw_interface_is_p2p(vnet_get_main(),
     510             :                                          path->attached_next_hop.fp_interface))
     511             :             {
     512           0 :                 s = format (s, " (p2p)");
     513             :             }
     514             :         }
     515           9 :         if (!dpo_id_is_valid(&path->fp_dpo))
     516             :         {
     517           0 :             s = format(s, "%s%Uunresolved", eol, format_white_space, indent+2);
     518             :         }
     519             :         else
     520             :         {
     521           9 :             s = format(s, "%s%U%U", eol,
     522             :                        format_white_space, indent,
     523             :                        format_dpo_id,
     524             :                        &path->fp_dpo, 13);
     525             :         }
     526           9 :         break;
     527           9 :     case FIB_PATH_TYPE_ATTACHED:
     528           9 :         if (path->fp_oper_flags & FIB_PATH_OPER_FLAG_DROP)
     529             :         {
     530           0 :             s = format (s, "if_index:%d", path->attached_next_hop.fp_interface);
     531             :         }
     532             :         else
     533             :         {
     534           9 :             s = format (s, " %U",
     535             :                         format_vnet_sw_interface_name,
     536             :                         vnm,
     537             :                         vnet_get_sw_interface(
     538             :                             vnm,
     539             :                             path->attached.fp_interface));
     540             :         }
     541           9 :         break;
     542         136 :     case FIB_PATH_TYPE_RECURSIVE:
     543         136 :         if (DPO_PROTO_MPLS == path->fp_nh_proto)
     544             :         {
     545           2 :             s = format (s, "via %U %U",
     546             :                         format_mpls_unicast_label,
     547             :                         path->recursive.fp_nh.fp_local_label,
     548             :                         format_mpls_eos_bit,
     549           2 :                         path->recursive.fp_nh.fp_eos);
     550             :         }
     551             :         else
     552             :         {
     553         134 :             s = format (s, "via %U",
     554             :                         format_ip46_address,
     555             :                         &path->recursive.fp_nh.fp_ip,
     556             :                         IP46_TYPE_ANY);
     557             :         }
     558         136 :         s = format (s, " in fib:%d",
     559             :                     path->recursive.fp_tbl_id,
     560             :                     path->fp_via_fib); 
     561         136 :         s = format (s, " via-fib:%d", path->fp_via_fib); 
     562         136 :         s = format (s, " via-dpo:[%U:%d]",
     563         136 :                     format_dpo_type, path->fp_dpo.dpoi_type, 
     564             :                     path->fp_dpo.dpoi_index);
     565             : 
     566         136 :         break;
     567           0 :     case FIB_PATH_TYPE_UDP_ENCAP:
     568           0 :         s = format (s, "UDP-encap ID:%d", path->udp_encap.fp_udp_encap_id);
     569           0 :         break;
     570           0 :     case FIB_PATH_TYPE_BIER_TABLE:
     571           0 :         s = format (s, "via bier-table:[%U}",
     572             :                     format_bier_table_id,
     573             :                     &path->bier_table.fp_bier_tbl);
     574           0 :         s = format (s, " via-dpo:[%U:%d]",
     575           0 :                     format_dpo_type, path->fp_dpo.dpoi_type,
     576             :                     path->fp_dpo.dpoi_index);
     577           0 :         break;
     578           0 :     case FIB_PATH_TYPE_BIER_FMASK:
     579           0 :         s = format (s, "via-fmask:%d", path->bier_fmask.fp_bier_fmask); 
     580           0 :         s = format (s, " via-dpo:[%U:%d]",
     581           0 :                     format_dpo_type, path->fp_dpo.dpoi_type, 
     582             :                     path->fp_dpo.dpoi_index);
     583           0 :         break;
     584           0 :     case FIB_PATH_TYPE_BIER_IMP:
     585           0 :         s = format (s, "via %U", format_bier_imp,
     586             :                     path->bier_imp.fp_bier_imp, 0, BIER_SHOW_BRIEF);
     587           0 :         break;
     588           0 :     case FIB_PATH_TYPE_DVR:
     589           0 :         s = format (s, " %U",
     590             :                     format_vnet_sw_interface_name,
     591             :                     vnm,
     592             :                     vnet_get_sw_interface(
     593             :                         vnm,
     594             :                         path->dvr.fp_interface));
     595           0 :         break;
     596           0 :     case FIB_PATH_TYPE_DEAG:
     597           0 :         s = format (s, " %sfib-index:%d",
     598           0 :                     (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RPF_ID ?  "m" : ""),
     599             :                     path->deag.fp_tbl_id);
     600           0 :         break;
     601         166 :     case FIB_PATH_TYPE_RECEIVE:
     602             :     case FIB_PATH_TYPE_INTF_RX:
     603             :     case FIB_PATH_TYPE_SPECIAL:
     604             :     case FIB_PATH_TYPE_EXCLUSIVE:
     605         166 :         if (dpo_id_is_valid(&path->fp_dpo))
     606             :         {
     607         166 :             s = format(s, "%U", format_dpo_id,
     608             :                        &path->fp_dpo, indent+2);
     609             :         }
     610         166 :         break;
     611             :     }
     612         320 :     return (s);
     613             : }
     614             : 
     615             : /*
     616             :  * fib_path_last_lock_gone
     617             :  *
     618             :  * We don't share paths, we share path lists, so the [un]lock functions
     619             :  * are no-ops
     620             :  */
     621             : static void
     622           0 : fib_path_last_lock_gone (fib_node_t *node)
     623             : {
     624           0 :     ASSERT(0);
     625           0 : }
     626             : 
     627             : static fib_path_t*
     628       17482 : fib_path_attached_next_hop_get_adj (fib_path_t *path,
     629             :                                     vnet_link_t link,
     630             :                                     dpo_id_t *dpo)
     631             : {
     632             :     fib_node_index_t fib_path_index;
     633             :     fib_protocol_t nh_proto;
     634             :     adj_index_t ai;
     635             : 
     636       17482 :     fib_path_index = fib_path_get_index(path);
     637       17482 :     nh_proto = dpo_proto_to_fib(path->fp_nh_proto);
     638             : 
     639       17482 :     if (vnet_sw_interface_is_p2p(vnet_get_main(),
     640             :                                  path->attached_next_hop.fp_interface))
     641             :     {
     642             :         /*
     643             :          * if the interface is p2p then the adj for the specific
     644             :          * neighbour on that link will never exist. on p2p links
     645             :          * the subnet address (the attached route) links to the
     646             :          * auto-adj (see below), we want that adj here too.
     647             :          */
     648         247 :         ai = adj_nbr_add_or_lock(nh_proto, link, &zero_addr,
     649             :                                  path->attached_next_hop.fp_interface);
     650             :     }
     651             :     else
     652             :     {
     653       17235 :         ai = adj_nbr_add_or_lock(nh_proto, link,
     654       17235 :                                  &path->attached_next_hop.fp_nh,
     655             :                                  path->attached_next_hop.fp_interface);
     656             :     }
     657             : 
     658       17482 :     dpo_set(dpo, DPO_ADJACENCY, vnet_link_to_dpo_proto(link), ai);
     659       17482 :     adj_unlock(ai);
     660             : 
     661       17482 :     return (fib_path_get(fib_path_index));
     662             : }
     663             : 
     664             : static void
     665       10417 : fib_path_attached_next_hop_set (fib_path_t *path)
     666             : {
     667       10417 :     dpo_id_t tmp = DPO_INVALID;
     668             : 
     669             :     /*
     670             :      * resolve directly via the adjacency discribed by the
     671             :      * interface and next-hop
     672             :      */
     673       10417 :     dpo_copy (&tmp, &path->fp_dpo);
     674       10417 :     path = fib_path_attached_next_hop_get_adj(path,
     675       10417 :                                               dpo_proto_to_link(path->fp_nh_proto),
     676             :                                               &tmp);
     677       10417 :     dpo_copy(&path->fp_dpo, &tmp);
     678       10417 :     dpo_reset(&tmp);
     679       10417 :     ASSERT(dpo_is_adj(&path->fp_dpo));
     680             : 
     681             :     /*
     682             :      * become a child of the adjacency so we receive updates
     683             :      * when its rewrite changes
     684             :      */
     685       10417 :     path->fp_sibling = adj_child_add(path->fp_dpo.dpoi_index,
     686             :                                      FIB_NODE_TYPE_PATH,
     687             :                                      fib_path_get_index(path));
     688             : 
     689       10417 :     if (!vnet_sw_interface_is_up(vnet_get_main(),
     690        9930 :                                  path->attached_next_hop.fp_interface) ||
     691        9930 :         !adj_is_up(path->fp_dpo.dpoi_index))
     692             :     {
     693         489 :         path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
     694             :     }
     695       10417 : }
     696             : 
     697             : static void
     698       36521 : fib_path_attached_get_adj (fib_path_t *path,
     699             :                            vnet_link_t link,
     700             :                            dpo_id_t *dpo)
     701             : {
     702             :     fib_protocol_t nh_proto;
     703             : 
     704       36521 :     nh_proto = dpo_proto_to_fib(path->fp_nh_proto);
     705             : 
     706       36521 :     if (vnet_sw_interface_is_p2p(vnet_get_main(),
     707             :                                  path->attached.fp_interface))
     708             :     {
     709             :         /*
     710             :          * point-2-point interfaces do not require a glean, since
     711             :          * there is nothing to ARP. Install a rewrite/nbr adj instead
     712             :          */
     713             :         adj_index_t ai;
     714             : 
     715        1270 :         ai = adj_nbr_add_or_lock(nh_proto, link, &zero_addr,
     716             :                                  path->attached.fp_interface);
     717             : 
     718        1270 :         dpo_set(dpo, DPO_ADJACENCY, vnet_link_to_dpo_proto(link), ai);
     719        1270 :         adj_unlock(ai);
     720             :     }
     721       35251 :     else if (vnet_sw_interface_is_nbma(vnet_get_main(),
     722             :                                        path->attached.fp_interface))
     723             :     {
     724         364 :         dpo_copy(dpo, drop_dpo_get(path->fp_nh_proto));
     725             :     }
     726             :     else
     727             :     {
     728             :         adj_index_t ai;
     729             : 
     730       34887 :         ai = adj_glean_add_or_lock(nh_proto, link,
     731             :                                    path->attached.fp_interface,
     732       34887 :                                    &path->attached.fp_connected);
     733       34887 :         dpo_set(dpo, DPO_ADJACENCY_GLEAN, vnet_link_to_dpo_proto(link), ai);
     734       34887 :         adj_unlock(ai);
     735             :     }
     736       36521 : }
     737             : 
     738             : /*
     739             :  * create of update the paths recursive adj
     740             :  */
     741             : static void
     742        5037 : fib_path_recursive_adj_update (fib_path_t *path,
     743             :                                fib_forward_chain_type_t fct,
     744             :                                dpo_id_t *dpo)
     745             : {
     746        5037 :     dpo_id_t via_dpo = DPO_INVALID;
     747             : 
     748             :     /*
     749             :      * get the DPO to resolve through from the via-entry
     750             :      */
     751        5037 :     fib_entry_contribute_forwarding(path->fp_via_fib,
     752             :                                     fct,
     753             :                                     &via_dpo);
     754             : 
     755             : 
     756             :     /*
     757             :      * hope for the best - clear if restrictions apply.
     758             :      */
     759        5037 :     path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED;
     760             : 
     761             :     /*
     762             :      * Validate any recursion constraints and over-ride the via
     763             :      * adj if not met
     764             :      */
     765        5037 :     if (path->fp_oper_flags & FIB_PATH_OPER_FLAG_RECURSIVE_LOOP)
     766             :     {
     767          16 :         path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
     768          16 :         dpo_copy(&via_dpo, drop_dpo_get(path->fp_nh_proto));
     769             :     }
     770        5021 :     else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RESOLVE_HOST)
     771             :     {
     772             :         /*
     773             :          * the via FIB must be a host route.
     774             :          * note the via FIB just added will always be a host route
     775             :          * since it is an RR source added host route. So what we need to
     776             :          * check is whether the route has other sources. If it does then
     777             :          * some other source has added it as a host route. If it doesn't
     778             :          * then it was added only here and inherits forwarding from a cover.
     779             :          * the cover is not a host route.
     780             :          * The RR source is the lowest priority source, so we check if it
     781             :          * is the best. if it is there are no other sources.
     782             :          */
     783        1021 :         if (fib_entry_get_best_source(path->fp_via_fib) >= FIB_SOURCE_RR)
     784             :         {
     785          71 :             path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
     786          71 :             dpo_copy(&via_dpo, drop_dpo_get(path->fp_nh_proto));
     787             : 
     788             :             /*
     789             :              * PIC edge trigger. let the load-balance maps know
     790             :              */
     791          71 :             load_balance_map_path_state_change(fib_path_get_index(path));
     792             :         }
     793             :     }
     794        4000 :     else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RESOLVE_ATTACHED)
     795             :     {
     796             :         /*
     797             :          * RR source entries inherit the flags from the cover, so
     798             :          * we can check the via directly
     799             :          */
     800        1354 :         if (!(FIB_ENTRY_FLAG_ATTACHED & fib_entry_get_flags(path->fp_via_fib)))
     801             :         {
     802           6 :             path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
     803           6 :             dpo_copy(&via_dpo, drop_dpo_get(path->fp_nh_proto));
     804             : 
     805             :             /*
     806             :              * PIC edge trigger. let the load-balance maps know
     807             :              */
     808           6 :             load_balance_map_path_state_change(fib_path_get_index(path));
     809             :         }
     810             :     }
     811             :     /*
     812             :      * check for over-riding factors on the FIB entry itself
     813             :      */
     814        5037 :     if (!fib_entry_is_resolved(path->fp_via_fib))
     815             :     {
     816           3 :         path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
     817           3 :         dpo_copy(&via_dpo, drop_dpo_get(path->fp_nh_proto));
     818             : 
     819             :         /*
     820             :          * PIC edge trigger. let the load-balance maps know
     821             :          */
     822           3 :         load_balance_map_path_state_change(fib_path_get_index(path));
     823             :     }
     824             : 
     825             :     /*
     826             :      * If this path is contributing a drop, then it's not resolved
     827             :      */
     828        5037 :     if (dpo_is_drop(&via_dpo) || load_balance_is_drop(&via_dpo))
     829             :     {
     830         357 :         path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
     831             :     }
     832             : 
     833             :     /*
     834             :      * update the path's contributed DPO
     835             :      */
     836        5037 :     dpo_copy(dpo, &via_dpo);
     837             : 
     838        5037 :     FIB_PATH_DBG(path, "recursive update:");
     839             : 
     840        5037 :     dpo_reset(&via_dpo);
     841        5037 : }
     842             : 
     843             : /*
     844             :  * re-evaulate the forwarding state for a via fmask path
     845             :  */
     846             : static void
     847        2669 : fib_path_bier_fmask_update (fib_path_t *path,
     848             :                             dpo_id_t *dpo)
     849             : {
     850        2669 :     bier_fmask_contribute_forwarding(path->bier_fmask.fp_bier_fmask, dpo);
     851             : 
     852             :     /*
     853             :      * if we are stakcing on the drop, then the path is not resolved
     854             :      */
     855        2669 :     if (dpo_is_drop(dpo))
     856             :     {
     857           8 :         path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
     858             :     }
     859             :     else
     860             :     {
     861        2661 :         path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED;
     862             :     }
     863        2669 : }
     864             : 
     865             : /*
     866             :  * fib_path_is_permanent_drop
     867             :  *
     868             :  * Return !0 if the path is configured to permanently drop,
     869             :  * despite other attributes.
     870             :  */
     871             : static int
     872      635038 : fib_path_is_permanent_drop (fib_path_t *path)
     873             : {
     874     1227920 :     return ((path->fp_cfg_flags & FIB_PATH_CFG_FLAG_DROP) ||
     875      592883 :             (path->fp_oper_flags & FIB_PATH_OPER_FLAG_DROP));
     876             : }
     877             : 
     878             : /*
     879             :  * fib_path_unresolve
     880             :  *
     881             :  * Remove our dependency on the resolution target
     882             :  */
     883             : static void
     884       93267 : fib_path_unresolve (fib_path_t *path)
     885             : {
     886             :     /*
     887             :      * the forced drop path does not need unresolving
     888             :      */
     889       93267 :     if (fib_path_is_permanent_drop(path))
     890             :     {
     891        8107 :         return;
     892             :     }
     893             : 
     894       85160 :     switch (path->fp_type)
     895             :     {
     896        4297 :     case FIB_PATH_TYPE_RECURSIVE:
     897        4297 :         if (FIB_NODE_INDEX_INVALID != path->fp_via_fib)
     898             :         {
     899        2118 :             fib_entry_child_remove(path->fp_via_fib,
     900             :                                    path->fp_sibling);
     901        2118 :             fib_table_entry_special_remove(path->recursive.fp_tbl_id,
     902             :                                            fib_entry_get_prefix(path->fp_via_fib),
     903             :                                            FIB_SOURCE_RR);
     904        2118 :             fib_table_unlock(path->recursive.fp_tbl_id,
     905        2118 :                              dpo_proto_to_fib(path->fp_nh_proto),
     906             :                              FIB_SOURCE_RR);
     907        2118 :             path->fp_via_fib = FIB_NODE_INDEX_INVALID;
     908             :         }
     909        4297 :         break;
     910         244 :     case FIB_PATH_TYPE_BIER_FMASK:
     911         244 :         bier_fmask_child_remove(path->fp_via_bier_fmask,
     912             :                                 path->fp_sibling);
     913         244 :         break;
     914           6 :     case FIB_PATH_TYPE_BIER_IMP:
     915           6 :         bier_imp_unlock(path->fp_dpo.dpoi_index);
     916           6 :         break;
     917         160 :     case FIB_PATH_TYPE_BIER_TABLE:
     918         160 :         bier_table_ecmp_unlock(path->fp_via_bier_tbl);
     919         160 :         break;
     920       55604 :     case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
     921             :     case FIB_PATH_TYPE_ATTACHED:
     922       55604 :         if (dpo_is_adj(&path->fp_dpo))
     923       40849 :             adj_child_remove(path->fp_dpo.dpoi_index,
     924             :                              path->fp_sibling);
     925       55604 :         break;
     926          11 :     case FIB_PATH_TYPE_UDP_ENCAP:
     927          11 :         udp_encap_unlock(path->fp_dpo.dpoi_index);
     928          11 :         break;
     929        7643 :     case FIB_PATH_TYPE_EXCLUSIVE:
     930        7643 :         dpo_reset(&path->exclusive.fp_ex_dpo);
     931        7643 :         break;
     932       17195 :     case FIB_PATH_TYPE_SPECIAL:
     933             :     case FIB_PATH_TYPE_RECEIVE:
     934             :     case FIB_PATH_TYPE_INTF_RX:
     935             :     case FIB_PATH_TYPE_DEAG:
     936             :     case FIB_PATH_TYPE_DVR:
     937             :         /*
     938             :          * these hold only the path's DPO, which is reset below.
     939             :          */
     940       17195 :         break;
     941             :     }
     942             : 
     943             :     /*
     944             :      * release the adj we were holding and pick up the
     945             :      * drop just in case.
     946             :      */
     947       85160 :     dpo_reset(&path->fp_dpo);
     948       85160 :     path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
     949             : 
     950       85160 :     return;
     951             : }
     952             : 
     953             : static fib_forward_chain_type_t
     954      159016 : fib_path_to_chain_type (const fib_path_t *path)
     955             : {
     956      159016 :     if (DPO_PROTO_MPLS == path->fp_nh_proto)
     957             :     {
     958         632 :         if (FIB_PATH_TYPE_RECURSIVE == path->fp_type &&
     959          46 :             MPLS_EOS == path->recursive.fp_nh.fp_eos)
     960             :         {
     961           6 :             return (FIB_FORW_CHAIN_TYPE_MPLS_EOS);
     962             :         }
     963             :         else
     964             :         {
     965         626 :             return (FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS);
     966             :         }
     967             :     }
     968             :     else
     969             :     {
     970      158384 :         return (fib_forw_chain_type_from_dpo_proto(path->fp_nh_proto));
     971             :     }
     972             : }
     973             : 
     974             : /*
     975             :  * fib_path_back_walk_notify
     976             :  *
     977             :  * A back walk has reach this path.
     978             :  */
     979             : static fib_node_back_walk_rc_t
     980       35998 : fib_path_back_walk_notify (fib_node_t *node,
     981             :                            fib_node_back_walk_ctx_t *ctx)
     982             : {
     983             :     fib_path_t *path;
     984             : 
     985       35998 :     path = fib_path_from_fib_node(node);
     986             : 
     987       35998 :     FIB_PATH_DBG(path, "bw:%U",
     988             :                  format_fib_node_bw_reason, ctx->fnbw_reason);
     989             : 
     990       35998 :     switch (path->fp_type)
     991             :     {
     992         657 :     case FIB_PATH_TYPE_RECURSIVE:
     993         657 :         if (FIB_NODE_BW_REASON_FLAG_EVALUATE & ctx->fnbw_reason)
     994             :         {
     995             :             /*
     996             :              * modify the recursive adjacency to use the new forwarding
     997             :              * of the via-fib.
     998             :              * this update is visible to packets in flight in the DP.
     999             :              */
    1000         657 :             fib_path_recursive_adj_update(
    1001             :                 path,
    1002         657 :                 fib_path_to_chain_type(path),
    1003             :                 &path->fp_dpo);
    1004             :         }
    1005         657 :         if ((FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE & ctx->fnbw_reason) ||
    1006         657 :             (FIB_NODE_BW_REASON_FLAG_ADJ_MTU    & ctx->fnbw_reason) ||
    1007         657 :             (FIB_NODE_BW_REASON_FLAG_ADJ_DOWN   & ctx->fnbw_reason))
    1008             :         {
    1009             :             /*
    1010             :              * ADJ updates (complete<->incomplete) do not need to propagate to
    1011             :              * recursive entries.
    1012             :              * The only reason its needed as far back as here, is that the adj
    1013             :              * and the incomplete adj are a different DPO type, so the LBs need
    1014             :              * to re-stack.
    1015             :              * If this walk was quashed in the fib_entry, then any non-fib_path
    1016             :              * children (like tunnels that collapse out the LB when they stack)
    1017             :              * would not see the update.
    1018             :              */
    1019           0 :             return (FIB_NODE_BACK_WALK_CONTINUE);
    1020             :         }
    1021         657 :         break;
    1022          77 :     case FIB_PATH_TYPE_BIER_FMASK:
    1023          77 :         if (FIB_NODE_BW_REASON_FLAG_EVALUATE & ctx->fnbw_reason)
    1024             :         {
    1025             :             /*
    1026             :              * update to use the BIER fmask's new forwading
    1027             :              */
    1028          77 :             fib_path_bier_fmask_update(path, &path->fp_dpo);
    1029             :         }
    1030          77 :         if ((FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE & ctx->fnbw_reason) ||
    1031          77 :             (FIB_NODE_BW_REASON_FLAG_ADJ_DOWN   & ctx->fnbw_reason))
    1032             :         {
    1033             :             /*
    1034             :              * ADJ updates (complete<->incomplete) do not need to propagate to
    1035             :              * recursive entries.
    1036             :              * The only reason its needed as far back as here, is that the adj
    1037             :              * and the incomplete adj are a different DPO type, so the LBs need
    1038             :              * to re-stack.
    1039             :              * If this walk was quashed in the fib_entry, then any non-fib_path
    1040             :              * children (like tunnels that collapse out the LB when they stack)
    1041             :              * would not see the update.
    1042             :              */
    1043           0 :             return (FIB_NODE_BACK_WALK_CONTINUE);
    1044             :         }
    1045          77 :         break;
    1046       13310 :     case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
    1047             :         /*
    1048             : FIXME comment
    1049             :          * ADJ_UPDATE backwalk pass silently through here and up to
    1050             :          * the path-list when the multipath adj collapse occurs.
    1051             :          * The reason we do this is that the assumtption is that VPP
    1052             :          * runs in an environment where the Control-Plane is remote
    1053             :          * and hence reacts slowly to link up down. In order to remove
    1054             :          * this down link from the ECMP set quickly, we back-walk.
    1055             :          * VPP also has dedicated CPUs, so we are not stealing resources
    1056             :          * from the CP to do so.
    1057             :          */
    1058       13310 :         if (FIB_NODE_BW_REASON_FLAG_INTERFACE_UP & ctx->fnbw_reason)
    1059             :         {
    1060         959 :             if (path->fp_oper_flags & FIB_PATH_OPER_FLAG_RESOLVED)
    1061             :             {
    1062             :                 /*
    1063             :                  * alreday resolved. no need to walk back again
    1064             :                  */
    1065         486 :                 return (FIB_NODE_BACK_WALK_CONTINUE);
    1066             :             }
    1067         473 :             path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED;
    1068             :         }
    1069       12824 :         if (FIB_NODE_BW_REASON_FLAG_INTERFACE_DOWN & ctx->fnbw_reason)
    1070             :         {
    1071         577 :             if (!(path->fp_oper_flags & FIB_PATH_OPER_FLAG_RESOLVED))
    1072             :             {
    1073             :                 /*
    1074             :                  * alreday unresolved. no need to walk back again
    1075             :                  */
    1076         228 :                 return (FIB_NODE_BACK_WALK_CONTINUE);
    1077             :             }
    1078         349 :             path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
    1079             :         }
    1080       12596 :         if (FIB_NODE_BW_REASON_FLAG_INTERFACE_DELETE & ctx->fnbw_reason)
    1081             :         {
    1082             :             /*
    1083             :              * The interface this path resolves through has been deleted.
    1084             :              * This will leave the path in a permanent drop state. The route
    1085             :              * needs to be removed and readded (and hence the path-list deleted)
    1086             :              * before it can forward again.
    1087             :              */
    1088          14 :             fib_path_unresolve(path);
    1089          14 :             path->fp_oper_flags |= FIB_PATH_OPER_FLAG_DROP;
    1090             :         }
    1091       12596 :         if (FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE & ctx->fnbw_reason)
    1092             :         {
    1093             :             /*
    1094             :              * restack the DPO to pick up the correct DPO sub-type
    1095             :              */
    1096        5970 :             dpo_id_t tmp = DPO_INVALID;
    1097             :             uword if_is_up;
    1098             : 
    1099        5970 :             if_is_up = vnet_sw_interface_is_up(
    1100             :                            vnet_get_main(),
    1101             :                            path->attached_next_hop.fp_interface);
    1102             : 
    1103        5970 :             dpo_copy (&tmp, &path->fp_dpo);
    1104        5970 :             path = fib_path_attached_next_hop_get_adj(
    1105             :                 path,
    1106        5970 :                 dpo_proto_to_link(path->fp_nh_proto),
    1107             :                 &tmp);
    1108        5970 :             dpo_copy(&path->fp_dpo, &tmp);
    1109        5970 :             dpo_reset(&tmp);
    1110             : 
    1111        5970 :             path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
    1112        5970 :             if (if_is_up && adj_is_up(path->fp_dpo.dpoi_index))
    1113             :             {
    1114        2901 :                 path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED;
    1115             :             }
    1116             : 
    1117        5970 :             if (!if_is_up)
    1118             :             {
    1119             :                 /*
    1120             :                  * If the interface is not up there is no reason to walk
    1121             :                  * back to children. if we did they would only evalute
    1122             :                  * that this path is unresolved and hence it would
    1123             :                  * not contribute the adjacency - so it would be wasted
    1124             :                  * CPU time.
    1125             :                  */
    1126        2964 :                 return (FIB_NODE_BACK_WALK_CONTINUE);
    1127             :             }
    1128             :         }
    1129        9632 :         if (FIB_NODE_BW_REASON_FLAG_ADJ_DOWN & ctx->fnbw_reason)
    1130             :         {
    1131        5739 :             if (!(path->fp_oper_flags & FIB_PATH_OPER_FLAG_RESOLVED))
    1132             :             {
    1133             :                 /*
    1134             :                  * alreday unresolved. no need to walk back again
    1135             :                  */
    1136         155 :                 return (FIB_NODE_BACK_WALK_CONTINUE);
    1137             :             }
    1138             :             /*
    1139             :              * the adj has gone down. the path is no longer resolved.
    1140             :              */
    1141        5584 :             path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
    1142             :         }
    1143        9477 :         break;
    1144       21954 :     case FIB_PATH_TYPE_ATTACHED:
    1145             :     case FIB_PATH_TYPE_DVR:
    1146             :         /*
    1147             :          * FIXME; this could schedule a lower priority walk, since attached
    1148             :          * routes are not usually in ECMP configurations so the backwalk to
    1149             :          * the FIB entry does not need to be high priority
    1150             :          */
    1151       21954 :         if (FIB_NODE_BW_REASON_FLAG_INTERFACE_UP & ctx->fnbw_reason)
    1152             :         {
    1153        1788 :             path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED;
    1154             :         }
    1155       21954 :         if (FIB_NODE_BW_REASON_FLAG_INTERFACE_DOWN & ctx->fnbw_reason)
    1156             :         {
    1157       19882 :             path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
    1158             :         }
    1159       21954 :         if (FIB_NODE_BW_REASON_FLAG_INTERFACE_DELETE & ctx->fnbw_reason)
    1160             :         {
    1161          10 :             fib_path_unresolve(path);
    1162          10 :             path->fp_oper_flags |= FIB_PATH_OPER_FLAG_DROP;
    1163             :         }
    1164       21954 :         if (FIB_NODE_BW_REASON_FLAG_INTERFACE_BIND & ctx->fnbw_reason)
    1165             :         {
    1166             :             /* bind walks should appear here and pass silently up to
    1167             :              * to the fib_entry */
    1168             :         }
    1169       21954 :         break;
    1170           0 :     case FIB_PATH_TYPE_UDP_ENCAP:
    1171             :     {
    1172           0 :         dpo_id_t via_dpo = DPO_INVALID;
    1173             : 
    1174             :         /*
    1175             :          * hope for the best - clear if restrictions apply.
    1176             :          */
    1177           0 :         path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED;
    1178             : 
    1179           0 :         udp_encap_contribute_forwarding(path->udp_encap.fp_udp_encap_id,
    1180           0 :                                         path->fp_nh_proto,
    1181             :                                         &via_dpo);
    1182             :         /*
    1183             :          * If this path is contributing a drop, then it's not resolved
    1184             :          */
    1185           0 :         if (dpo_is_drop(&via_dpo) || load_balance_is_drop(&via_dpo))
    1186             :         {
    1187           0 :             path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
    1188             :         }
    1189             : 
    1190             :         /*
    1191             :          * update the path's contributed DPO
    1192             :          */
    1193           0 :         dpo_copy(&path->fp_dpo, &via_dpo);
    1194           0 :         dpo_reset(&via_dpo);
    1195           0 :         break;
    1196             :     }
    1197           0 :     case FIB_PATH_TYPE_INTF_RX:
    1198           0 :         ASSERT(0);
    1199             :     case FIB_PATH_TYPE_DEAG:
    1200             :         /*
    1201             :          * FIXME When VRF delete is allowed this will need a poke.
    1202             :          */
    1203             :     case FIB_PATH_TYPE_SPECIAL:
    1204             :     case FIB_PATH_TYPE_RECEIVE:
    1205             :     case FIB_PATH_TYPE_EXCLUSIVE:
    1206             :     case FIB_PATH_TYPE_BIER_TABLE:
    1207             :     case FIB_PATH_TYPE_BIER_IMP:
    1208             :         /*
    1209             :          * these path types have no parents. so to be
    1210             :          * walked from one is unexpected.
    1211             :          */
    1212           0 :         ASSERT(0);
    1213           0 :         break;
    1214             :     }
    1215             : 
    1216             :     /*
    1217             :      * propagate the backwalk further to the path-list
    1218             :      */
    1219       32165 :     fib_path_list_back_walk(path->fp_pl_index, ctx);
    1220             : 
    1221       32165 :     return (FIB_NODE_BACK_WALK_CONTINUE);
    1222             : }
    1223             : 
    1224             : static void
    1225           1 : fib_path_memory_show (void)
    1226             : {
    1227           1 :     fib_show_memory_usage("Path",
    1228           1 :                           pool_elts(fib_path_pool),
    1229           1 :                           pool_len(fib_path_pool),
    1230             :                           sizeof(fib_path_t));
    1231           1 : }
    1232             : 
    1233             : /*
    1234             :  * The FIB path's graph node virtual function table
    1235             :  */
    1236             : static const fib_node_vft_t fib_path_vft = {
    1237             :     .fnv_get = fib_path_get_node,
    1238             :     .fnv_last_lock = fib_path_last_lock_gone,
    1239             :     .fnv_back_walk = fib_path_back_walk_notify,
    1240             :     .fnv_mem_show = fib_path_memory_show,
    1241             : };
    1242             : 
    1243             : static fib_path_cfg_flags_t
    1244       73857 : fib_path_route_flags_to_cfg_flags (const fib_route_path_t *rpath)
    1245             : {
    1246       73857 :     fib_path_cfg_flags_t cfg_flags = FIB_PATH_CFG_FLAG_NONE;
    1247             : 
    1248       73857 :     if (rpath->frp_flags & FIB_ROUTE_PATH_POP_PW_CW)
    1249           1 :         cfg_flags |= FIB_PATH_CFG_FLAG_POP_PW_CW;
    1250       73857 :     if (rpath->frp_flags & FIB_ROUTE_PATH_RESOLVE_VIA_HOST)
    1251         651 :         cfg_flags |= FIB_PATH_CFG_FLAG_RESOLVE_HOST;
    1252       73857 :     if (rpath->frp_flags & FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED)
    1253         268 :         cfg_flags |= FIB_PATH_CFG_FLAG_RESOLVE_ATTACHED;
    1254       73857 :     if (rpath->frp_flags & FIB_ROUTE_PATH_LOCAL)
    1255       14020 :         cfg_flags |= FIB_PATH_CFG_FLAG_LOCAL;
    1256       73857 :     if (rpath->frp_flags & FIB_ROUTE_PATH_ATTACHED)
    1257       12847 :         cfg_flags |= FIB_PATH_CFG_FLAG_ATTACHED;
    1258       73857 :     if (rpath->frp_flags & FIB_ROUTE_PATH_INTF_RX)
    1259           7 :         cfg_flags |= FIB_PATH_CFG_FLAG_INTF_RX;
    1260       73857 :     if (rpath->frp_flags & FIB_ROUTE_PATH_RPF_ID)
    1261          15 :         cfg_flags |= FIB_PATH_CFG_FLAG_RPF_ID;
    1262       73857 :     if (rpath->frp_flags & FIB_ROUTE_PATH_EXCLUSIVE)
    1263         406 :         cfg_flags |= FIB_PATH_CFG_FLAG_EXCLUSIVE;
    1264       73857 :     if (rpath->frp_flags & FIB_ROUTE_PATH_DROP)
    1265          15 :         cfg_flags |= FIB_PATH_CFG_FLAG_DROP;
    1266       73857 :     if (rpath->frp_flags & FIB_ROUTE_PATH_SOURCE_LOOKUP)
    1267           3 :         cfg_flags |= FIB_PATH_CFG_FLAG_DEAG_SRC;
    1268       73857 :     if (rpath->frp_flags & FIB_ROUTE_PATH_ICMP_UNREACH)
    1269           2 :         cfg_flags |= FIB_PATH_CFG_FLAG_ICMP_UNREACH;
    1270       73857 :     if (rpath->frp_flags & FIB_ROUTE_PATH_ICMP_PROHIBIT)
    1271           2 :         cfg_flags |= FIB_PATH_CFG_FLAG_ICMP_PROHIBIT;
    1272       73857 :     if (rpath->frp_flags & FIB_ROUTE_PATH_GLEAN)
    1273       19157 :         cfg_flags |= FIB_PATH_CFG_FLAG_GLEAN;
    1274             : 
    1275       73857 :     return (cfg_flags);
    1276             : }
    1277             : 
    1278             : /*
    1279             :  * fib_path_create
    1280             :  *
    1281             :  * Create and initialise a new path object.
    1282             :  * return the index of the path.
    1283             :  */
    1284             : fib_node_index_t
    1285       73857 : fib_path_create (fib_node_index_t pl_index,
    1286             :                  const fib_route_path_t *rpath)
    1287             : {
    1288             :     fib_path_t *path;
    1289             : 
    1290       73857 :     pool_get(fib_path_pool, path);
    1291       73857 :     clib_memset(path, 0, sizeof(*path));
    1292             : 
    1293       73857 :     fib_node_init(&path->fp_node,
    1294             :                   FIB_NODE_TYPE_PATH);
    1295             : 
    1296       73857 :     dpo_reset(&path->fp_dpo);
    1297       73857 :     path->fp_pl_index = pl_index;
    1298       73857 :     path->fp_nh_proto = rpath->frp_proto;
    1299       73857 :     path->fp_via_fib = FIB_NODE_INDEX_INVALID;
    1300       73857 :     path->fp_weight = rpath->frp_weight;
    1301       73857 :     if (0 == path->fp_weight)
    1302             :     {
    1303             :         /*
    1304             :          * a weight of 0 is a meaningless value. We could either reject it, and thus force
    1305             :          * clients to always use 1, or we can accept it and fixup approrpiately.
    1306             :          */
    1307         199 :         path->fp_weight = 1;
    1308             :     }
    1309       73857 :     path->fp_preference = rpath->frp_preference;
    1310       73857 :     path->fp_cfg_flags = fib_path_route_flags_to_cfg_flags(rpath);
    1311             : 
    1312             :     /*
    1313             :      * deduce the path's tpye from the parementers and save what is needed.
    1314             :      */
    1315       73857 :     if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_LOCAL)
    1316             :     {
    1317       14020 :         path->fp_type = FIB_PATH_TYPE_RECEIVE;
    1318       14020 :         path->receive.fp_interface = rpath->frp_sw_if_index;
    1319       14020 :         path->receive.fp_addr = rpath->frp_addr;
    1320             :     }
    1321       59837 :     else if (rpath->frp_flags & FIB_ROUTE_PATH_UDP_ENCAP)
    1322             :     {
    1323          11 :         path->fp_type = FIB_PATH_TYPE_UDP_ENCAP;
    1324          11 :         path->udp_encap.fp_udp_encap_id = rpath->frp_udp_encap_id;
    1325             :     }
    1326       59826 :     else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_INTF_RX)
    1327             :     {
    1328           7 :         path->fp_type = FIB_PATH_TYPE_INTF_RX;
    1329           7 :         path->intf_rx.fp_interface = rpath->frp_sw_if_index;
    1330             :     }
    1331       59819 :     else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RPF_ID)
    1332             :     {
    1333          15 :         path->fp_type = FIB_PATH_TYPE_DEAG;
    1334          15 :         path->deag.fp_tbl_id = rpath->frp_fib_index;
    1335          15 :         path->deag.fp_rpf_id = rpath->frp_rpf_id;
    1336             :     }
    1337       59804 :     else if (rpath->frp_flags & FIB_ROUTE_PATH_BIER_FMASK)
    1338             :     {
    1339         159 :         path->fp_type = FIB_PATH_TYPE_BIER_FMASK;
    1340         159 :         path->bier_fmask.fp_bier_fmask = rpath->frp_bier_fmask;
    1341             :     }
    1342       59645 :     else if (rpath->frp_flags & FIB_ROUTE_PATH_BIER_IMP)
    1343             :     {
    1344           6 :         path->fp_type = FIB_PATH_TYPE_BIER_IMP;
    1345           6 :         path->bier_imp.fp_bier_imp = rpath->frp_bier_imp;
    1346             :     }
    1347       59639 :     else if (rpath->frp_flags & FIB_ROUTE_PATH_BIER_TABLE)
    1348             :     {
    1349         160 :         path->fp_type = FIB_PATH_TYPE_BIER_TABLE;
    1350         160 :         path->bier_table.fp_bier_tbl = rpath->frp_bier_tbl;
    1351             :     }
    1352       59479 :     else if (rpath->frp_flags & FIB_ROUTE_PATH_DEAG)
    1353             :     {
    1354          62 :         path->fp_type = FIB_PATH_TYPE_DEAG;
    1355          62 :         path->deag.fp_tbl_id = rpath->frp_fib_index;
    1356             :     }
    1357       59417 :     else if (rpath->frp_flags & FIB_ROUTE_PATH_DVR)
    1358             :     {
    1359           8 :         path->fp_type = FIB_PATH_TYPE_DVR;
    1360           8 :         path->dvr.fp_interface = rpath->frp_sw_if_index;
    1361             :     }
    1362       59409 :     else if (rpath->frp_flags & FIB_ROUTE_PATH_EXCLUSIVE)
    1363             :     {
    1364           0 :         path->fp_type = FIB_PATH_TYPE_EXCLUSIVE;
    1365           0 :         dpo_copy(&path->exclusive.fp_ex_dpo, &rpath->dpo);
    1366             :     }
    1367       59409 :     else if ((path->fp_cfg_flags & FIB_PATH_CFG_FLAG_ICMP_PROHIBIT) ||
    1368       59407 :         (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_ICMP_UNREACH))
    1369             :     {
    1370           4 :         path->fp_type = FIB_PATH_TYPE_SPECIAL;
    1371             :     }
    1372       59405 :     else if ((path->fp_cfg_flags & FIB_PATH_CFG_FLAG_CLASSIFY))
    1373             :     {
    1374           0 :         path->fp_type = FIB_PATH_TYPE_SPECIAL;
    1375           0 :         path->classify.fp_classify_table_id = rpath->frp_classify_table_id;
    1376             :     }
    1377       59405 :     else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_GLEAN)
    1378             :     {
    1379       19152 :         path->fp_type = FIB_PATH_TYPE_ATTACHED;
    1380       19152 :         path->attached.fp_interface = rpath->frp_sw_if_index;
    1381       19152 :         path->attached.fp_connected = rpath->frp_connected;
    1382             :     }
    1383       40253 :     else if (~0 != rpath->frp_sw_if_index)
    1384             :     {
    1385       36356 :         if (ip46_address_is_zero(&rpath->frp_addr))
    1386             :         {
    1387       17376 :             path->fp_type = FIB_PATH_TYPE_ATTACHED;
    1388       17376 :             path->attached.fp_interface = rpath->frp_sw_if_index;
    1389             :         }
    1390             :         else
    1391             :         {
    1392       18980 :             path->fp_type = FIB_PATH_TYPE_ATTACHED_NEXT_HOP;
    1393       18980 :             path->attached_next_hop.fp_interface = rpath->frp_sw_if_index;
    1394       18980 :             path->attached_next_hop.fp_nh = rpath->frp_addr;
    1395             :         }
    1396             :     }
    1397             :     else
    1398             :     {
    1399        3897 :         if (ip46_address_is_zero(&rpath->frp_addr))
    1400             :         {
    1401           9 :             if (~0 == rpath->frp_fib_index)
    1402             :             {
    1403           0 :                 path->fp_type = FIB_PATH_TYPE_SPECIAL;
    1404             :             }
    1405             :             else
    1406             :             {
    1407           9 :                 path->fp_type = FIB_PATH_TYPE_DEAG;
    1408           9 :                 path->deag.fp_tbl_id = rpath->frp_fib_index;
    1409           9 :                 path->deag.fp_rpf_id = ~0;
    1410             :             }
    1411             :         }
    1412             :         else
    1413             :         {
    1414        3888 :             path->fp_type = FIB_PATH_TYPE_RECURSIVE;
    1415        3888 :             if (DPO_PROTO_MPLS == path->fp_nh_proto)
    1416             :             {
    1417          21 :                 path->recursive.fp_nh.fp_local_label = rpath->frp_local_label;
    1418          21 :                 path->recursive.fp_nh.fp_eos = rpath->frp_eos;
    1419             :             }
    1420             :             else
    1421             :             {
    1422        3867 :                 path->recursive.fp_nh.fp_ip = rpath->frp_addr;
    1423             :             }
    1424        3888 :             path->recursive.fp_tbl_id = rpath->frp_fib_index;
    1425             :         }
    1426             :     }
    1427             : 
    1428       73857 :     FIB_PATH_DBG(path, "create");
    1429             : 
    1430       73857 :     return (fib_path_get_index(path));
    1431             : }
    1432             : 
    1433             : /*
    1434             :  * fib_path_create_special
    1435             :  *
    1436             :  * Create and initialise a new path object.
    1437             :  * return the index of the path.
    1438             :  */
    1439             : fib_node_index_t
    1440       27717 : fib_path_create_special (fib_node_index_t pl_index,
    1441             :                          dpo_proto_t nh_proto,
    1442             :                          fib_path_cfg_flags_t flags,
    1443             :                          const dpo_id_t *dpo)
    1444             : {
    1445             :     fib_path_t *path;
    1446             : 
    1447       27717 :     pool_get(fib_path_pool, path);
    1448       27717 :     clib_memset(path, 0, sizeof(*path));
    1449             : 
    1450       27717 :     fib_node_init(&path->fp_node,
    1451             :                   FIB_NODE_TYPE_PATH);
    1452       27717 :     dpo_reset(&path->fp_dpo);
    1453             : 
    1454       27717 :     path->fp_pl_index = pl_index;
    1455       27717 :     path->fp_weight = 1;
    1456       27717 :     path->fp_preference = 0;
    1457       27717 :     path->fp_nh_proto = nh_proto;
    1458       27717 :     path->fp_via_fib = FIB_NODE_INDEX_INVALID;
    1459       27717 :     path->fp_cfg_flags = flags;
    1460             : 
    1461       27717 :     if (FIB_PATH_CFG_FLAG_DROP & flags)
    1462             :     {
    1463       12274 :         path->fp_type = FIB_PATH_TYPE_SPECIAL;
    1464             :     }
    1465       15443 :     else if (FIB_PATH_CFG_FLAG_LOCAL & flags)
    1466             :     {
    1467        7183 :         path->fp_type = FIB_PATH_TYPE_RECEIVE;
    1468        7183 :         path->attached.fp_interface = FIB_NODE_INDEX_INVALID;
    1469             :     }
    1470             :     else
    1471             :     {
    1472        8260 :         path->fp_type = FIB_PATH_TYPE_EXCLUSIVE;
    1473        8260 :         ASSERT(NULL != dpo);
    1474        8260 :         dpo_copy(&path->exclusive.fp_ex_dpo, dpo);
    1475             :     }
    1476             : 
    1477       27717 :     return (fib_path_get_index(path));
    1478             : }
    1479             : 
    1480             : /*
    1481             :  * fib_path_copy
    1482             :  *
    1483             :  * Copy a path. return index of new path.
    1484             :  */
    1485             : fib_node_index_t
    1486        6346 : fib_path_copy (fib_node_index_t path_index,
    1487             :                fib_node_index_t path_list_index)
    1488             : {
    1489             :     fib_path_t *path, *orig_path;
    1490             : 
    1491        6346 :     pool_get(fib_path_pool, path);
    1492             : 
    1493        6346 :     orig_path = fib_path_get(path_index);
    1494        6346 :     ASSERT(NULL != orig_path);
    1495             : 
    1496        6346 :     clib_memcpy(path, orig_path, sizeof(*path));
    1497             : 
    1498        6346 :     FIB_PATH_DBG(path, "create-copy:%d", path_index);
    1499             : 
    1500             :     /*
    1501             :      * reset the dynamic section
    1502             :      */
    1503        6346 :     fib_node_init(&path->fp_node, FIB_NODE_TYPE_PATH);
    1504        6346 :     path->fp_oper_flags     = FIB_PATH_OPER_FLAG_NONE;
    1505        6346 :     path->fp_pl_index  = path_list_index;
    1506        6346 :     path->fp_via_fib   = FIB_NODE_INDEX_INVALID;
    1507        6346 :     clib_memset(&path->fp_dpo, 0, sizeof(path->fp_dpo));
    1508        6346 :     dpo_reset(&path->fp_dpo);
    1509             : 
    1510        6346 :     if (path->fp_type == FIB_PATH_TYPE_EXCLUSIVE)
    1511             :     {
    1512           0 :         clib_memset(&path->exclusive.fp_ex_dpo, 0, sizeof(dpo_id_t));
    1513           0 :         dpo_copy(&path->exclusive.fp_ex_dpo, &orig_path->exclusive.fp_ex_dpo);
    1514             :     }
    1515             : 
    1516        6346 :     return (fib_path_get_index(path));
    1517             : }
    1518             : 
    1519             : /*
    1520             :  * fib_path_destroy
    1521             :  *
    1522             :  * destroy a path that is no longer required
    1523             :  */
    1524             : void
    1525       93243 : fib_path_destroy (fib_node_index_t path_index)
    1526             : {
    1527             :     fib_path_t *path;
    1528             : 
    1529       93243 :     path = fib_path_get(path_index);
    1530             : 
    1531       93243 :     ASSERT(NULL != path);
    1532       93243 :     FIB_PATH_DBG(path, "destroy");
    1533             : 
    1534       93243 :     fib_path_unresolve(path);
    1535             : 
    1536       93243 :     fib_node_deinit(&path->fp_node);
    1537       93243 :     pool_put(fib_path_pool, path);
    1538       93243 : }
    1539             : 
    1540             : /*
    1541             :  * fib_path_destroy
    1542             :  *
    1543             :  * destroy a path that is no longer required
    1544             :  */
    1545             : uword
    1546      190363 : fib_path_hash (fib_node_index_t path_index)
    1547             : {
    1548             :     fib_path_t *path;
    1549             : 
    1550      190363 :     path = fib_path_get(path_index);
    1551             : 
    1552      190363 :     return (hash_memory(STRUCT_MARK_PTR(path, path_hash_start),
    1553             :                         (STRUCT_OFFSET_OF(fib_path_t, path_hash_end) -
    1554             :                          STRUCT_OFFSET_OF(fib_path_t, path_hash_start)),
    1555             :                         0));
    1556             : }
    1557             : 
    1558             : /*
    1559             :  * fib_path_cmp_i
    1560             :  *
    1561             :  * Compare two paths for equivalence.
    1562             :  */
    1563             : static int
    1564       86542 : fib_path_cmp_i (const fib_path_t *path1,
    1565             :                 const fib_path_t *path2)
    1566             : {
    1567             :     int res;
    1568             : 
    1569       86542 :     res = 1;
    1570             : 
    1571             :     /*
    1572             :      * paths of different types and protocol are not equal.
    1573             :      * different weights and/or preference only are the same path.
    1574             :      */
    1575       86542 :     if (path1->fp_type != path2->fp_type)
    1576             :     {
    1577           9 :         res = (path1->fp_type - path2->fp_type);
    1578             :     }
    1579       86533 :     else if (path1->fp_nh_proto != path2->fp_nh_proto)
    1580             :     {
    1581           0 :         res = (path1->fp_nh_proto - path2->fp_nh_proto);
    1582             :     }
    1583             :     else
    1584             :     {
    1585             :         /*
    1586             :          * both paths are of the same type.
    1587             :          * consider each type and its attributes in turn.
    1588             :          */
    1589       86533 :         switch (path1->fp_type)
    1590             :         {
    1591        7160 :         case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
    1592        7160 :             res = ip46_address_cmp(&path1->attached_next_hop.fp_nh,
    1593             :                                    &path2->attached_next_hop.fp_nh);
    1594        7160 :             if (0 == res) {
    1595        5925 :                 res = (path1->attached_next_hop.fp_interface -
    1596        5925 :                        path2->attached_next_hop.fp_interface);
    1597             :             }
    1598        7160 :             break;
    1599       77937 :         case FIB_PATH_TYPE_ATTACHED:
    1600       77937 :             res = (path1->attached.fp_interface -
    1601       77937 :                    path2->attached.fp_interface);
    1602       77937 :             break;
    1603        1017 :         case FIB_PATH_TYPE_RECURSIVE:
    1604        1017 :             res = ip46_address_cmp(&path1->recursive.fp_nh.fp_ip,
    1605             :                                    &path2->recursive.fp_nh.fp_ip);
    1606             :  
    1607        1017 :             if (0 == res)
    1608             :             {
    1609          28 :                 res = (path1->recursive.fp_tbl_id - path2->recursive.fp_tbl_id);
    1610             :             }
    1611        1017 :             break;
    1612          90 :         case FIB_PATH_TYPE_BIER_FMASK:
    1613          90 :             res = (path1->bier_fmask.fp_bier_fmask -
    1614          90 :                    path2->bier_fmask.fp_bier_fmask);
    1615          90 :             break;
    1616           0 :         case FIB_PATH_TYPE_BIER_IMP:
    1617           0 :             res = (path1->bier_imp.fp_bier_imp -
    1618           0 :                    path2->bier_imp.fp_bier_imp);
    1619           0 :             break;
    1620         320 :         case FIB_PATH_TYPE_BIER_TABLE:
    1621         320 :             res = bier_table_id_cmp(&path1->bier_table.fp_bier_tbl,
    1622             :                                     &path2->bier_table.fp_bier_tbl);
    1623         320 :             break;
    1624           8 :         case FIB_PATH_TYPE_DEAG:
    1625           8 :             res = (path1->deag.fp_tbl_id - path2->deag.fp_tbl_id);
    1626           8 :             if (0 == res)
    1627             :             {
    1628           8 :                 res = (path1->deag.fp_rpf_id - path2->deag.fp_rpf_id);
    1629             :             }
    1630           8 :             break;
    1631           0 :         case FIB_PATH_TYPE_INTF_RX:
    1632           0 :             res = (path1->intf_rx.fp_interface - path2->intf_rx.fp_interface);
    1633           0 :             break;
    1634           0 :         case FIB_PATH_TYPE_UDP_ENCAP:
    1635           0 :             res = (path1->udp_encap.fp_udp_encap_id - path2->udp_encap.fp_udp_encap_id);
    1636           0 :             break;
    1637           1 :         case FIB_PATH_TYPE_DVR:
    1638           1 :             res = (path1->dvr.fp_interface - path2->dvr.fp_interface);
    1639           1 :             break;
    1640           0 :         case FIB_PATH_TYPE_EXCLUSIVE:
    1641           0 :             res = dpo_cmp(&path1->exclusive.fp_ex_dpo, &path2->exclusive.fp_ex_dpo);
    1642           0 :             break;
    1643           0 :         case FIB_PATH_TYPE_SPECIAL:
    1644             :         case FIB_PATH_TYPE_RECEIVE:
    1645           0 :             res = 0;
    1646           0 :             break;
    1647             :         }
    1648       86542 :     }
    1649       86542 :     return (res);
    1650             : }
    1651             : 
    1652             : /*
    1653             :  * fib_path_cmp_for_sort
    1654             :  *
    1655             :  * Compare two paths for equivalence. Used during path sorting.
    1656             :  * As usual 0 means equal.
    1657             :  */
    1658             : int
    1659       81258 : fib_path_cmp_for_sort (void * v1,
    1660             :                        void * v2)
    1661             : {
    1662       81258 :     fib_node_index_t *pi1 = v1, *pi2 = v2;
    1663             :     fib_path_t *path1, *path2;
    1664             : 
    1665       81258 :     path1 = fib_path_get(*pi1);
    1666       81258 :     path2 = fib_path_get(*pi2);
    1667             : 
    1668             :     /*
    1669             :      * when sorting paths we want the highest preference paths
    1670             :      * first, so that the choices set built is in prefernce order
    1671             :      */
    1672       81258 :     if (path1->fp_preference != path2->fp_preference)
    1673             :     {
    1674        1045 :         return (path1->fp_preference - path2->fp_preference);
    1675             :     }
    1676             : 
    1677       80213 :     return (fib_path_cmp_i(path1, path2));
    1678             : }
    1679             : 
    1680             : /*
    1681             :  * fib_path_cmp
    1682             :  *
    1683             :  * Compare two paths for equivalence.
    1684             :  */
    1685             : int
    1686        6329 : fib_path_cmp (fib_node_index_t pi1,
    1687             :               fib_node_index_t pi2)
    1688             : {
    1689             :     fib_path_t *path1, *path2;
    1690             : 
    1691        6329 :     path1 = fib_path_get(pi1);
    1692        6329 :     path2 = fib_path_get(pi2);
    1693             : 
    1694        6329 :     return (fib_path_cmp_i(path1, path2));
    1695             : }
    1696             : 
    1697             : int
    1698      128483 : fib_path_cmp_w_route_path (fib_node_index_t path_index,
    1699             :                            const fib_route_path_t *rpath)
    1700             : {
    1701             :     fib_path_t *path;
    1702             :     int res;
    1703             : 
    1704      128483 :     path = fib_path_get(path_index);
    1705             : 
    1706      128483 :     res = 1;
    1707             : 
    1708      128483 :     if (path->fp_weight != rpath->frp_weight)
    1709             :     {
    1710          20 :         res = (path->fp_weight - rpath->frp_weight);
    1711             :     }
    1712             :     else
    1713             :     {
    1714             :         /*
    1715             :          * both paths are of the same type.
    1716             :          * consider each type and its attributes in turn.
    1717             :          */
    1718      128463 :         switch (path->fp_type)
    1719             :         {
    1720        9876 :         case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
    1721        9876 :             res = ip46_address_cmp(&path->attached_next_hop.fp_nh,
    1722             :                                    &rpath->frp_addr);
    1723        9876 :             if (0 == res)
    1724             :             {
    1725        9861 :                 res = (path->attached_next_hop.fp_interface -
    1726        9861 :                        rpath->frp_sw_if_index);
    1727             :             }
    1728        9876 :             break;
    1729       63712 :         case FIB_PATH_TYPE_ATTACHED:
    1730       63712 :             res = (path->attached.fp_interface - rpath->frp_sw_if_index);
    1731       63712 :             break;
    1732         222 :         case FIB_PATH_TYPE_RECURSIVE:
    1733         222 :             if (DPO_PROTO_MPLS == path->fp_nh_proto)
    1734             :             {
    1735          13 :                 res = path->recursive.fp_nh.fp_local_label - rpath->frp_local_label;
    1736             : 
    1737          13 :                 if (res == 0)
    1738             :                 {
    1739          11 :                     res = path->recursive.fp_nh.fp_eos - rpath->frp_eos;
    1740             :                 }
    1741             :             }
    1742             :             else
    1743             :             {
    1744         209 :                 res = ip46_address_cmp(&path->recursive.fp_nh.fp_ip,
    1745             :                                        &rpath->frp_addr);
    1746             :             }
    1747             : 
    1748         222 :             if (0 == res)
    1749             :             {
    1750         152 :                 res = (path->recursive.fp_tbl_id - rpath->frp_fib_index);
    1751             :             }
    1752         222 :             break;
    1753           0 :         case FIB_PATH_TYPE_BIER_FMASK:
    1754           0 :             res = (path->bier_fmask.fp_bier_fmask - rpath->frp_bier_fmask);
    1755           0 :             break;
    1756           7 :         case FIB_PATH_TYPE_BIER_IMP:
    1757           7 :             res = (path->bier_imp.fp_bier_imp - rpath->frp_bier_imp);
    1758           7 :             break;
    1759           0 :         case FIB_PATH_TYPE_BIER_TABLE:
    1760           0 :             res = bier_table_id_cmp(&path->bier_table.fp_bier_tbl,
    1761             :                                     &rpath->frp_bier_tbl);
    1762           0 :             break;
    1763           0 :         case FIB_PATH_TYPE_INTF_RX:
    1764           0 :             res = (path->intf_rx.fp_interface - rpath->frp_sw_if_index);
    1765           0 :             break;
    1766           1 :         case FIB_PATH_TYPE_UDP_ENCAP:
    1767           1 :             res = (path->udp_encap.fp_udp_encap_id - rpath->frp_udp_encap_id);
    1768           1 :             break;
    1769           1 :         case FIB_PATH_TYPE_DEAG:
    1770           1 :             res = (path->deag.fp_tbl_id - rpath->frp_fib_index);
    1771           1 :             if (0 == res)
    1772             :             {
    1773           1 :                 res = (path->deag.fp_rpf_id - rpath->frp_rpf_id);
    1774             :             }
    1775           1 :             break;
    1776           0 :         case FIB_PATH_TYPE_DVR:
    1777           0 :             res = (path->dvr.fp_interface - rpath->frp_sw_if_index);
    1778           0 :             break;
    1779           0 :         case FIB_PATH_TYPE_EXCLUSIVE:
    1780           0 :             res = dpo_cmp(&path->exclusive.fp_ex_dpo, &rpath->dpo);
    1781           0 :             break;
    1782       54644 :         case FIB_PATH_TYPE_RECEIVE:
    1783       54644 :             if (rpath->frp_flags & FIB_ROUTE_PATH_LOCAL)
    1784             :             {
    1785         963 :                 res = 0;
    1786             :             }
    1787             :             else
    1788             :             {
    1789       53681 :                 res = 1;
    1790             :             }
    1791       54644 :             break;
    1792           0 :         case FIB_PATH_TYPE_SPECIAL:
    1793           0 :             res = 0;
    1794           0 :             break;
    1795             :         }
    1796      128483 :     }
    1797      128483 :     return (res);
    1798             : }
    1799             : 
    1800             : /*
    1801             :  * fib_path_recursive_loop_detect
    1802             :  *
    1803             :  * A forward walk of the FIB object graph to detect for a cycle/loop. This
    1804             :  * walk is initiated when an entry is linking to a new path list or from an old.
    1805             :  * The entry vector passed contains all the FIB entrys that are children of this
    1806             :  * path (it is all the entries encountered on the walk so far). If this vector
    1807             :  * contains the entry this path resolve via, then a loop is about to form.
    1808             :  * The loop must be allowed to form, since we need the dependencies in place
    1809             :  * so that we can track when the loop breaks.
    1810             :  * However, we MUST not produce a loop in the forwarding graph (else packets
    1811             :  * would loop around the switch path until the loop breaks), so we mark recursive
    1812             :  * paths as looped so that they do not contribute forwarding information.
    1813             :  * By marking the path as looped, an etry such as;
    1814             :  *    X/Y
    1815             :  *     via a.a.a.a (looped)
    1816             :  *     via b.b.b.b (not looped)
    1817             :  * can still forward using the info provided by b.b.b.b only
    1818             :  */
    1819             : int
    1820      117614 : fib_path_recursive_loop_detect (fib_node_index_t path_index,
    1821             :                                 fib_node_index_t **entry_indicies)
    1822             : {
    1823             :     fib_path_t *path;
    1824             : 
    1825      117614 :     path = fib_path_get(path_index);
    1826             : 
    1827             :     /*
    1828             :      * the forced drop path is never looped, cos it is never resolved.
    1829             :      */
    1830      117614 :     if (fib_path_is_permanent_drop(path))
    1831             :     {
    1832       21800 :         return (0);
    1833             :     }
    1834             : 
    1835       95814 :     switch (path->fp_type)
    1836             :     {
    1837        7460 :     case FIB_PATH_TYPE_RECURSIVE:
    1838             :     {
    1839             :         fib_node_index_t *entry_index, *entries;
    1840        7460 :         int looped = 0;
    1841        7460 :         entries = *entry_indicies;
    1842             : 
    1843        7503 :         vec_foreach(entry_index, entries) {
    1844          51 :             if (*entry_index == path->fp_via_fib)
    1845             :             {
    1846             :                 /*
    1847             :                  * the entry that is about to link to this path-list (or
    1848             :                  * one of this path-list's children) is the same entry that
    1849             :                  * this recursive path resolves through. this is a cycle.
    1850             :                  * abort the walk.
    1851             :                  */
    1852           8 :                 looped = 1;
    1853           8 :                 break;
    1854             :             }
    1855             :         }
    1856             : 
    1857        7460 :         if (looped)
    1858             :         {
    1859           8 :             FIB_PATH_DBG(path, "recursive loop formed");
    1860           8 :             path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RECURSIVE_LOOP;
    1861             : 
    1862           8 :             dpo_copy(&path->fp_dpo, drop_dpo_get(path->fp_nh_proto));
    1863             :         }
    1864             :         else
    1865             :         {
    1866             :             /*
    1867             :              * no loop here yet. keep forward walking the graph.
    1868             :              */
    1869        7452 :             if (fib_entry_recursive_loop_detect(path->fp_via_fib, entry_indicies))
    1870             :             {
    1871          12 :                 FIB_PATH_DBG(path, "recursive loop formed");
    1872          12 :                 path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RECURSIVE_LOOP;
    1873             :             }
    1874             :             else
    1875             :             {
    1876        7440 :                 FIB_PATH_DBG(path, "recursive loop cleared");
    1877        7440 :                 path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RECURSIVE_LOOP;
    1878             :             }
    1879             :         }
    1880        7460 :         break;
    1881             :     }
    1882       67813 :     case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
    1883             :     case FIB_PATH_TYPE_ATTACHED:
    1884      135366 :         if (dpo_is_adj(&path->fp_dpo) &&
    1885       67553 :             adj_recursive_loop_detect(path->fp_dpo.dpoi_index,
    1886             :                                       entry_indicies))
    1887             :         {
    1888           1 :             FIB_PATH_DBG(path, "recursive loop formed");
    1889           1 :             path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RECURSIVE_LOOP;
    1890             :         }
    1891             :         else
    1892             :         {
    1893       67812 :             FIB_PATH_DBG(path, "recursive loop cleared");
    1894       67812 :             path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RECURSIVE_LOOP;
    1895             :         }
    1896       67813 :         break;
    1897       20541 :     case FIB_PATH_TYPE_SPECIAL:
    1898             :     case FIB_PATH_TYPE_DEAG:
    1899             :     case FIB_PATH_TYPE_DVR:
    1900             :     case FIB_PATH_TYPE_RECEIVE:
    1901             :     case FIB_PATH_TYPE_INTF_RX:
    1902             :     case FIB_PATH_TYPE_UDP_ENCAP:
    1903             :     case FIB_PATH_TYPE_EXCLUSIVE:
    1904             :     case FIB_PATH_TYPE_BIER_FMASK:
    1905             :     case FIB_PATH_TYPE_BIER_TABLE:
    1906             :     case FIB_PATH_TYPE_BIER_IMP:
    1907             :         /*
    1908             :          * these path types cannot be part of a loop, since they are the leaves
    1909             :          * of the graph.
    1910             :          */
    1911       20541 :         break;
    1912             :     }
    1913             : 
    1914       95814 :     return (fib_path_is_looped(path_index));
    1915             : }
    1916             : 
    1917             : int
    1918       91166 : fib_path_resolve (fib_node_index_t path_index)
    1919             : {
    1920             :     fib_path_t *path;
    1921             : 
    1922       91166 :     path = fib_path_get(path_index);
    1923             : 
    1924             :     /*
    1925             :      * hope for the best.
    1926             :      */
    1927       91166 :     path->fp_oper_flags |= FIB_PATH_OPER_FLAG_RESOLVED;
    1928             : 
    1929             :     /*
    1930             :      * the forced drop path resolves via the drop adj
    1931             :      */
    1932       91166 :     if (fib_path_is_permanent_drop(path))
    1933             :     {
    1934       12284 :         dpo_copy(&path->fp_dpo, drop_dpo_get(path->fp_nh_proto));
    1935       12284 :         path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
    1936       12284 :         return (fib_path_is_resolved(path_index));
    1937             :     }
    1938             : 
    1939       78882 :     switch (path->fp_type)
    1940             :     {
    1941       10417 :     case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
    1942       10417 :         fib_path_attached_next_hop_set(path);
    1943       10417 :         break;
    1944       36511 :     case FIB_PATH_TYPE_ATTACHED:
    1945             :     {
    1946       36511 :         dpo_id_t tmp = DPO_INVALID;
    1947             : 
    1948             :         /*
    1949             :          * path->attached.fp_interface
    1950             :          */
    1951       36511 :         if (!vnet_sw_interface_is_up(vnet_get_main(),
    1952             :                                      path->attached.fp_interface))
    1953             :         {
    1954         727 :             path->fp_oper_flags &= ~FIB_PATH_OPER_FLAG_RESOLVED;
    1955             :         }
    1956       36511 :         fib_path_attached_get_adj(path,
    1957       36511 :                                   dpo_proto_to_link(path->fp_nh_proto),
    1958             :                                   &tmp);
    1959             : 
    1960             :         /*
    1961             :          * re-fetch after possible mem realloc
    1962             :          */
    1963       36511 :         path = fib_path_get(path_index);
    1964       36511 :         dpo_copy(&path->fp_dpo, &tmp);
    1965             : 
    1966             :         /*
    1967             :          * become a child of the adjacency so we receive updates
    1968             :          * when the interface state changes
    1969             :          */
    1970       36511 :         if (dpo_is_adj(&path->fp_dpo))
    1971             :         {
    1972       36147 :             path->fp_sibling = adj_child_add(path->fp_dpo.dpoi_index,
    1973             :                                              FIB_NODE_TYPE_PATH,
    1974             :                                              fib_path_get_index(path));
    1975             :         }
    1976       36511 :         dpo_reset(&tmp);
    1977       36511 :         break;
    1978             :     }
    1979        2133 :     case FIB_PATH_TYPE_RECURSIVE:
    1980             :     {
    1981             :         /*
    1982             :          * Create a RR source entry in the table for the address
    1983             :          * that this path recurses through.
    1984             :          * This resolve action is recursive, hence we may create
    1985             :          * more paths in the process. more creates mean maybe realloc
    1986             :          * of this path.
    1987             :          */
    1988             :         fib_node_index_t fei;
    1989             :         fib_prefix_t pfx;
    1990             : 
    1991        2133 :         ASSERT(FIB_NODE_INDEX_INVALID == path->fp_via_fib);
    1992             : 
    1993        2133 :         if (DPO_PROTO_MPLS == path->fp_nh_proto)
    1994             :         {
    1995          10 :             fib_prefix_from_mpls_label(path->recursive.fp_nh.fp_local_label,
    1996             :                                        path->recursive.fp_nh.fp_eos,
    1997             :                                        &pfx);
    1998             :         }
    1999             :         else
    2000             :         {
    2001        2123 :             ASSERT(!ip46_address_is_zero(&path->recursive.fp_nh.fp_ip));
    2002             : 
    2003        2123 :             fib_protocol_t fp = (ip46_address_is_ip4(&path->recursive.fp_nh.fp_ip) ?
    2004        2123 :                                         FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6);
    2005        2123 :             fib_prefix_from_ip46_addr(fp, &path->recursive.fp_nh.fp_ip, &pfx);
    2006             :         }
    2007             : 
    2008        2133 :         fib_table_lock(path->recursive.fp_tbl_id,
    2009        2133 :                        dpo_proto_to_fib(path->fp_nh_proto),
    2010             :                        FIB_SOURCE_RR);
    2011        2133 :         fei = fib_table_entry_special_add(path->recursive.fp_tbl_id,
    2012             :                                           &pfx,
    2013             :                                           FIB_SOURCE_RR,
    2014             :                                           FIB_ENTRY_FLAG_NONE);
    2015             : 
    2016        2133 :         path = fib_path_get(path_index);
    2017        2133 :         path->fp_via_fib = fei;
    2018             : 
    2019             :         /*
    2020             :          * become a dependent child of the entry so the path is 
    2021             :          * informed when the forwarding for the entry changes.
    2022             :          */
    2023        2133 :         path->fp_sibling = fib_entry_child_add(path->fp_via_fib,
    2024             :                                                FIB_NODE_TYPE_PATH,
    2025             :                                                fib_path_get_index(path));
    2026             : 
    2027             :         /*
    2028             :          * create and configure the IP DPO
    2029             :          */
    2030        2133 :         fib_path_recursive_adj_update(
    2031             :             path,
    2032        2133 :             fib_path_to_chain_type(path),
    2033             :             &path->fp_dpo);
    2034             : 
    2035        2133 :         break;
    2036             :     }
    2037          87 :     case FIB_PATH_TYPE_BIER_FMASK:
    2038             :     {
    2039             :         /*
    2040             :          * become a dependent child of the entry so the path is
    2041             :          * informed when the forwarding for the entry changes.
    2042             :          */
    2043          87 :         path->fp_sibling = bier_fmask_child_add(path->bier_fmask.fp_bier_fmask,
    2044             :                                                 FIB_NODE_TYPE_PATH,
    2045             :                                                 fib_path_get_index(path));
    2046             : 
    2047          87 :         path->fp_via_bier_fmask = path->bier_fmask.fp_bier_fmask;
    2048          87 :         fib_path_bier_fmask_update(path, &path->fp_dpo);
    2049             : 
    2050          87 :         break;
    2051             :     }
    2052           6 :     case FIB_PATH_TYPE_BIER_IMP:
    2053           6 :         bier_imp_lock(path->bier_imp.fp_bier_imp);
    2054           6 :         bier_imp_contribute_forwarding(path->bier_imp.fp_bier_imp,
    2055             :                                        DPO_PROTO_IP4,
    2056             :                                        &path->fp_dpo);
    2057           6 :         break;
    2058         160 :     case FIB_PATH_TYPE_BIER_TABLE:
    2059             :     {
    2060             :         /*
    2061             :          * Find/create the BIER table to link to
    2062             :          */
    2063         160 :         ASSERT(FIB_NODE_INDEX_INVALID == path->fp_via_bier_tbl);
    2064             : 
    2065         160 :         path->fp_via_bier_tbl =
    2066         160 :             bier_table_ecmp_create_and_lock(&path->bier_table.fp_bier_tbl);
    2067             : 
    2068         160 :         bier_table_contribute_forwarding(path->fp_via_bier_tbl,
    2069             :                                          &path->fp_dpo);
    2070         160 :         break;
    2071             :     }
    2072           4 :     case FIB_PATH_TYPE_SPECIAL:
    2073           4 :         if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_ICMP_PROHIBIT)
    2074             :         {
    2075           2 :             ip_null_dpo_add_and_lock (path->fp_nh_proto,
    2076             :                                       IP_NULL_ACTION_SEND_ICMP_PROHIBIT,
    2077             :                                       &path->fp_dpo);
    2078             :         }
    2079           2 :         else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_ICMP_UNREACH)
    2080             :         {
    2081           2 :             ip_null_dpo_add_and_lock (path->fp_nh_proto,
    2082             :                                       IP_NULL_ACTION_SEND_ICMP_UNREACH,
    2083             :                                       &path->fp_dpo);
    2084             :         }
    2085           0 :         else if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_CLASSIFY)
    2086             :         {
    2087           0 :             dpo_set (&path->fp_dpo, DPO_CLASSIFY,
    2088           0 :                      path->fp_nh_proto,
    2089           0 :                      classify_dpo_create (path->fp_nh_proto,
    2090             :                                           path->classify.fp_classify_table_id));
    2091             :         }
    2092             :         else
    2093             :         {
    2094             :             /*
    2095             :              * Resolve via the drop
    2096             :              */
    2097           0 :             dpo_copy(&path->fp_dpo, drop_dpo_get(path->fp_nh_proto));
    2098             :         }
    2099           4 :         break;
    2100          76 :     case FIB_PATH_TYPE_DEAG:
    2101             :     {
    2102          76 :         if (DPO_PROTO_BIER == path->fp_nh_proto)
    2103             :         {
    2104           4 :             bier_disp_table_contribute_forwarding(path->deag.fp_tbl_id,
    2105             :                                                   &path->fp_dpo);
    2106             :         }
    2107             :         else
    2108             :         {
    2109             :             /*
    2110             :              * Resolve via a lookup DPO.
    2111             :              * FIXME. control plane should add routes with a table ID
    2112             :              */
    2113             :             lookup_input_t input;
    2114             :             lookup_cast_t cast;
    2115             : 
    2116          72 :             cast = (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RPF_ID ?
    2117          72 :                     LOOKUP_MULTICAST :
    2118             :                     LOOKUP_UNICAST);
    2119          72 :             input = (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_DEAG_SRC ?
    2120          72 :                      LOOKUP_INPUT_SRC_ADDR :
    2121             :                      LOOKUP_INPUT_DST_ADDR);
    2122             : 
    2123          72 :             lookup_dpo_add_or_lock_w_fib_index(path->deag.fp_tbl_id,
    2124          72 :                                                path->fp_nh_proto,
    2125             :                                                cast,
    2126             :                                                input,
    2127             :                                                LOOKUP_TABLE_FROM_CONFIG,
    2128             :                                                &path->fp_dpo);
    2129             :         }
    2130          76 :         break;
    2131             :     }
    2132           7 :     case FIB_PATH_TYPE_DVR:
    2133           7 :         dvr_dpo_add_or_lock(path->dvr.fp_interface,
    2134           7 :                             path->fp_nh_proto,
    2135             :                             &path->fp_dpo);
    2136           7 :         break;
    2137       21202 :     case FIB_PATH_TYPE_RECEIVE:
    2138             :         /*
    2139             :          * Resolve via a receive DPO.
    2140             :          */
    2141       21202 :         receive_dpo_add_or_lock(path->fp_nh_proto,
    2142             :                                 path->receive.fp_interface,
    2143       21202 :                                 &path->receive.fp_addr,
    2144             :                                 &path->fp_dpo);
    2145       21202 :         break;
    2146          11 :     case FIB_PATH_TYPE_UDP_ENCAP:
    2147          11 :         udp_encap_lock(path->udp_encap.fp_udp_encap_id);
    2148          11 :         udp_encap_contribute_forwarding(path->udp_encap.fp_udp_encap_id,
    2149          11 :                                         path->fp_nh_proto,
    2150             :                                         &path->fp_dpo);
    2151          11 :         break;
    2152           8 :     case FIB_PATH_TYPE_INTF_RX: {
    2153             :         /*
    2154             :          * Resolve via a receive DPO.
    2155             :          */
    2156           8 :         interface_rx_dpo_add_or_lock(path->fp_nh_proto,
    2157             :                                      path->intf_rx.fp_interface,
    2158             :                                      &path->fp_dpo);
    2159           8 :         break;
    2160             :     }
    2161        8260 :     case FIB_PATH_TYPE_EXCLUSIVE:
    2162             :         /*
    2163             :          * Resolve via the user provided DPO
    2164             :          */
    2165        8260 :         dpo_copy(&path->fp_dpo, &path->exclusive.fp_ex_dpo);
    2166        8260 :         break;
    2167             :     }
    2168             : 
    2169       78882 :     return (fib_path_is_resolved(path_index));
    2170             : }
    2171             : 
    2172             : u32
    2173      136478 : fib_path_get_resolving_interface (fib_node_index_t path_index)
    2174             : {
    2175             :     fib_path_t *path;
    2176             : 
    2177      136478 :     path = fib_path_get(path_index);
    2178             : 
    2179      136480 :     switch (path->fp_type)
    2180             :     {
    2181       91000 :     case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
    2182       91000 :         return (path->attached_next_hop.fp_interface);
    2183       38795 :     case FIB_PATH_TYPE_ATTACHED:
    2184       38795 :         return (path->attached.fp_interface);
    2185        2099 :     case FIB_PATH_TYPE_RECEIVE:
    2186        2099 :         return (path->receive.fp_interface);
    2187           1 :     case FIB_PATH_TYPE_RECURSIVE:
    2188           1 :         if (fib_path_is_resolved(path_index))
    2189             :         {
    2190           0 :             return (fib_entry_get_resolving_interface(path->fp_via_fib));
    2191             :         }
    2192           1 :         break;
    2193           0 :     case FIB_PATH_TYPE_DVR:
    2194           0 :         return (path->dvr.fp_interface);
    2195        4585 :     case FIB_PATH_TYPE_INTF_RX:
    2196             :     case FIB_PATH_TYPE_UDP_ENCAP:
    2197             :     case FIB_PATH_TYPE_SPECIAL:
    2198             :     case FIB_PATH_TYPE_DEAG:
    2199             :     case FIB_PATH_TYPE_EXCLUSIVE:
    2200             :     case FIB_PATH_TYPE_BIER_FMASK:
    2201             :     case FIB_PATH_TYPE_BIER_TABLE:
    2202             :     case FIB_PATH_TYPE_BIER_IMP:
    2203        4585 :         break;
    2204             :     }
    2205        4586 :     return (dpo_get_urpf(&path->fp_dpo));
    2206             : }
    2207             : 
    2208             : index_t
    2209        3940 : fib_path_get_resolving_index (fib_node_index_t path_index)
    2210             : {
    2211             :     fib_path_t *path;
    2212             : 
    2213        3940 :     path = fib_path_get(path_index);
    2214             : 
    2215        3940 :     switch (path->fp_type)
    2216             :     {
    2217           0 :     case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
    2218             :     case FIB_PATH_TYPE_ATTACHED:
    2219             :     case FIB_PATH_TYPE_RECEIVE:
    2220             :     case FIB_PATH_TYPE_INTF_RX:
    2221             :     case FIB_PATH_TYPE_SPECIAL:
    2222             :     case FIB_PATH_TYPE_DEAG:
    2223             :     case FIB_PATH_TYPE_DVR:
    2224             :     case FIB_PATH_TYPE_EXCLUSIVE:
    2225           0 :         break;
    2226           0 :     case FIB_PATH_TYPE_UDP_ENCAP:
    2227           0 :         return (path->udp_encap.fp_udp_encap_id);
    2228           0 :     case FIB_PATH_TYPE_RECURSIVE:
    2229           0 :         return (path->fp_via_fib);
    2230         180 :     case FIB_PATH_TYPE_BIER_FMASK:
    2231         180 :         return (path->bier_fmask.fp_bier_fmask);
    2232        3760 :    case FIB_PATH_TYPE_BIER_TABLE:
    2233        3760 :        return (path->fp_via_bier_tbl);
    2234           0 :    case FIB_PATH_TYPE_BIER_IMP:
    2235           0 :        return (path->bier_imp.fp_bier_imp);
    2236             :     }
    2237           0 :     return (~0);
    2238             : }
    2239             : 
    2240             : adj_index_t
    2241        5621 : fib_path_get_adj (fib_node_index_t path_index)
    2242             : {
    2243             :     fib_path_t *path;
    2244             : 
    2245        5621 :     path = fib_path_get(path_index);
    2246             : 
    2247        5621 :     if (dpo_is_adj(&path->fp_dpo))
    2248             :     {
    2249        5523 :         return (path->fp_dpo.dpoi_index);
    2250             :     }
    2251          98 :     return (ADJ_INDEX_INVALID);
    2252             : }
    2253             : 
    2254             : u16
    2255      153003 : fib_path_get_weight (fib_node_index_t path_index)
    2256             : {
    2257             :     fib_path_t *path;
    2258             : 
    2259      153003 :     path = fib_path_get(path_index);
    2260             : 
    2261      153003 :     ASSERT(path);
    2262             : 
    2263      153003 :     return (path->fp_weight);
    2264             : }
    2265             : 
    2266             : u16
    2267       80572 : fib_path_get_preference (fib_node_index_t path_index)
    2268             : {
    2269             :     fib_path_t *path;
    2270             : 
    2271       80572 :     path = fib_path_get(path_index);
    2272             : 
    2273       80572 :     ASSERT(path);
    2274             : 
    2275       80572 :     return (path->fp_preference);
    2276             : }
    2277             : 
    2278             : u32
    2279           6 : fib_path_get_rpf_id (fib_node_index_t path_index)
    2280             : {
    2281             :     fib_path_t *path;
    2282             : 
    2283           6 :     path = fib_path_get(path_index);
    2284             : 
    2285           6 :     ASSERT(path);
    2286             : 
    2287           6 :     if (FIB_PATH_CFG_FLAG_RPF_ID & path->fp_cfg_flags)
    2288             :     {
    2289           6 :         return (path->deag.fp_rpf_id);
    2290             :     }
    2291             : 
    2292           0 :     return (~0);
    2293             : }
    2294             : 
    2295             : /**
    2296             :  * @brief Contribute the path's adjacency to the list passed.
    2297             :  * By calling this function over all paths, recursively, a child
    2298             :  * can construct its full set of forwarding adjacencies, and hence its
    2299             :  * uRPF list.
    2300             :  */
    2301             : void
    2302      139494 : fib_path_contribute_urpf (fib_node_index_t path_index,
    2303             :                           index_t urpf)
    2304             : {
    2305             :     fib_path_t *path;
    2306             : 
    2307      139494 :     path = fib_path_get(path_index);
    2308             : 
    2309             :     /*
    2310             :      * resolved and unresolved paths contribute to the RPF list.
    2311             :      */
    2312      139494 :     switch (path->fp_type)
    2313             :     {
    2314       20001 :     case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
    2315       20001 :         fib_urpf_list_append(urpf, path->attached_next_hop.fp_interface);
    2316       20001 :         break;
    2317             : 
    2318       64626 :     case FIB_PATH_TYPE_ATTACHED:
    2319       64626 :         fib_urpf_list_append(urpf, path->attached.fp_interface);
    2320       64626 :         break;
    2321             : 
    2322        3323 :     case FIB_PATH_TYPE_RECURSIVE:
    2323        6645 :         if (FIB_NODE_INDEX_INVALID != path->fp_via_fib &&
    2324        3322 :             !fib_path_is_looped(path_index))
    2325             :         {
    2326             :             /*
    2327             :              * there's unresolved due to constraints, and there's unresolved
    2328             :              * due to ain't got no via. can't do nowt w'out via.
    2329             :              */
    2330        3306 :             fib_entry_contribute_urpf(path->fp_via_fib, urpf);
    2331             :         }
    2332        3323 :         break;
    2333             : 
    2334       20538 :     case FIB_PATH_TYPE_EXCLUSIVE:
    2335             :     case FIB_PATH_TYPE_SPECIAL:
    2336             :     {
    2337             :         /*
    2338             :          * these path types may link to an adj, if that's what
    2339             :          * the clinet gave
    2340             :          */
    2341             :         u32 rpf_sw_if_index;
    2342             : 
    2343       20538 :         rpf_sw_if_index = dpo_get_urpf(&path->fp_dpo);
    2344             : 
    2345       20538 :         if (~0 != rpf_sw_if_index)
    2346             :         {
    2347          16 :             fib_urpf_list_append(urpf, rpf_sw_if_index);
    2348             :         }
    2349       20538 :         break;
    2350             :     }
    2351           3 :     case FIB_PATH_TYPE_DVR:
    2352           3 :         fib_urpf_list_append(urpf, path->dvr.fp_interface);
    2353           3 :         break;
    2354          10 :     case FIB_PATH_TYPE_UDP_ENCAP:
    2355          10 :         fib_urpf_list_append(urpf, path->udp_encap.fp_udp_encap_id);
    2356          10 :         break;
    2357       30993 :     case FIB_PATH_TYPE_DEAG:
    2358             :     case FIB_PATH_TYPE_RECEIVE:
    2359             :     case FIB_PATH_TYPE_INTF_RX:
    2360             :     case FIB_PATH_TYPE_BIER_FMASK:
    2361             :     case FIB_PATH_TYPE_BIER_TABLE:
    2362             :     case FIB_PATH_TYPE_BIER_IMP:
    2363             :         /*
    2364             :          * these path types don't link to an adj
    2365             :          */
    2366       30993 :         break;
    2367             :     }
    2368      139494 : }
    2369             : 
    2370             : void
    2371        1735 : fib_path_stack_mpls_disp (fib_node_index_t path_index,
    2372             :                           dpo_proto_t payload_proto,
    2373             :                           fib_mpls_lsp_mode_t mode,
    2374             :                           dpo_id_t *dpo)
    2375             : {
    2376             :     fib_path_t *path;
    2377             : 
    2378        1735 :     path = fib_path_get(path_index);
    2379             : 
    2380        1735 :     ASSERT(path);
    2381             : 
    2382        1735 :     switch (path->fp_type)
    2383             :     {
    2384          80 :     case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
    2385             :     {
    2386          80 :         dpo_id_t tmp = DPO_INVALID;
    2387             : 
    2388          80 :         dpo_copy(&tmp, dpo);
    2389             : 
    2390          80 :         mpls_disp_dpo_create(payload_proto, ~0, mode, &tmp, dpo);
    2391          80 :         dpo_reset(&tmp);
    2392          80 :         break;
    2393             :     }                
    2394          10 :     case FIB_PATH_TYPE_DEAG:
    2395             :     {
    2396          10 :         dpo_id_t tmp = DPO_INVALID;
    2397             : 
    2398          10 :         dpo_copy(&tmp, dpo);
    2399             : 
    2400          10 :         mpls_disp_dpo_create(payload_proto,
    2401             :                              path->deag.fp_rpf_id,
    2402             :                              mode, &tmp, dpo);
    2403          10 :         dpo_reset(&tmp);
    2404          10 :         break;
    2405             :     }
    2406        1645 :     case FIB_PATH_TYPE_RECEIVE:
    2407             :     case FIB_PATH_TYPE_ATTACHED:
    2408             :     case FIB_PATH_TYPE_RECURSIVE:
    2409             :     case FIB_PATH_TYPE_INTF_RX:
    2410             :     case FIB_PATH_TYPE_UDP_ENCAP:
    2411             :     case FIB_PATH_TYPE_EXCLUSIVE:
    2412             :     case FIB_PATH_TYPE_SPECIAL:
    2413             :     case FIB_PATH_TYPE_BIER_FMASK:
    2414             :     case FIB_PATH_TYPE_BIER_TABLE:
    2415             :     case FIB_PATH_TYPE_BIER_IMP:
    2416             :     case FIB_PATH_TYPE_DVR:
    2417        1645 :         break;
    2418             :     }
    2419             : 
    2420        1735 :     if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_POP_PW_CW)
    2421             :     {
    2422           1 :         dpo_id_t tmp = DPO_INVALID;
    2423             : 
    2424           1 :         dpo_copy(&tmp, dpo);
    2425             : 
    2426           1 :         pw_cw_dpo_create(&tmp, dpo);
    2427           1 :         dpo_reset(&tmp);
    2428             :     }
    2429        1735 : }
    2430             : 
    2431             : void
    2432      156226 : fib_path_contribute_forwarding (fib_node_index_t path_index,
    2433             :                                 fib_forward_chain_type_t fct,
    2434             :                                 dpo_proto_t payload_proto,
    2435             :                                 dpo_id_t *dpo)
    2436             : {
    2437             :     fib_path_t *path;
    2438             : 
    2439      156226 :     path = fib_path_get(path_index);
    2440             : 
    2441      156226 :     ASSERT(path);
    2442             : 
    2443             :     /*
    2444             :      * The DPO stored in the path was created when the path was resolved.
    2445             :      * This then represents the path's 'native' protocol; IP.
    2446             :      * For all others will need to go find something else.
    2447             :      */
    2448      156226 :     if (fib_path_to_chain_type(path) == fct)
    2449             :     {
    2450       69671 :         dpo_copy(dpo, &path->fp_dpo);
    2451             :     }
    2452             :     else
    2453             :     {
    2454       86555 :         switch (path->fp_type)
    2455             :         {
    2456        1095 :         case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
    2457        1095 :             switch (fct)
    2458             :             {
    2459          67 :             case FIB_FORW_CHAIN_TYPE_MPLS_EOS: {
    2460          67 :                     dpo_id_t tmp = DPO_INVALID;
    2461          67 :                     dpo_copy (&tmp, dpo);
    2462          67 :                     path = fib_path_attached_next_hop_get_adj(
    2463             :                            path,
    2464          67 :                            dpo_proto_to_link(payload_proto),
    2465             :                            &tmp);
    2466          67 :                     dpo_copy (dpo, &tmp);
    2467          67 :                     dpo_reset(&tmp);
    2468          67 :                     break;
    2469             :             }
    2470        1028 :             case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
    2471             :             case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
    2472             :             case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
    2473             :             case FIB_FORW_CHAIN_TYPE_ETHERNET:
    2474             :             case FIB_FORW_CHAIN_TYPE_NSH:
    2475             :             case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
    2476             :             case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
    2477             :                 {
    2478        1028 :                     dpo_id_t tmp = DPO_INVALID;
    2479        1028 :                     dpo_copy (&tmp, dpo);
    2480        1028 :                     path = fib_path_attached_next_hop_get_adj(
    2481             :                            path,
    2482        1028 :                            fib_forw_chain_type_to_link_type(fct),
    2483             :                            &tmp);
    2484        1028 :                     dpo_copy (dpo, &tmp);
    2485        1028 :                     dpo_reset(&tmp);
    2486        1028 :                     break;
    2487             :                 }
    2488           0 :             case FIB_FORW_CHAIN_TYPE_BIER:
    2489           0 :                 break;
    2490             :             }
    2491        1095 :             break;
    2492        2247 :         case FIB_PATH_TYPE_RECURSIVE:
    2493        2247 :             switch (fct)
    2494             :             {
    2495        2247 :             case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
    2496             :             case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
    2497             :             case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
    2498             :             case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
    2499             :             case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
    2500             :             case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
    2501             :             case FIB_FORW_CHAIN_TYPE_BIER:
    2502        2247 :                 fib_path_recursive_adj_update(path, fct, dpo);
    2503        2247 :                 break;
    2504           0 :             case FIB_FORW_CHAIN_TYPE_ETHERNET:
    2505             :             case FIB_FORW_CHAIN_TYPE_NSH:
    2506           0 :                 ASSERT(0);
    2507           0 :                 break;
    2508             :             }
    2509        2247 :             break;
    2510         400 :         case FIB_PATH_TYPE_BIER_TABLE:
    2511         400 :             switch (fct)
    2512             :             {
    2513         400 :             case FIB_FORW_CHAIN_TYPE_BIER:
    2514         400 :                 bier_table_contribute_forwarding(path->fp_via_bier_tbl, dpo);
    2515         400 :                 break;
    2516           0 :             case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
    2517             :             case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
    2518             :             case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
    2519             :             case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
    2520             :             case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
    2521             :             case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
    2522             :             case FIB_FORW_CHAIN_TYPE_ETHERNET:
    2523             :             case FIB_FORW_CHAIN_TYPE_NSH:
    2524           0 :                 ASSERT(0);
    2525           0 :                 break;
    2526             :             }
    2527         400 :             break;
    2528        2505 :         case FIB_PATH_TYPE_BIER_FMASK:
    2529        2505 :             switch (fct)
    2530             :             {
    2531        2505 :             case FIB_FORW_CHAIN_TYPE_BIER:
    2532        2505 :                 fib_path_bier_fmask_update(path, dpo);
    2533        2505 :                 break;
    2534           0 :             case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
    2535             :             case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
    2536             :             case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
    2537             :             case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
    2538             :             case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
    2539             :             case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
    2540             :             case FIB_FORW_CHAIN_TYPE_ETHERNET:
    2541             :             case FIB_FORW_CHAIN_TYPE_NSH:
    2542           0 :                 ASSERT(0);
    2543           0 :                 break;
    2544             :             }
    2545        2505 :             break;
    2546          22 :         case FIB_PATH_TYPE_BIER_IMP:
    2547          22 :             bier_imp_contribute_forwarding(path->bier_imp.fp_bier_imp,
    2548          22 :                                            fib_forw_chain_type_to_dpo_proto(fct),
    2549             :                                            dpo);
    2550          22 :             break;
    2551          11 :         case FIB_PATH_TYPE_DEAG:
    2552          11 :             switch (fct)
    2553             :             {
    2554           2 :             case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
    2555           2 :                 lookup_dpo_add_or_lock_w_table_id(MPLS_FIB_DEFAULT_TABLE_ID,
    2556             :                                                   DPO_PROTO_MPLS,
    2557             :                                                   LOOKUP_UNICAST,
    2558             :                                                   LOOKUP_INPUT_DST_ADDR,
    2559             :                                                   LOOKUP_TABLE_FROM_CONFIG,
    2560             :                                                   dpo);
    2561           2 :                 break;
    2562           9 :             case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
    2563             :             case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
    2564             :             case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
    2565             :             case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
    2566             :             case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
    2567           9 :                 dpo_copy(dpo, &path->fp_dpo);
    2568           9 :                 break;
    2569           0 :             case FIB_FORW_CHAIN_TYPE_BIER:
    2570           0 :                 break;
    2571           0 :             case FIB_FORW_CHAIN_TYPE_ETHERNET:
    2572             :             case FIB_FORW_CHAIN_TYPE_NSH:
    2573           0 :                 ASSERT(0);
    2574           0 :                 break;
    2575             :             }
    2576          11 :             break;
    2577         303 :         case FIB_PATH_TYPE_EXCLUSIVE:
    2578         303 :             dpo_copy(dpo, &path->exclusive.fp_ex_dpo);
    2579         303 :             break;
    2580        3100 :         case FIB_PATH_TYPE_ATTACHED:
    2581        3100 :             switch (fct)
    2582             :             {
    2583           1 :             case FIB_FORW_CHAIN_TYPE_MPLS_EOS:
    2584             :                 /*
    2585             :                  * End of stack traffic via an attacehd path (a glean)
    2586             :                  * must forace an IP lookup so that the IP packet can
    2587             :                  * match against any installed adj-fibs
    2588             :                  */
    2589           1 :                 lookup_dpo_add_or_lock_w_fib_index(
    2590             :                     fib_table_get_index_for_sw_if_index(
    2591           1 :                         dpo_proto_to_fib(payload_proto),
    2592             :                         path->attached.fp_interface),
    2593             :                     payload_proto,
    2594             :                     LOOKUP_UNICAST,
    2595             :                     LOOKUP_INPUT_DST_ADDR,
    2596             :                     LOOKUP_TABLE_FROM_CONFIG,
    2597             :                     dpo);
    2598           1 :                 break;
    2599          10 :             case FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS:
    2600             :             case FIB_FORW_CHAIN_TYPE_UNICAST_IP4:
    2601             :             case FIB_FORW_CHAIN_TYPE_UNICAST_IP6:
    2602             :             case FIB_FORW_CHAIN_TYPE_ETHERNET:
    2603             :             case FIB_FORW_CHAIN_TYPE_NSH:
    2604             :             case FIB_FORW_CHAIN_TYPE_BIER:
    2605          10 :                 fib_path_attached_get_adj(path,
    2606          10 :                                           fib_forw_chain_type_to_link_type(fct),
    2607             :                                           dpo);
    2608          10 :                 break;
    2609        3089 :             case FIB_FORW_CHAIN_TYPE_MCAST_IP4:
    2610             :             case FIB_FORW_CHAIN_TYPE_MCAST_IP6:
    2611             :                 {
    2612             :                     adj_index_t ai;
    2613             : 
    2614             :                     /*
    2615             :                      * Create the adj needed for sending IP multicast traffic
    2616             :                      */
    2617        3089 :                     if (vnet_sw_interface_is_p2p(vnet_get_main(),
    2618             :                                                  path->attached.fp_interface))
    2619             :                     {
    2620             :                         /*
    2621             :                          * point-2-point interfaces do not require a glean, since
    2622             :                          * there is nothing to ARP. Install a rewrite/nbr adj instead
    2623             :                          */
    2624          11 :                         ai = adj_nbr_add_or_lock(dpo_proto_to_fib(path->fp_nh_proto),
    2625          11 :                                                  fib_forw_chain_type_to_link_type(fct),
    2626             :                                                  &zero_addr,
    2627             :                                                  path->attached.fp_interface);
    2628             :                     }
    2629             :                     else
    2630             :                     {
    2631        3078 :                         ai = adj_mcast_add_or_lock(dpo_proto_to_fib(path->fp_nh_proto),
    2632        3078 :                                                    fib_forw_chain_type_to_link_type(fct),
    2633             :                                                    path->attached.fp_interface);
    2634             :                     }
    2635        3089 :                     dpo_set(dpo, DPO_ADJACENCY,
    2636        3089 :                             fib_forw_chain_type_to_dpo_proto(fct),
    2637             :                             ai);
    2638        3089 :                     adj_unlock(ai);
    2639             :                 }
    2640        3089 :                 break;
    2641             :             }
    2642        3100 :             break;
    2643          21 :         case FIB_PATH_TYPE_INTF_RX:
    2644             :             /*
    2645             :              * Create the adj needed for sending IP multicast traffic
    2646             :              */
    2647          21 :             interface_rx_dpo_add_or_lock(payload_proto,
    2648             :                                          path->intf_rx.fp_interface,
    2649             :                                          dpo);
    2650          21 :             break;
    2651           2 :         case FIB_PATH_TYPE_UDP_ENCAP:
    2652           2 :             udp_encap_contribute_forwarding(path->udp_encap.fp_udp_encap_id,
    2653           2 :                                             path->fp_nh_proto,
    2654             :                                             dpo);
    2655           2 :             break;
    2656       76849 :         case FIB_PATH_TYPE_RECEIVE:
    2657             :         case FIB_PATH_TYPE_SPECIAL:
    2658             :         case FIB_PATH_TYPE_DVR:
    2659       76849 :             dpo_copy(dpo, &path->fp_dpo);
    2660       76849 :             break;
    2661             :         }
    2662      156226 :     }
    2663      156226 : }
    2664             : 
    2665             : load_balance_path_t *
    2666        3221 : fib_path_append_nh_for_multipath_hash (fib_node_index_t path_index,
    2667             :                                        fib_forward_chain_type_t fct,
    2668             :                                        dpo_proto_t payload_proto,
    2669             :                                        load_balance_path_t *hash_key)
    2670             : {
    2671             :     load_balance_path_t *mnh;
    2672             :     fib_path_t *path;
    2673             : 
    2674        3221 :     path = fib_path_get(path_index);
    2675             : 
    2676        3221 :     ASSERT(path);
    2677             : 
    2678        3221 :     vec_add2(hash_key, mnh, 1);
    2679             : 
    2680        3221 :     mnh->path_weight = path->fp_weight;
    2681        3221 :     mnh->path_index = path_index;
    2682             : 
    2683        3221 :     if (fib_path_is_resolved(path_index))
    2684             :     {
    2685        3221 :         fib_path_contribute_forwarding(path_index, fct, payload_proto, &mnh->path_dpo);
    2686             :     }
    2687             :     else
    2688             :     {
    2689           0 :         dpo_copy(&mnh->path_dpo,
    2690           0 :                  drop_dpo_get(fib_forw_chain_type_to_dpo_proto(fct)));
    2691             :     }
    2692        3221 :     return (hash_key);
    2693             : }
    2694             : 
    2695             : int
    2696       80572 : fib_path_is_recursive_constrained (fib_node_index_t path_index)
    2697             : {
    2698             :     fib_path_t *path;
    2699             : 
    2700       80572 :     path = fib_path_get(path_index);
    2701             : 
    2702      105783 :     return ((FIB_PATH_TYPE_RECURSIVE == path->fp_type) &&
    2703       25211 :             ((path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RESOLVE_ATTACHED) ||
    2704       20971 :              (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RESOLVE_HOST)));
    2705             : }
    2706             : 
    2707             : int
    2708        1667 : fib_path_is_exclusive (fib_node_index_t path_index)
    2709             : {
    2710             :     fib_path_t *path;
    2711             : 
    2712        1667 :     path = fib_path_get(path_index);
    2713             : 
    2714        1667 :     return (FIB_PATH_TYPE_EXCLUSIVE == path->fp_type);
    2715             : }
    2716             : 
    2717             : int
    2718        1379 : fib_path_is_deag (fib_node_index_t path_index)
    2719             : {
    2720             :     fib_path_t *path;
    2721             : 
    2722        1379 :     path = fib_path_get(path_index);
    2723             : 
    2724        1379 :     return (FIB_PATH_TYPE_DEAG == path->fp_type);
    2725             : }
    2726             : 
    2727             : int
    2728      396942 : fib_path_is_resolved (fib_node_index_t path_index)
    2729             : {
    2730             :     fib_path_t *path;
    2731             : 
    2732      396942 :     path = fib_path_get(path_index);
    2733             : 
    2734      396942 :     return (dpo_id_is_valid(&path->fp_dpo) &&
    2735      729902 :             (path->fp_oper_flags & FIB_PATH_OPER_FLAG_RESOLVED) &&
    2736     1126840 :             !fib_path_is_looped(path_index) &&
    2737      332991 :             !fib_path_is_permanent_drop(path));
    2738             : }
    2739             : 
    2740             : int
    2741      432128 : fib_path_is_looped (fib_node_index_t path_index)
    2742             : {
    2743             :     fib_path_t *path;
    2744             : 
    2745      432128 :     path = fib_path_get(path_index);
    2746             : 
    2747      432128 :     return (path->fp_oper_flags & FIB_PATH_OPER_FLAG_RECURSIVE_LOOP);
    2748             : }
    2749             : 
    2750             : fib_path_list_walk_rc_t
    2751      235792 : fib_path_encode (fib_node_index_t path_list_index,
    2752             :                  fib_node_index_t path_index,
    2753             :                  const fib_path_ext_t *path_ext,
    2754             :                  void *args)
    2755             : {
    2756      235792 :     fib_path_encode_ctx_t *ctx = args;
    2757             :     fib_route_path_t *rpath;
    2758             :     fib_path_t *path;
    2759             : 
    2760      235792 :     path = fib_path_get(path_index);
    2761      235792 :     if (!path)
    2762           0 :       return (FIB_PATH_LIST_WALK_CONTINUE);
    2763             : 
    2764      235792 :     vec_add2(ctx->rpaths, rpath, 1);
    2765      235792 :     rpath->frp_weight = path->fp_weight;
    2766      235792 :     rpath->frp_preference = path->fp_preference;
    2767      235792 :     rpath->frp_proto = path->fp_nh_proto;
    2768      235792 :     rpath->frp_sw_if_index = ~0;
    2769      235792 :     rpath->frp_fib_index = 0;
    2770             : 
    2771      235792 :     switch (path->fp_type)
    2772             :     {
    2773        8953 :       case FIB_PATH_TYPE_RECEIVE:
    2774        8953 :         rpath->frp_addr = path->receive.fp_addr;
    2775        8953 :         rpath->frp_sw_if_index = path->receive.fp_interface;
    2776        8953 :         rpath->frp_flags |= FIB_ROUTE_PATH_LOCAL;
    2777        8953 :         break;
    2778       13051 :       case FIB_PATH_TYPE_ATTACHED:
    2779       13051 :         rpath->frp_sw_if_index = path->attached.fp_interface;
    2780       13051 :         break;
    2781       57494 :       case FIB_PATH_TYPE_ATTACHED_NEXT_HOP:
    2782       57494 :         rpath->frp_sw_if_index = path->attached_next_hop.fp_interface;
    2783       57494 :         rpath->frp_addr = path->attached_next_hop.fp_nh;
    2784       57494 :         break;
    2785          11 :       case FIB_PATH_TYPE_BIER_FMASK:
    2786          11 :         rpath->frp_bier_fmask = path->bier_fmask.fp_bier_fmask;
    2787          11 :         break;
    2788       28532 :       case FIB_PATH_TYPE_SPECIAL:
    2789       28532 :         break;
    2790          59 :       case FIB_PATH_TYPE_DEAG:
    2791          59 :         rpath->frp_fib_index = path->deag.fp_tbl_id;
    2792          59 :         if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_RPF_ID)
    2793             :         {
    2794          11 :             rpath->frp_flags |= FIB_ROUTE_PATH_RPF_ID;
    2795             :         }
    2796          59 :         break;
    2797      106523 :       case FIB_PATH_TYPE_RECURSIVE:
    2798      106523 :         rpath->frp_addr = path->recursive.fp_nh.fp_ip;
    2799      106523 :         rpath->frp_fib_index = path->recursive.fp_tbl_id;
    2800      106523 :         break;
    2801           2 :       case FIB_PATH_TYPE_DVR:
    2802           2 :           rpath->frp_sw_if_index = path->dvr.fp_interface;
    2803           2 :           rpath->frp_flags |= FIB_ROUTE_PATH_DVR;
    2804           2 :           break;
    2805          18 :       case FIB_PATH_TYPE_UDP_ENCAP:
    2806          18 :           rpath->frp_udp_encap_id = path->udp_encap.fp_udp_encap_id;
    2807          18 :           rpath->frp_flags |= FIB_ROUTE_PATH_UDP_ENCAP;
    2808          18 :           break;
    2809           7 :       case FIB_PATH_TYPE_INTF_RX:
    2810           7 :           rpath->frp_sw_if_index = path->receive.fp_interface;
    2811           7 :           rpath->frp_flags |= FIB_ROUTE_PATH_INTF_RX;
    2812           7 :           break;
    2813       21135 :       case FIB_PATH_TYPE_EXCLUSIVE:
    2814       21135 :         rpath->frp_flags |= FIB_ROUTE_PATH_EXCLUSIVE;
    2815       21142 :       default:
    2816       21142 :         break;
    2817             :     }
    2818             : 
    2819      235792 :     if (path_ext && path_ext->fpe_type == FIB_PATH_EXT_MPLS) 
    2820             :     {
    2821       49099 :         rpath->frp_label_stack = path_ext->fpe_path.frp_label_stack;
    2822             :     }
    2823             : 
    2824      235792 :     if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_DROP)
    2825       28532 :         rpath->frp_flags |= FIB_ROUTE_PATH_DROP;
    2826      235792 :     if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_ICMP_UNREACH)
    2827           6 :         rpath->frp_flags |= FIB_ROUTE_PATH_ICMP_UNREACH;
    2828      235792 :     if (path->fp_cfg_flags & FIB_PATH_CFG_FLAG_ICMP_PROHIBIT)
    2829           2 :         rpath->frp_flags |= FIB_ROUTE_PATH_ICMP_PROHIBIT;
    2830             : 
    2831      235792 :     return (FIB_PATH_LIST_WALK_CONTINUE);
    2832             : }
    2833             : 
    2834             : dpo_proto_t
    2835           0 : fib_path_get_proto (fib_node_index_t path_index)
    2836             : {
    2837             :     fib_path_t *path;
    2838             : 
    2839           0 :     path = fib_path_get(path_index);
    2840             : 
    2841           0 :     return (path->fp_nh_proto);
    2842             : }
    2843             : 
    2844             : void
    2845         575 : fib_path_module_init (void)
    2846             : {
    2847         575 :     fib_node_register_type (FIB_NODE_TYPE_PATH, &fib_path_vft);
    2848         575 :     fib_path_logger = vlib_log_register_class ("fib", "path");
    2849         575 : }
    2850             : 
    2851             : static clib_error_t *
    2852           3 : show_fib_path_command (vlib_main_t * vm,
    2853             :                         unformat_input_t * input,
    2854             :                         vlib_cli_command_t * cmd)
    2855             : {
    2856             :     fib_node_index_t pi;
    2857             :     fib_path_t *path;
    2858             : 
    2859           3 :     if (unformat (input, "%d", &pi))
    2860             :     {
    2861             :         /*
    2862             :          * show one in detail
    2863             :          */
    2864           2 :         if (!pool_is_free_index(fib_path_pool, pi))
    2865             :         {
    2866           1 :             path = fib_path_get(pi);
    2867           1 :             u8 *s = format(NULL, "%U", format_fib_path, pi, 1,
    2868             :                            FIB_PATH_FORMAT_FLAGS_NONE);
    2869           1 :             s = format(s, "\n  children:");
    2870           1 :             s = fib_node_children_format(path->fp_node.fn_children, s);
    2871           1 :             vlib_cli_output (vm, "%v", s);
    2872           1 :             vec_free(s);
    2873             :         }
    2874             :         else
    2875             :         {
    2876           1 :             vlib_cli_output (vm, "path %d invalid", pi);
    2877             :         }
    2878             :     }
    2879             :     else
    2880             :     {
    2881           1 :         vlib_cli_output (vm, "FIB Paths");
    2882          14 :         pool_foreach_index (pi, fib_path_pool)
    2883             :          {
    2884          13 :             vlib_cli_output (vm, "%U", format_fib_path, pi, 0,
    2885             :                              FIB_PATH_FORMAT_FLAGS_NONE);
    2886             :         }
    2887             :     }
    2888             : 
    2889           3 :     return (NULL);
    2890             : }
    2891             : 
    2892      285289 : VLIB_CLI_COMMAND (show_fib_path, static) = {
    2893             :   .path = "show fib paths",
    2894             :   .function = show_fib_path_command,
    2895             :   .short_help = "show fib paths",
    2896             : };

Generated by: LCOV version 1.14