back to topotato report
topotato coverage report
Current view: top level - zebra - zebra_rib.c (source / functions) Hit Total Coverage
Test: test_pim6_bootstrap.py::PIM6Bootstrap Lines: 895 2036 44.0 %
Date: 2023-02-16 02:07:22 Functions: 80 116 69.0 %

          Line data    Source code
       1             : /* Routing Information Base.
       2             :  * Copyright (C) 1997, 98, 99, 2001 Kunihiro Ishiguro
       3             :  *
       4             :  * This file is part of GNU Zebra.
       5             :  *
       6             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the
       8             :  * Free Software Foundation; either version 2, or (at your option) any
       9             :  * later version.
      10             :  *
      11             :  * GNU Zebra is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include <zebra.h>
      22             : 
      23             : #include "command.h"
      24             : #include "if.h"
      25             : #include "linklist.h"
      26             : #include "log.h"
      27             : #include "memory.h"
      28             : #include "mpls.h"
      29             : #include "nexthop.h"
      30             : #include "prefix.h"
      31             : #include "prefix.h"
      32             : #include "routemap.h"
      33             : #include "sockunion.h"
      34             : #include "srcdest_table.h"
      35             : #include "table.h"
      36             : #include "thread.h"
      37             : #include "vrf.h"
      38             : #include "workqueue.h"
      39             : #include "nexthop_group_private.h"
      40             : #include "frr_pthread.h"
      41             : #include "printfrr.h"
      42             : #include "frrscript.h"
      43             : 
      44             : #include "zebra/zebra_router.h"
      45             : #include "zebra/connected.h"
      46             : #include "zebra/debug.h"
      47             : #include "zebra/interface.h"
      48             : #include "zebra/redistribute.h"
      49             : #include "zebra/rib.h"
      50             : #include "zebra/rt.h"
      51             : #include "zebra/zapi_msg.h"
      52             : #include "zebra/zebra_errors.h"
      53             : #include "zebra/zebra_ns.h"
      54             : #include "zebra/zebra_rnh.h"
      55             : #include "zebra/zebra_routemap.h"
      56             : #include "zebra/zebra_vrf.h"
      57             : #include "zebra/zebra_vxlan.h"
      58             : #include "zebra/zapi_msg.h"
      59             : #include "zebra/zebra_dplane.h"
      60             : #include "zebra/zebra_evpn_mh.h"
      61             : #include "zebra/zebra_script.h"
      62             : 
      63           3 : DEFINE_MGROUP(ZEBRA, "zebra");
      64             : 
      65           3 : DEFINE_MTYPE(ZEBRA, RE,       "Route Entry");
      66           3 : DEFINE_MTYPE_STATIC(ZEBRA, RIB_DEST,       "RIB destination");
      67           3 : DEFINE_MTYPE_STATIC(ZEBRA, RIB_UPDATE_CTX, "Rib update context object");
      68           3 : DEFINE_MTYPE_STATIC(ZEBRA, WQ_WRAPPER, "WQ wrapper");
      69             : 
      70             : /*
      71             :  * Event, list, and mutex for delivery of dataplane results
      72             :  */
      73             : static pthread_mutex_t dplane_mutex;
      74             : static struct thread *t_dplane;
      75             : static struct dplane_ctx_list_head rib_dplane_q;
      76             : 
      77          30 : DEFINE_HOOK(rib_update, (struct route_node * rn, const char *reason),
      78             :             (rn, reason));
      79          18 : DEFINE_HOOK(rib_shutdown, (struct route_node * rn), (rn));
      80             : 
      81             : 
      82             : /* Meta Q's specific names */
      83             : enum meta_queue_indexes {
      84             :         META_QUEUE_NHG,
      85             :         META_QUEUE_EVPN,
      86             :         META_QUEUE_EARLY_ROUTE,
      87             :         META_QUEUE_EARLY_LABEL,
      88             :         META_QUEUE_CONNECTED,
      89             :         META_QUEUE_KERNEL,
      90             :         META_QUEUE_STATIC,
      91             :         META_QUEUE_NOTBGP,
      92             :         META_QUEUE_BGP,
      93             :         META_QUEUE_OTHER,
      94             : };
      95             : 
      96             : /* Each route type's string and default distance value. */
      97             : static const struct {
      98             :         int key;
      99             :         uint8_t distance;
     100             :         enum meta_queue_indexes meta_q_map;
     101             : } route_info[ZEBRA_ROUTE_MAX] = {
     102             :         [ZEBRA_ROUTE_NHG] = {ZEBRA_ROUTE_NHG, 255 /* Unneeded for nhg's */,
     103             :                              META_QUEUE_NHG},
     104             :         [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0, META_QUEUE_KERNEL},
     105             :         [ZEBRA_ROUTE_KERNEL] = {ZEBRA_ROUTE_KERNEL, 0, META_QUEUE_KERNEL},
     106             :         [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT, 0, META_QUEUE_CONNECTED},
     107             :         [ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC, 1, META_QUEUE_STATIC},
     108             :         [ZEBRA_ROUTE_RIP] = {ZEBRA_ROUTE_RIP, 120, META_QUEUE_NOTBGP},
     109             :         [ZEBRA_ROUTE_RIPNG] = {ZEBRA_ROUTE_RIPNG, 120, META_QUEUE_NOTBGP},
     110             :         [ZEBRA_ROUTE_OSPF] = {ZEBRA_ROUTE_OSPF, 110, META_QUEUE_NOTBGP},
     111             :         [ZEBRA_ROUTE_OSPF6] = {ZEBRA_ROUTE_OSPF6, 110, META_QUEUE_NOTBGP},
     112             :         [ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115, META_QUEUE_NOTBGP},
     113             :         [ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */,
     114             :                              META_QUEUE_BGP},
     115             :         [ZEBRA_ROUTE_PIM] = {ZEBRA_ROUTE_PIM, 255, META_QUEUE_OTHER},
     116             :         [ZEBRA_ROUTE_EIGRP] = {ZEBRA_ROUTE_EIGRP, 90, META_QUEUE_NOTBGP},
     117             :         [ZEBRA_ROUTE_NHRP] = {ZEBRA_ROUTE_NHRP, 10, META_QUEUE_NOTBGP},
     118             :         [ZEBRA_ROUTE_HSLS] = {ZEBRA_ROUTE_HSLS, 255, META_QUEUE_OTHER},
     119             :         [ZEBRA_ROUTE_OLSR] = {ZEBRA_ROUTE_OLSR, 255, META_QUEUE_OTHER},
     120             :         [ZEBRA_ROUTE_TABLE] = {ZEBRA_ROUTE_TABLE, 150, META_QUEUE_STATIC},
     121             :         [ZEBRA_ROUTE_LDP] = {ZEBRA_ROUTE_LDP, 150, META_QUEUE_OTHER},
     122             :         [ZEBRA_ROUTE_VNC] = {ZEBRA_ROUTE_VNC, 20, META_QUEUE_BGP},
     123             :         [ZEBRA_ROUTE_VNC_DIRECT] = {ZEBRA_ROUTE_VNC_DIRECT, 20, META_QUEUE_BGP},
     124             :         [ZEBRA_ROUTE_VNC_DIRECT_RH] = {ZEBRA_ROUTE_VNC_DIRECT_RH, 20,
     125             :                                        META_QUEUE_BGP},
     126             :         [ZEBRA_ROUTE_BGP_DIRECT] = {ZEBRA_ROUTE_BGP_DIRECT, 20, META_QUEUE_BGP},
     127             :         [ZEBRA_ROUTE_BGP_DIRECT_EXT] = {ZEBRA_ROUTE_BGP_DIRECT_EXT, 20,
     128             :                                         META_QUEUE_BGP},
     129             :         [ZEBRA_ROUTE_BABEL] = {ZEBRA_ROUTE_BABEL, 100, META_QUEUE_NOTBGP},
     130             :         [ZEBRA_ROUTE_SHARP] = {ZEBRA_ROUTE_SHARP, 150, META_QUEUE_OTHER},
     131             :         [ZEBRA_ROUTE_PBR] = {ZEBRA_ROUTE_PBR, 200, META_QUEUE_OTHER},
     132             :         [ZEBRA_ROUTE_BFD] = {ZEBRA_ROUTE_BFD, 255, META_QUEUE_OTHER},
     133             :         [ZEBRA_ROUTE_OPENFABRIC] = {ZEBRA_ROUTE_OPENFABRIC, 115,
     134             :                                     META_QUEUE_NOTBGP},
     135             :         [ZEBRA_ROUTE_VRRP] = {ZEBRA_ROUTE_VRRP, 255, META_QUEUE_OTHER},
     136             :         [ZEBRA_ROUTE_SRTE] = {ZEBRA_ROUTE_SRTE, 255, META_QUEUE_OTHER},
     137             :         [ZEBRA_ROUTE_ALL] = {ZEBRA_ROUTE_ALL, 255, META_QUEUE_OTHER},
     138             :         /* Any new route type added to zebra, should be mirrored here */
     139             : 
     140             :         /* no entry/default: 150 */
     141             : };
     142             : 
     143             : /* Wrapper struct for nhg workqueue items; a 'ctx' is an incoming update
     144             :  * from the OS, and an 'nhe' is a nhe update.
     145             :  */
     146             : struct wq_nhg_wrapper {
     147             :         int type;
     148             :         union {
     149             :                 struct nhg_ctx *ctx;
     150             :                 struct nhg_hash_entry *nhe;
     151             :         } u;
     152             : };
     153             : 
     154             : #define WQ_NHG_WRAPPER_TYPE_CTX  0x01
     155             : #define WQ_NHG_WRAPPER_TYPE_NHG  0x02
     156             : 
     157             : /* Wrapper structs for evpn/vxlan workqueue items. */
     158             : struct wq_evpn_wrapper {
     159             :         int type;
     160             :         bool add_p;
     161             :         vrf_id_t vrf_id;
     162             :         bool esr_rxed;
     163             :         uint8_t df_alg;
     164             :         uint16_t df_pref;
     165             :         uint32_t flags;
     166             :         uint32_t seq;
     167             :         esi_t esi;
     168             :         vni_t vni;
     169             :         struct ipaddr ip;
     170             :         struct ethaddr macaddr;
     171             :         struct prefix prefix;
     172             :         struct in_addr vtep_ip;
     173             : };
     174             : 
     175             : #define WQ_EVPN_WRAPPER_TYPE_VRFROUTE     0x01
     176             : #define WQ_EVPN_WRAPPER_TYPE_REM_ES       0x02
     177             : #define WQ_EVPN_WRAPPER_TYPE_REM_MACIP    0x03
     178             : #define WQ_EVPN_WRAPPER_TYPE_REM_VTEP     0x04
     179             : 
     180             : enum wq_label_types {
     181             :         WQ_LABEL_FTN_UNINSTALL,
     182             :         WQ_LABEL_LABELS_PROCESS,
     183             : };
     184             : 
     185             : struct wq_label_wrapper {
     186             :         enum wq_label_types type;
     187             :         vrf_id_t vrf_id;
     188             : 
     189             :         struct prefix p;
     190             :         enum lsp_types_t ltype;
     191             :         uint8_t route_type;
     192             :         uint8_t route_instance;
     193             : 
     194             :         bool add_p;
     195             :         struct zapi_labels zl;
     196             : 
     197             :         int afi;
     198             : };
     199             : 
     200             : static void rib_addnode(struct route_node *rn, struct route_entry *re,
     201             :                         int process);
     202             : 
     203             : /* %pRN is already a printer for route_nodes that just prints the prefix */
     204             : #ifdef _FRR_ATTRIBUTE_PRINTFRR
     205             : #pragma FRR printfrr_ext "%pZN" (struct route_node *)
     206             : #endif
     207             : 
     208          40 : static const char *subqueue2str(enum meta_queue_indexes index)
     209             : {
     210          32 :         switch (index) {
     211             :         case META_QUEUE_NHG:
     212             :                 return "NHG Objects";
     213           0 :         case META_QUEUE_EVPN:
     214           0 :                 return "EVPN/VxLan Objects";
     215           0 :         case META_QUEUE_EARLY_ROUTE:
     216           0 :                 return "Early Route Processing";
     217           0 :         case META_QUEUE_EARLY_LABEL:
     218           0 :                 return "Early Label Handling";
     219          32 :         case META_QUEUE_CONNECTED:
     220          32 :                 return "Connected Routes";
     221           0 :         case META_QUEUE_KERNEL:
     222           0 :                 return "Kernel Routes";
     223           0 :         case META_QUEUE_STATIC:
     224           0 :                 return "Static Routes";
     225           0 :         case META_QUEUE_NOTBGP:
     226           0 :                 return "RIP/OSPF/ISIS/EIGRP/NHRP Routes";
     227           0 :         case META_QUEUE_BGP:
     228           0 :                 return "BGP Routes";
     229           0 :         case META_QUEUE_OTHER:
     230           0 :                 return "Other Routes";
     231             :         }
     232             : 
     233           0 :         return "Unknown";
     234             : }
     235             : 
     236           1 : printfrr_ext_autoreg_p("ZN", printfrr_zebra_node);
     237         124 : static ssize_t printfrr_zebra_node(struct fbuf *buf, struct printfrr_eargs *ea,
     238             :                                    const void *ptr)
     239             : {
     240         124 :         struct route_node *rn = (struct route_node *)ptr;
     241         124 :         ssize_t rv = 0;
     242             : 
     243             :         /* just the table number? */
     244         124 :         if (ea->fmt[0] == 't') {
     245          62 :                 rib_dest_t *dest;
     246          62 :                 struct route_entry *re = NULL;
     247             : 
     248          62 :                 ea->fmt++;
     249             : 
     250          62 :                 if (!rn)
     251           0 :                         return bputch(buf, '!');
     252             : 
     253          62 :                 dest = rib_dest_from_rnode(rn);
     254          62 :                 if (dest)
     255          34 :                         re = re_list_first(&dest->routes);
     256          34 :                 if (re)
     257          34 :                         rv += bprintfrr(buf, "%u", re->table);
     258             :                 else
     259          28 :                         rv += bputch(buf, '?');
     260             : 
     261             :         } else {
     262          62 :                 char cbuf[PREFIX_STRLEN * 2 + 6];
     263          62 :                 struct rib_table_info *info;
     264             : 
     265          62 :                 if (!rn)
     266           0 :                         return bputs(buf, "{(route_node *) NULL}");
     267             : 
     268          62 :                 srcdest_rnode2str(rn, cbuf, sizeof(cbuf));
     269          62 :                 rv += bputs(buf, cbuf);
     270             : 
     271          62 :                 info = srcdest_rnode_table_info(rn);
     272          62 :                 if (info->safi == SAFI_MULTICAST)
     273          31 :                         rv += bputs(buf, " (MRIB)");
     274             :         }
     275             :         return rv;
     276             : }
     277             : 
     278             : #define rnode_debug(node, vrf_id, msg, ...)                                    \
     279             :         zlog_debug("%s: (%u:%pZNt):%pZN: " msg, __func__, vrf_id, node, node,  \
     280             :                    ##__VA_ARGS__)
     281             : 
     282             : #define rnode_info(node, vrf_id, msg, ...)                                     \
     283             :         zlog_info("%s: (%u:%pZNt):%pZN: " msg, __func__, vrf_id, node, node,   \
     284             :                   ##__VA_ARGS__)
     285             : 
     286          34 : static char *_dump_re_status(const struct route_entry *re, char *buf,
     287             :                              size_t len)
     288             : {
     289          34 :         if (re->status == 0) {
     290          17 :                 snprintfrr(buf, len, "None ");
     291          17 :                 return buf;
     292             :         }
     293             : 
     294         153 :         snprintfrr(
     295             :                 buf, len, "%s%s%s%s%s%s%s%s",
     296          17 :                 CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED) ? "Removed " : "",
     297          17 :                 CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED) ? "Changed " : "",
     298          17 :                 CHECK_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED)
     299             :                         ? "Label Changed "
     300             :                         : "",
     301          17 :                 CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED) ? "Queued " : "",
     302          17 :                 CHECK_FLAG(re->status, ROUTE_ENTRY_ROUTE_REPLACING)
     303             :                         ? "Replacing"
     304             :                         : "",
     305          17 :                 CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED) ? "Installed "
     306             :                                                               : "",
     307          17 :                 CHECK_FLAG(re->status, ROUTE_ENTRY_FAILED) ? "Failed " : "",
     308          17 :                 CHECK_FLAG(re->status, ROUTE_ENTRY_USE_FIB_NHG) ? "Fib NHG "
     309             :                                                                 : "");
     310          17 :         return buf;
     311             : }
     312             : 
     313          16 : uint8_t route_distance(int type)
     314             : {
     315          16 :         uint8_t distance;
     316             : 
     317           0 :         if ((unsigned)type >= array_size(route_info))
     318             :                 distance = 150;
     319             :         else
     320          16 :                 distance = route_info[type].distance;
     321             : 
     322          16 :         return distance;
     323             : }
     324             : 
     325          16 : int is_zebra_valid_kernel_table(uint32_t table_id)
     326             : {
     327             : #ifdef linux
     328          16 :         if ((table_id == RT_TABLE_UNSPEC) || (table_id == RT_TABLE_LOCAL)
     329          16 :             || (table_id == RT_TABLE_COMPAT))
     330           0 :                 return 0;
     331             : #endif
     332             : 
     333             :         return 1;
     334             : }
     335             : 
     336           0 : int is_zebra_main_routing_table(uint32_t table_id)
     337             : {
     338           0 :         if (table_id == RT_TABLE_MAIN)
     339           0 :                 return 1;
     340             :         return 0;
     341             : }
     342             : 
     343          18 : int zebra_check_addr(const struct prefix *p)
     344             : {
     345          18 :         if (p->family == AF_INET) {
     346           7 :                 uint32_t addr;
     347             : 
     348           7 :                 addr = p->u.prefix4.s_addr;
     349           7 :                 addr = ntohl(addr);
     350             : 
     351           7 :                 if (IPV4_NET127(addr) || IN_CLASSD(addr)
     352           7 :                     || IPV4_LINKLOCAL(addr))
     353             :                         return 0;
     354             :         }
     355          18 :         if (p->family == AF_INET6) {
     356          11 :                 if (IN6_IS_ADDR_LOOPBACK(&p->u.prefix6))
     357             :                         return 0;
     358          11 :                 if (IN6_IS_ADDR_LINKLOCAL(&p->u.prefix6))
     359             :                         return 0;
     360             :         }
     361             :         return 1;
     362             : }
     363             : 
     364          32 : static void route_entry_attach_ref(struct route_entry *re,
     365             :                                    struct nhg_hash_entry *new)
     366             : {
     367          32 :         re->nhe = new;
     368          32 :         re->nhe_id = new->id;
     369          32 :         re->nhe_installed_id = 0;
     370             : 
     371          32 :         zebra_nhg_increment_ref(new);
     372          16 : }
     373             : 
     374             : /* Replace (if 'new_nhghe') or clear (if that's NULL) an re's nhe. */
     375          48 : int route_entry_update_nhe(struct route_entry *re,
     376             :                            struct nhg_hash_entry *new_nhghe)
     377             : {
     378          48 :         int ret = 0;
     379          48 :         struct nhg_hash_entry *old_nhg = NULL;
     380             : 
     381          48 :         if (new_nhghe == NULL) {
     382          16 :                 old_nhg = re->nhe;
     383             : 
     384          16 :                 re->nhe_id = 0;
     385          16 :                 re->nhe_installed_id = 0;
     386          16 :                 re->nhe = NULL;
     387          16 :                 goto done;
     388             :         }
     389             : 
     390          32 :         if ((re->nhe_id != 0) && re->nhe && (re->nhe != new_nhghe)) {
     391             :                 /* Capture previous nhg, if any */
     392          16 :                 old_nhg = re->nhe;
     393             : 
     394          16 :                 route_entry_attach_ref(re, new_nhghe);
     395          16 :         } else if (!re->nhe)
     396             :                 /* This is the first time it's being attached */
     397          96 :                 route_entry_attach_ref(re, new_nhghe);
     398             : 
     399           0 : done:
     400             :         /* Detach / deref previous nhg */
     401          48 :         if (old_nhg)
     402          32 :                 zebra_nhg_decrement_ref(old_nhg);
     403             : 
     404          48 :         return ret;
     405             : }
     406             : 
     407           0 : void rib_handle_nhg_replace(struct nhg_hash_entry *old_entry,
     408             :                             struct nhg_hash_entry *new_entry)
     409             : {
     410           0 :         struct zebra_router_table *zrt;
     411           0 :         struct route_node *rn;
     412           0 :         struct route_entry *re, *next;
     413             : 
     414           0 :         if (IS_ZEBRA_DEBUG_RIB_DETAILED || IS_ZEBRA_DEBUG_NHG_DETAIL)
     415           0 :                 zlog_debug("%s: replacing routes nhe (%u) OLD %p NEW %p",
     416             :                            __func__, new_entry->id, new_entry, old_entry);
     417             : 
     418             :         /* We have to do them ALL */
     419           0 :         RB_FOREACH (zrt, zebra_router_table_head, &zrouter.tables) {
     420           0 :                 for (rn = route_top(zrt->table); rn;
     421           0 :                      rn = srcdest_route_next(rn)) {
     422           0 :                         RNODE_FOREACH_RE_SAFE (rn, re, next) {
     423           0 :                                 if (re->nhe && re->nhe == old_entry)
     424           0 :                                         route_entry_update_nhe(re, new_entry);
     425             :                         }
     426             :                 }
     427             :         }
     428           0 : }
     429             : 
     430           0 : struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id,
     431             :                               const union g_addr *addr,
     432             :                               struct route_node **rn_out)
     433             : {
     434           0 :         struct prefix p;
     435           0 :         struct route_table *table;
     436           0 :         struct route_node *rn;
     437           0 :         struct route_entry *match = NULL;
     438             : 
     439             :         /* Lookup table.  */
     440           0 :         table = zebra_vrf_table(afi, safi, vrf_id);
     441           0 :         if (!table)
     442             :                 return 0;
     443             : 
     444           0 :         memset(&p, 0, sizeof(p));
     445           0 :         p.family = afi;
     446           0 :         if (afi == AFI_IP) {
     447           0 :                 p.u.prefix4 = addr->ipv4;
     448           0 :                 p.prefixlen = IPV4_MAX_BITLEN;
     449             :         } else {
     450           0 :                 p.u.prefix6 = addr->ipv6;
     451           0 :                 p.prefixlen = IPV6_MAX_BITLEN;
     452             :         }
     453             : 
     454           0 :         rn = route_node_match(table, &p);
     455             : 
     456           0 :         while (rn) {
     457           0 :                 rib_dest_t *dest;
     458             : 
     459           0 :                 route_unlock_node(rn);
     460             : 
     461           0 :                 dest = rib_dest_from_rnode(rn);
     462           0 :                 if (dest && dest->selected_fib
     463           0 :                     && !CHECK_FLAG(dest->selected_fib->status,
     464             :                                    ROUTE_ENTRY_REMOVED))
     465           0 :                         match = dest->selected_fib;
     466             : 
     467             :                 /* If there is no selected route or matched route is EGP, go up
     468             :                    tree. */
     469           0 :                 if (!match) {
     470           0 :                         do {
     471           0 :                                 rn = rn->parent;
     472           0 :                         } while (rn && rn->info == NULL);
     473           0 :                         if (rn)
     474           0 :                                 route_lock_node(rn);
     475             :                 } else {
     476           0 :                         if (match->type != ZEBRA_ROUTE_CONNECT) {
     477           0 :                                 if (!CHECK_FLAG(match->status,
     478             :                                                 ROUTE_ENTRY_INSTALLED))
     479             :                                         return NULL;
     480             :                         }
     481             : 
     482           0 :                         if (rn_out)
     483           0 :                                 *rn_out = rn;
     484           0 :                         return match;
     485             :                 }
     486             :         }
     487             :         return NULL;
     488             : }
     489             : 
     490           0 : struct route_entry *rib_match_ipv4_multicast(vrf_id_t vrf_id,
     491             :                                              struct in_addr addr,
     492             :                                              struct route_node **rn_out)
     493             : {
     494           0 :         struct route_entry *re = NULL, *mre = NULL, *ure = NULL;
     495           0 :         struct route_node *m_rn = NULL, *u_rn = NULL;
     496           0 :         union g_addr gaddr = {.ipv4 = addr};
     497             : 
     498           0 :         switch (zrouter.ipv4_multicast_mode) {
     499           0 :         case MCAST_MRIB_ONLY:
     500           0 :                 return rib_match(AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr,
     501             :                                  rn_out);
     502           0 :         case MCAST_URIB_ONLY:
     503           0 :                 return rib_match(AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, rn_out);
     504           0 :         case MCAST_NO_CONFIG:
     505             :         case MCAST_MIX_MRIB_FIRST:
     506           0 :                 re = mre = rib_match(AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr,
     507             :                                      &m_rn);
     508           0 :                 if (!mre)
     509           0 :                         re = ure = rib_match(AFI_IP, SAFI_UNICAST, vrf_id,
     510             :                                              &gaddr, &u_rn);
     511             :                 break;
     512           0 :         case MCAST_MIX_DISTANCE:
     513           0 :                 mre = rib_match(AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn);
     514           0 :                 ure = rib_match(AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, &u_rn);
     515           0 :                 if (mre && ure)
     516           0 :                         re = ure->distance < mre->distance ? ure : mre;
     517           0 :                 else if (mre)
     518             :                         re = mre;
     519           0 :                 else if (ure)
     520           0 :                         re = ure;
     521             :                 break;
     522           0 :         case MCAST_MIX_PFXLEN:
     523           0 :                 mre = rib_match(AFI_IP, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn);
     524           0 :                 ure = rib_match(AFI_IP, SAFI_UNICAST, vrf_id, &gaddr, &u_rn);
     525           0 :                 if (mre && ure)
     526           0 :                         re = u_rn->p.prefixlen > m_rn->p.prefixlen ? ure : mre;
     527           0 :                 else if (mre)
     528             :                         re = mre;
     529           0 :                 else if (ure)
     530           0 :                         re = ure;
     531             :                 break;
     532             :         }
     533             : 
     534           0 :         if (rn_out)
     535           0 :                 *rn_out = (re == mre) ? m_rn : u_rn;
     536             : 
     537           0 :         if (IS_ZEBRA_DEBUG_RIB) {
     538           0 :                 char buf[BUFSIZ];
     539           0 :                 inet_ntop(AF_INET, &addr, buf, BUFSIZ);
     540             : 
     541           0 :                 zlog_debug("%s: %s: vrf: %s(%u) found %s, using %s", __func__,
     542             :                            buf, vrf_id_to_name(vrf_id), vrf_id,
     543             :                            mre ? (ure ? "MRIB+URIB" : "MRIB")
     544             :                                : ure ? "URIB" : "nothing",
     545             :                            re == ure ? "URIB" : re == mre ? "MRIB" : "none");
     546             :         }
     547             :         return re;
     548             : }
     549             : 
     550           0 : struct route_entry *rib_match_ipv6_multicast(vrf_id_t vrf_id,
     551             :                                              struct in6_addr addr,
     552             :                                              struct route_node **rn_out)
     553             : {
     554           0 :         struct route_entry *re = NULL, *mre = NULL, *ure = NULL;
     555           0 :         struct route_node *m_rn = NULL, *u_rn = NULL;
     556           0 :         union g_addr gaddr = {.ipv6 = addr};
     557             : 
     558           0 :         switch (zrouter.ipv4_multicast_mode) {
     559           0 :         case MCAST_MRIB_ONLY:
     560           0 :                 return rib_match(AFI_IP6, SAFI_MULTICAST, vrf_id, &gaddr,
     561             :                                  rn_out);
     562           0 :         case MCAST_URIB_ONLY:
     563           0 :                 return rib_match(AFI_IP6, SAFI_UNICAST, vrf_id, &gaddr, rn_out);
     564           0 :         case MCAST_NO_CONFIG:
     565             :         case MCAST_MIX_MRIB_FIRST:
     566           0 :                 re = mre = rib_match(AFI_IP6, SAFI_MULTICAST, vrf_id, &gaddr,
     567             :                                      &m_rn);
     568           0 :                 if (!mre)
     569           0 :                         re = ure = rib_match(AFI_IP6, SAFI_UNICAST, vrf_id,
     570             :                                              &gaddr, &u_rn);
     571             :                 break;
     572           0 :         case MCAST_MIX_DISTANCE:
     573           0 :                 mre = rib_match(AFI_IP6, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn);
     574           0 :                 ure = rib_match(AFI_IP6, SAFI_UNICAST, vrf_id, &gaddr, &u_rn);
     575           0 :                 if (mre && ure)
     576           0 :                         re = ure->distance < mre->distance ? ure : mre;
     577           0 :                 else if (mre)
     578             :                         re = mre;
     579           0 :                 else if (ure)
     580           0 :                         re = ure;
     581             :                 break;
     582           0 :         case MCAST_MIX_PFXLEN:
     583           0 :                 mre = rib_match(AFI_IP6, SAFI_MULTICAST, vrf_id, &gaddr, &m_rn);
     584           0 :                 ure = rib_match(AFI_IP6, SAFI_UNICAST, vrf_id, &gaddr, &u_rn);
     585           0 :                 if (mre && ure)
     586           0 :                         re = u_rn->p.prefixlen > m_rn->p.prefixlen ? ure : mre;
     587           0 :                 else if (mre)
     588             :                         re = mre;
     589           0 :                 else if (ure)
     590           0 :                         re = ure;
     591             :                 break;
     592             :         }
     593             : 
     594           0 :         if (rn_out)
     595           0 :                 *rn_out = (re == mre) ? m_rn : u_rn;
     596             : 
     597           0 :         if (IS_ZEBRA_DEBUG_RIB)
     598           0 :                 zlog_debug("%s: %pI6: vrf: %s(%u) found %s, using %s", __func__,
     599             :                            &addr, vrf_id_to_name(vrf_id), vrf_id,
     600             :                            mre ? (ure ? "MRIB+URIB" : "MRIB")
     601             :                                : ure ? "URIB" : "nothing",
     602             :                            re == ure ? "URIB" : re == mre ? "MRIB" : "none");
     603             :         return re;
     604             : }
     605             : 
     606           0 : struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id)
     607             : {
     608           0 :         struct route_table *table;
     609           0 :         struct route_node *rn;
     610           0 :         struct route_entry *match = NULL;
     611           0 :         rib_dest_t *dest;
     612             : 
     613             :         /* Lookup table.  */
     614           0 :         table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
     615           0 :         if (!table)
     616             :                 return 0;
     617             : 
     618           0 :         rn = route_node_lookup(table, (struct prefix *)p);
     619             : 
     620             :         /* No route for this prefix. */
     621           0 :         if (!rn)
     622             :                 return NULL;
     623             : 
     624             :         /* Unlock node. */
     625           0 :         route_unlock_node(rn);
     626           0 :         dest = rib_dest_from_rnode(rn);
     627             : 
     628           0 :         if (dest && dest->selected_fib
     629           0 :             && !CHECK_FLAG(dest->selected_fib->status, ROUTE_ENTRY_REMOVED))
     630           0 :                 match = dest->selected_fib;
     631             : 
     632           0 :         if (!match)
     633             :                 return NULL;
     634             : 
     635           0 :         if (match->type == ZEBRA_ROUTE_CONNECT)
     636             :                 return match;
     637             : 
     638           0 :         if (CHECK_FLAG(match->status, ROUTE_ENTRY_INSTALLED))
     639             :                 return match;
     640             : 
     641             :         return NULL;
     642             : }
     643             : 
     644             : /*
     645             :  * Is this RIB labeled-unicast? It must be of type BGP and all paths
     646             :  * (nexthops) must have a label.
     647             :  */
     648          15 : int zebra_rib_labeled_unicast(struct route_entry *re)
     649             : {
     650          15 :         struct nexthop *nexthop = NULL;
     651             : 
     652          15 :         if (re->type != ZEBRA_ROUTE_BGP)
     653             :                 return 0;
     654             : 
     655           0 :         for (ALL_NEXTHOPS(re->nhe->nhg, nexthop))
     656           0 :                 if (!nexthop->nh_label || !nexthop->nh_label->num_labels)
     657             :                         return 0;
     658             : 
     659             :         return 1;
     660             : }
     661             : 
     662             : /* Update flag indicates whether this is a "replace" or not. Currently, this
     663             :  * is only used for IPv4.
     664             :  */
     665          16 : void rib_install_kernel(struct route_node *rn, struct route_entry *re,
     666             :                         struct route_entry *old)
     667             : {
     668          16 :         struct nexthop *nexthop;
     669          16 :         struct rib_table_info *info = srcdest_rnode_table_info(rn);
     670          16 :         struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id);
     671          16 :         const struct prefix *p, *src_p;
     672          16 :         enum zebra_dplane_result ret;
     673             : 
     674          16 :         rib_dest_t *dest = rib_dest_from_rnode(rn);
     675             : 
     676          16 :         srcdest_rnode_prefixes(rn, &p, &src_p);
     677             : 
     678          16 :         if (info->safi != SAFI_UNICAST) {
     679          16 :                 for (ALL_NEXTHOPS(re->nhe->nhg, nexthop))
     680           8 :                         SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
     681             :                 return;
     682             :         }
     683             : 
     684             : 
     685             :         /*
     686             :          * Install the resolved nexthop object first.
     687             :          */
     688           8 :         zebra_nhg_install_kernel(re->nhe);
     689             : 
     690             :         /*
     691             :          * If this is a replace to a new RE let the originator of the RE
     692             :          * know that they've lost
     693             :          */
     694           8 :         if (old && (old != re) && (old->type != re->type))
     695           0 :                 zsend_route_notify_owner(rn, old, ZAPI_ROUTE_BETTER_ADMIN_WON,
     696             :                                          info->afi, info->safi);
     697             : 
     698             :         /* Update fib selection */
     699           8 :         dest->selected_fib = re;
     700             : 
     701             :         /*
     702             :          * Make sure we update the FPM any time we send new information to
     703             :          * the kernel.
     704             :          */
     705           8 :         hook_call(rib_update, rn, "installing in kernel");
     706             : 
     707             :         /* Send add or update */
     708           8 :         if (old)
     709           0 :                 ret = dplane_route_update(rn, re, old);
     710             :         else
     711           8 :                 ret = dplane_route_add(rn, re);
     712             : 
     713           8 :         switch (ret) {
     714           8 :         case ZEBRA_DPLANE_REQUEST_QUEUED:
     715           8 :                 SET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
     716             : 
     717           8 :                 if (old) {
     718           0 :                         SET_FLAG(old->status, ROUTE_ENTRY_QUEUED);
     719           0 :                         SET_FLAG(re->status, ROUTE_ENTRY_ROUTE_REPLACING);
     720             : 
     721             :                         /* Free old FIB nexthop group */
     722           0 :                         UNSET_FLAG(old->status, ROUTE_ENTRY_USE_FIB_NHG);
     723           0 :                         if (old->fib_ng.nexthop) {
     724           0 :                                 nexthops_free(old->fib_ng.nexthop);
     725           0 :                                 old->fib_ng.nexthop = NULL;
     726             :                         }
     727             :                 }
     728             : 
     729           8 :                 if (zvrf)
     730           8 :                         zvrf->installs_queued++;
     731             :                 break;
     732           0 :         case ZEBRA_DPLANE_REQUEST_FAILURE:
     733             :         {
     734           0 :                 flog_err(EC_ZEBRA_DP_INSTALL_FAIL,
     735             :                          "%u:%u:%pRN: Failed to enqueue dataplane install",
     736             :                          re->vrf_id, re->table, rn);
     737           0 :                 break;
     738             :         }
     739           0 :         case ZEBRA_DPLANE_REQUEST_SUCCESS:
     740           0 :                 if (zvrf)
     741           0 :                         zvrf->installs++;
     742             :                 break;
     743             :         }
     744             : 
     745             :         return;
     746             : }
     747             : 
     748             : /* Uninstall the route from kernel. */
     749           7 : void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re)
     750             : {
     751           7 :         struct nexthop *nexthop;
     752           7 :         struct rib_table_info *info = srcdest_rnode_table_info(rn);
     753           7 :         struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id);
     754             : 
     755           7 :         if (info->safi != SAFI_UNICAST) {
     756           0 :                 UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
     757           0 :                 for (ALL_NEXTHOPS(re->nhe->nhg, nexthop))
     758           0 :                         UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
     759             :                 return;
     760             :         }
     761             : 
     762             :         /*
     763             :          * Make sure we update the FPM any time we send new information to
     764             :          * the dataplane.
     765             :          */
     766           7 :         hook_call(rib_update, rn, "uninstalling from kernel");
     767             : 
     768           7 :         switch (dplane_route_delete(rn, re)) {
     769           7 :         case ZEBRA_DPLANE_REQUEST_QUEUED:
     770           7 :                 if (zvrf)
     771           7 :                         zvrf->removals_queued++;
     772             :                 break;
     773           0 :         case ZEBRA_DPLANE_REQUEST_FAILURE:
     774           0 :                 flog_err(EC_ZEBRA_DP_INSTALL_FAIL,
     775             :                          "%u:%pRN: Failed to enqueue dataplane uninstall",
     776             :                          re->vrf_id, rn);
     777           0 :                 break;
     778           0 :         case ZEBRA_DPLANE_REQUEST_SUCCESS:
     779           0 :                 if (zvrf)
     780           0 :                         zvrf->removals++;
     781             :                 break;
     782             :         }
     783             : 
     784             :         return;
     785             : }
     786             : 
     787             : /*
     788             :  * rib_can_delete_dest
     789             :  *
     790             :  * Returns true if the given dest can be deleted from the table.
     791             :  */
     792          16 : static int rib_can_delete_dest(rib_dest_t *dest)
     793             : {
     794          16 :         if (re_list_first(&dest->routes)) {
     795             :                 return 0;
     796             :         }
     797             : 
     798             :         /*
     799             :          * Unresolved rnh's are stored on the default route's list
     800             :          *
     801             :          * dest->rnode can also be the source prefix node in an
     802             :          * ipv6 sourcedest table.  Fortunately the prefix of a
     803             :          * source prefix node can never be the default prefix.
     804             :          */
     805           0 :         if (is_default_prefix(&dest->rnode->p))
     806             :                 return 0;
     807             : 
     808             :         /*
     809             :          * Don't delete the dest if we have to update the FPM about this
     810             :          * prefix.
     811             :          */
     812           0 :         if (CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_FPM)
     813           0 :             || CHECK_FLAG(dest->flags, RIB_DEST_SENT_TO_FPM))
     814           0 :                 return 0;
     815             : 
     816             :         return 1;
     817             : }
     818             : 
     819           8 : void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq,
     820             :                                     bool rt_delete)
     821             : {
     822           8 :         rib_dest_t *dest = rib_dest_from_rnode(rn);
     823           8 :         struct rnh *rnh;
     824             : 
     825             :         /*
     826             :          * We are storing the rnh's associated withb
     827             :          * the tracked nexthop as a list of the rn's.
     828             :          * Unresolved rnh's are placed at the top
     829             :          * of the tree list.( 0.0.0.0/0 for v4 and 0::0/0 for v6 )
     830             :          * As such for each rn we need to walk up the tree
     831             :          * and see if any rnh's need to see if they
     832             :          * would match a more specific route
     833             :          */
     834           8 :         while (rn) {
     835          27 :                 if (IS_ZEBRA_DEBUG_NHT_DETAILED)
     836          27 :                         zlog_debug(
     837             :                                 "%s: %pRN Being examined for Nexthop Tracking Count: %zd",
     838             :                                 __func__, rn,
     839             :                                 dest ? rnh_list_count(&dest->nht) : 0);
     840             : 
     841          27 :                 if (rt_delete && (!dest || !rnh_list_count(&dest->nht))) {
     842           0 :                         if (IS_ZEBRA_DEBUG_NHT_DETAILED)
     843           0 :                                 zlog_debug("%pRN has no tracking NHTs. Bailing",
     844             :                                            rn);
     845             :                         break;
     846             :                 }
     847          27 :                 if (!dest) {
     848          11 :                         rn = rn->parent;
     849          11 :                         if (rn)
     850          11 :                                 dest = rib_dest_from_rnode(rn);
     851          11 :                         continue;
     852             :                 }
     853             :                 /*
     854             :                  * If we have any rnh's stored in the nht list
     855             :                  * then we know that this route node was used for
     856             :                  * nht resolution and as such we need to call the
     857             :                  * nexthop tracking evaluation code
     858             :                  */
     859          16 :                 frr_each_safe(rnh_list, &dest->nht, rnh) {
     860           0 :                         struct zebra_vrf *zvrf =
     861           0 :                                 zebra_vrf_lookup_by_id(rnh->vrf_id);
     862           0 :                         struct prefix *p = &rnh->node->p;
     863             : 
     864           0 :                         if (IS_ZEBRA_DEBUG_NHT_DETAILED)
     865           0 :                                 zlog_debug(
     866             :                                         "%s(%u):%pRN has Nexthop(%pRN) depending on it, evaluating %u:%u",
     867             :                                         zvrf_name(zvrf), zvrf_id(zvrf), rn,
     868             :                                         rnh->node, seq, rnh->seqno);
     869             : 
     870             :                         /*
     871             :                          * If we have evaluated this node on this pass
     872             :                          * already, due to following the tree up
     873             :                          * then we know that we can move onto the next
     874             :                          * rnh to process.
     875             :                          *
     876             :                          * Additionally we call zebra_evaluate_rnh
     877             :                          * when we gc the dest.  In this case we know
     878             :                          * that there must be no other re's where
     879             :                          * we were originally as such we know that
     880             :                          * that sequence number is ok to respect.
     881             :                          */
     882           0 :                         if (rnh->seqno == seq) {
     883           0 :                                 if (IS_ZEBRA_DEBUG_NHT_DETAILED)
     884           0 :                                         zlog_debug(
     885             :                                                 "    Node processed and moved already");
     886           0 :                                 continue;
     887             :                         }
     888             : 
     889           0 :                         rnh->seqno = seq;
     890           0 :                         zebra_evaluate_rnh(zvrf, family2afi(p->family), 0, p,
     891             :                                            rnh->safi);
     892             :                 }
     893             : 
     894          16 :                 rn = rn->parent;
     895          16 :                 if (rn)
     896           8 :                         dest = rib_dest_from_rnode(rn);
     897             :         }
     898           8 : }
     899             : 
     900             : /*
     901             :  * rib_gc_dest
     902             :  *
     903             :  * Garbage collect the rib dest corresponding to the given route node
     904             :  * if appropriate.
     905             :  *
     906             :  * Returns true if the dest was deleted, false otherwise.
     907             :  */
     908          16 : int rib_gc_dest(struct route_node *rn)
     909             : {
     910          16 :         rib_dest_t *dest;
     911             : 
     912          16 :         dest = rib_dest_from_rnode(rn);
     913          16 :         if (!dest)
     914             :                 return 0;
     915             : 
     916          16 :         if (!rib_can_delete_dest(dest))
     917             :                 return 0;
     918             : 
     919           0 :         if (IS_ZEBRA_DEBUG_RIB) {
     920           0 :                 struct zebra_vrf *zvrf;
     921             : 
     922           0 :                 zvrf = rib_dest_vrf(dest);
     923           0 :                 rnode_debug(rn, zvrf_id(zvrf), "removing dest from table");
     924             :         }
     925             : 
     926           0 :         zebra_rib_evaluate_rn_nexthops(rn, zebra_router_get_next_sequence(),
     927             :                                        true);
     928             : 
     929           0 :         dest->rnode = NULL;
     930           0 :         rnh_list_fini(&dest->nht);
     931           0 :         XFREE(MTYPE_RIB_DEST, dest);
     932           0 :         rn->info = NULL;
     933             : 
     934             :         /*
     935             :          * Release the one reference that we keep on the route node.
     936             :          */
     937           0 :         route_unlock_node(rn);
     938           0 :         return 1;
     939             : }
     940             : 
     941          28 : void zebra_rtable_node_cleanup(struct route_table *table,
     942             :                                struct route_node *node)
     943             : {
     944          28 :         struct route_entry *re, *next;
     945             : 
     946          72 :         RNODE_FOREACH_RE_SAFE (node, re, next) {
     947          16 :                 rib_unlink(node, re);
     948             :         }
     949             : 
     950          28 :         if (node->info) {
     951          18 :                 rib_dest_t *dest = node->info;
     952             : 
     953             :                 /* Remove from update queue of FPM module */
     954          18 :                 hook_call(rib_shutdown, node);
     955             : 
     956          18 :                 rnh_list_fini(&dest->nht);
     957          18 :                 XFREE(MTYPE_RIB_DEST, node->info);
     958             :         }
     959          28 : }
     960             : 
     961          15 : static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn,
     962             :                                 struct route_entry *new)
     963             : {
     964          15 :         hook_call(rib_update, rn, "new route selected");
     965             : 
     966             :         /* Update real nexthop. This may actually determine if nexthop is active
     967             :          * or not. */
     968          15 :         if (!nexthop_group_active_nexthop_num(&(new->nhe->nhg))) {
     969           0 :                 UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED);
     970           0 :                 return;
     971             :         }
     972             : 
     973          15 :         if (IS_ZEBRA_DEBUG_RIB)
     974          45 :                 zlog_debug("%s(%u:%u):%pRN: Adding route rn %p, re %p (%s)",
     975             :                            zvrf_name(zvrf), zvrf_id(zvrf), new->table, rn, rn,
     976             :                            new, zebra_route_string(new->type));
     977             : 
     978             :         /* If labeled-unicast route, install transit LSP. */
     979          15 :         if (zebra_rib_labeled_unicast(new))
     980           0 :                 zebra_mpls_lsp_install(zvrf, rn, new);
     981             : 
     982          15 :         rib_install_kernel(rn, new, NULL);
     983             : 
     984          15 :         UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED);
     985             : }
     986             : 
     987           0 : static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn,
     988             :                                 struct route_entry *old)
     989             : {
     990           0 :         hook_call(rib_update, rn, "removing existing route");
     991             : 
     992             :         /* Uninstall from kernel. */
     993           0 :         if (IS_ZEBRA_DEBUG_RIB)
     994           0 :                 zlog_debug("%s(%u:%u):%pRN: Deleting route rn %p, re %p (%s)",
     995             :                            zvrf_name(zvrf), zvrf_id(zvrf), old->table, rn, rn,
     996             :                            old, zebra_route_string(old->type));
     997             : 
     998             :         /* If labeled-unicast route, uninstall transit LSP. */
     999           0 :         if (zebra_rib_labeled_unicast(old))
    1000           0 :                 zebra_mpls_lsp_uninstall(zvrf, rn, old);
    1001             : 
    1002           0 :         rib_uninstall_kernel(rn, old);
    1003             : 
    1004             :         /* Update nexthop for route, reset changed flag. */
    1005             :         /* Note: this code also handles the Linux case when an interface goes
    1006             :          * down, causing the kernel to delete routes without sending DELROUTE
    1007             :          * notifications
    1008             :          */
    1009           0 :         if (RIB_KERNEL_ROUTE(old))
    1010           0 :                 SET_FLAG(old->status, ROUTE_ENTRY_REMOVED);
    1011             :         else
    1012           0 :                 UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED);
    1013           0 : }
    1014             : 
    1015           1 : static void rib_process_update_fib(struct zebra_vrf *zvrf,
    1016             :                                    struct route_node *rn,
    1017             :                                    struct route_entry *old,
    1018             :                                    struct route_entry *new)
    1019             : {
    1020           1 :         int nh_active = 0;
    1021             : 
    1022             :         /*
    1023             :          * We have to install or update if a new route has been selected or
    1024             :          * something has changed.
    1025             :          */
    1026           1 :         if (new != old || CHECK_FLAG(new->status, ROUTE_ENTRY_CHANGED)) {
    1027           0 :                 hook_call(rib_update, rn, "updating existing route");
    1028             : 
    1029             :                 /* Update the nexthop; we could determine here that nexthop is
    1030             :                  * inactive. */
    1031           0 :                 if (nexthop_group_active_nexthop_num(&(new->nhe->nhg)))
    1032           0 :                         nh_active = 1;
    1033             : 
    1034             :                 /* If nexthop is active, install the selected route, if
    1035             :                  * appropriate. If
    1036             :                  * the install succeeds, cleanup flags for prior route, if
    1037             :                  * different from
    1038             :                  * newly selected.
    1039             :                  */
    1040           0 :                 if (nh_active) {
    1041           0 :                         if (IS_ZEBRA_DEBUG_RIB) {
    1042           0 :                                 if (new != old)
    1043           0 :                                         zlog_debug(
    1044             :                                                 "%s(%u:%u):%pRN: Updating route rn %p, re %p (%s) old %p (%s)",
    1045             :                                                 zvrf_name(zvrf), zvrf_id(zvrf),
    1046             :                                                 new->table, rn, rn, new,
    1047             :                                                 zebra_route_string(new->type),
    1048             :                                                 old,
    1049             :                                                 zebra_route_string(old->type));
    1050             :                                 else
    1051           0 :                                         zlog_debug(
    1052             :                                                 "%s(%u:%u):%pRN: Updating route rn %p, re %p (%s)",
    1053             :                                                 zvrf_name(zvrf), zvrf_id(zvrf),
    1054             :                                                 new->table, rn, rn, new,
    1055             :                                                 zebra_route_string(new->type));
    1056             :                         }
    1057             : 
    1058             :                         /* If labeled-unicast route, uninstall transit LSP. */
    1059           0 :                         if (zebra_rib_labeled_unicast(old))
    1060           0 :                                 zebra_mpls_lsp_uninstall(zvrf, rn, old);
    1061             : 
    1062             :                         /*
    1063             :                          * Non-system route should be installed.
    1064             :                          * If labeled-unicast route, install transit
    1065             :                          * LSP.
    1066             :                          */
    1067           0 :                         if (zebra_rib_labeled_unicast(new))
    1068           0 :                                 zebra_mpls_lsp_install(zvrf, rn, new);
    1069             : 
    1070           0 :                         rib_install_kernel(rn, new, old);
    1071             :                 }
    1072             : 
    1073             :                 /*
    1074             :                  * If nexthop for selected route is not active or install
    1075             :                  * failed, we
    1076             :                  * may need to uninstall and delete for redistribution.
    1077             :                  */
    1078           0 :                 if (!nh_active) {
    1079           0 :                         if (IS_ZEBRA_DEBUG_RIB) {
    1080           0 :                                 if (new != old)
    1081           0 :                                         zlog_debug(
    1082             :                                                 "%s(%u:%u):%pRN: Deleting route rn %p, re %p (%s) old %p (%s) - nexthop inactive",
    1083             :                                                 zvrf_name(zvrf), zvrf_id(zvrf),
    1084             :                                                 new->table, rn, rn, new,
    1085             :                                                 zebra_route_string(new->type),
    1086             :                                                 old,
    1087             :                                                 zebra_route_string(old->type));
    1088             :                                 else
    1089           0 :                                         zlog_debug(
    1090             :                                                 "%s(%u:%u):%pRN: Deleting route rn %p, re %p (%s) - nexthop inactive",
    1091             :                                                 zvrf_name(zvrf), zvrf_id(zvrf),
    1092             :                                                 new->table, rn, rn, new,
    1093             :                                                 zebra_route_string(new->type));
    1094             :                         }
    1095             : 
    1096             :                         /*
    1097             :                          * When we have gotten to this point
    1098             :                          * the new route entry has no nexthops
    1099             :                          * that are usable and as such we need
    1100             :                          * to remove the old route, but only
    1101             :                          * if we were the one who installed
    1102             :                          * the old route
    1103             :                          */
    1104           0 :                         if (!RIB_SYSTEM_ROUTE(old)) {
    1105             :                                 /* If labeled-unicast route, uninstall transit
    1106             :                                  * LSP. */
    1107           0 :                                 if (zebra_rib_labeled_unicast(old))
    1108           0 :                                         zebra_mpls_lsp_uninstall(zvrf, rn, old);
    1109             : 
    1110           0 :                                 rib_uninstall_kernel(rn, old);
    1111             :                         }
    1112             :                 }
    1113             :         } else {
    1114             :                 /*
    1115             :                  * Same route selected; check if in the FIB and if not,
    1116             :                  * re-install. This is housekeeping code to deal with
    1117             :                  * race conditions in kernel with linux netlink reporting
    1118             :                  * interface up before IPv4 or IPv6 protocol is ready
    1119             :                  * to add routes.
    1120             :                  */
    1121           1 :                 if (!CHECK_FLAG(new->status, ROUTE_ENTRY_INSTALLED) ||
    1122           1 :                     RIB_SYSTEM_ROUTE(new))
    1123           1 :                         rib_install_kernel(rn, new, NULL);
    1124             :         }
    1125             : 
    1126             :         /* Update prior route. */
    1127           1 :         if (new != old)
    1128           0 :                 UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED);
    1129             : 
    1130             :         /* Clear changed flag. */
    1131           1 :         UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED);
    1132           1 : }
    1133             : 
    1134             : /* Check if 'alternate' RIB entry is better than 'current'. */
    1135          18 : static struct route_entry *rib_choose_best(struct route_entry *current,
    1136             :                                            struct route_entry *alternate)
    1137             : {
    1138          18 :         if (current == NULL)
    1139             :                 return alternate;
    1140             : 
    1141             :         /* filter route selection in following order:
    1142             :          * - connected beats other types
    1143             :          * - if both connected, loopback or vrf wins
    1144             :          * - lower distance beats higher
    1145             :          * - lower metric beats higher for equal distance
    1146             :          * - last, hence oldest, route wins tie break.
    1147             :          */
    1148             : 
    1149             :         /* Connected routes. Check to see if either are a vrf
    1150             :          * or loopback interface.  If not, pick the last connected
    1151             :          * route of the set of lowest metric connected routes.
    1152             :          */
    1153           2 :         if (alternate->type == ZEBRA_ROUTE_CONNECT) {
    1154           2 :                 if (current->type != ZEBRA_ROUTE_CONNECT)
    1155             :                         return alternate;
    1156             : 
    1157             :                 /* both are connected.  are either loop or vrf? */
    1158           2 :                 struct nexthop *nexthop = NULL;
    1159             : 
    1160           4 :                 for (ALL_NEXTHOPS(alternate->nhe->nhg, nexthop)) {
    1161           2 :                         struct interface *ifp = if_lookup_by_index(
    1162             :                                 nexthop->ifindex, alternate->vrf_id);
    1163             : 
    1164           2 :                         if (ifp && if_is_loopback(ifp))
    1165             :                                 return alternate;
    1166             :                 }
    1167             : 
    1168           4 :                 for (ALL_NEXTHOPS(current->nhe->nhg, nexthop)) {
    1169           2 :                         struct interface *ifp = if_lookup_by_index(
    1170             :                                 nexthop->ifindex, current->vrf_id);
    1171             : 
    1172           2 :                         if (ifp && if_is_loopback(ifp))
    1173             :                                 return current;
    1174             :                 }
    1175             : 
    1176             :                 /* Neither are loop or vrf so pick best metric  */
    1177           2 :                 if (alternate->metric <= current->metric)
    1178             :                         return alternate;
    1179             : 
    1180             :                 return current;
    1181             :         }
    1182             : 
    1183           0 :         if (current->type == ZEBRA_ROUTE_CONNECT)
    1184             :                 return current;
    1185             : 
    1186             :         /* higher distance loses */
    1187           0 :         if (alternate->distance < current->distance)
    1188             :                 return alternate;
    1189           0 :         if (current->distance < alternate->distance)
    1190             :                 return current;
    1191             : 
    1192             :         /* metric tie-breaks equal distance */
    1193           0 :         if (alternate->metric <= current->metric)
    1194             :                 return alternate;
    1195             : 
    1196             :         return current;
    1197             : }
    1198             : 
    1199             : /* Core function for processing routing information base. */
    1200          16 : static void rib_process(struct route_node *rn)
    1201             : {
    1202          16 :         struct route_entry *re;
    1203          16 :         struct route_entry *next;
    1204          16 :         struct route_entry *old_selected = NULL;
    1205          16 :         struct route_entry *new_selected = NULL;
    1206          16 :         struct route_entry *old_fib = NULL;
    1207          16 :         struct route_entry *new_fib = NULL;
    1208          16 :         struct route_entry *best = NULL;
    1209          16 :         rib_dest_t *dest;
    1210          16 :         struct zebra_vrf *zvrf = NULL;
    1211          16 :         struct vrf *vrf;
    1212             : 
    1213          16 :         vrf_id_t vrf_id = VRF_UNKNOWN;
    1214             : 
    1215          16 :         assert(rn);
    1216             : 
    1217          16 :         dest = rib_dest_from_rnode(rn);
    1218             :         /*
    1219             :          * We have an enqueued node with nothing to process here
    1220             :          * let's just finish up and return;
    1221             :          */
    1222          16 :         if (!dest)
    1223             :                 return;
    1224             : 
    1225          16 :         zvrf = rib_dest_vrf(dest);
    1226          16 :         vrf_id = zvrf_id(zvrf);
    1227             : 
    1228          16 :         vrf = vrf_lookup_by_id(vrf_id);
    1229             : 
    1230             :         /*
    1231             :          * we can have rn's that have a NULL info pointer
    1232             :          * (dest).  As such let's not let the deref happen
    1233             :          * additionally we know RNODE_FOREACH_RE_SAFE
    1234             :          * will not iterate so we are ok.
    1235             :          */
    1236          16 :         if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
    1237          16 :                 struct route_entry *re = re_list_first(&dest->routes);
    1238             : 
    1239          16 :                 zlog_debug("%s(%u:%u):%pRN: Processing rn %p",
    1240             :                            VRF_LOGNAME(vrf), vrf_id, re->table, rn,
    1241             :                            rn);
    1242             :         }
    1243             : 
    1244          16 :         old_fib = dest->selected_fib;
    1245             : 
    1246          50 :         RNODE_FOREACH_RE_SAFE (rn, re, next) {
    1247          18 :                 if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
    1248          18 :                         char flags_buf[128];
    1249          18 :                         char status_buf[128];
    1250             : 
    1251          18 :                         zlog_debug(
    1252             :                                 "%s(%u:%u):%pRN: Examine re %p (%s) status: %sflags: %sdist %d metric %d",
    1253             :                                 VRF_LOGNAME(vrf), vrf_id, re->table, rn, re,
    1254             :                                 zebra_route_string(re->type),
    1255             :                                 _dump_re_status(re, status_buf,
    1256             :                                                 sizeof(status_buf)),
    1257             :                                 zclient_dump_route_flags(re->flags, flags_buf,
    1258             :                                                          sizeof(flags_buf)),
    1259             :                                 re->distance, re->metric);
    1260             :                 }
    1261             : 
    1262             :                 /* Currently selected re. */
    1263          18 :                 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) {
    1264           2 :                         assert(old_selected == NULL);
    1265             :                         old_selected = re;
    1266             :                 }
    1267             : 
    1268             :                 /* Skip deleted entries from selection */
    1269          18 :                 if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
    1270           0 :                         continue;
    1271             : 
    1272             :                 /*
    1273             :                  * If the route entry has changed, verify/resolve
    1274             :                  * the nexthops associated with the entry.
    1275             :                  *
    1276             :                  * In any event if we have nexthops that are not active
    1277             :                  * then we cannot use this particular route entry so
    1278             :                  * skip it.
    1279             :                  */
    1280          18 :                 if (CHECK_FLAG(re->status, ROUTE_ENTRY_CHANGED)) {
    1281          16 :                         if (!nexthop_active_update(rn, re)) {
    1282           0 :                                 const struct prefix *p;
    1283           0 :                                 struct rib_table_info *info;
    1284             : 
    1285           0 :                                 if (re->type == ZEBRA_ROUTE_TABLE) {
    1286             :                                         /* XXX: HERE BE DRAGONS!!!!!
    1287             :                                          * In all honesty, I have not yet
    1288             :                                          * figured out what this part does or
    1289             :                                          * why the ROUTE_ENTRY_CHANGED test
    1290             :                                          * above is correct or why we need to
    1291             :                                          * delete a route here, and also not
    1292             :                                          * whether this concerns both selected
    1293             :                                          * and fib route, or only selected
    1294             :                                          * or only fib
    1295             :                                          *
    1296             :                                          * This entry was denied by the 'ip
    1297             :                                          * protocol
    1298             :                                          * table' route-map, we need to delete
    1299             :                                          * it */
    1300           0 :                                         if (re != old_selected) {
    1301           0 :                                                 if (IS_ZEBRA_DEBUG_RIB)
    1302           0 :                                                         zlog_debug(
    1303             :                                                                 "%s: %s(%u):%pRN: imported via import-table but denied by the ip protocol table route-map",
    1304             :                                                                 __func__,
    1305             :                                                                 VRF_LOGNAME(
    1306             :                                                                         vrf),
    1307             :                                                                 vrf_id, rn);
    1308           0 :                                                 rib_unlink(rn, re);
    1309           0 :                                                 continue;
    1310             :                                         } else
    1311           0 :                                                 SET_FLAG(re->status,
    1312             :                                                          ROUTE_ENTRY_REMOVED);
    1313             :                                 }
    1314             : 
    1315           0 :                                 info = srcdest_rnode_table_info(rn);
    1316           0 :                                 srcdest_rnode_prefixes(rn, &p, NULL);
    1317           0 :                                 zsend_route_notify_owner(
    1318             :                                         rn, re, ZAPI_ROUTE_FAIL_INSTALL,
    1319             :                                         info->afi, info->safi);
    1320           0 :                                 continue;
    1321             :                         }
    1322             :                 } else {
    1323             :                         /*
    1324             :                          * If the re has not changed and the nhg we have is
    1325             :                          * not usable, then we cannot use this route entry
    1326             :                          * for consideration, as that the route will just
    1327             :                          * not install if it is selected.
    1328             :                          */
    1329           2 :                         if (!nexthop_group_active_nexthop_num(&re->nhe->nhg))
    1330           0 :                                 continue;
    1331             :                 }
    1332             : 
    1333             :                 /* Infinite distance. */
    1334          18 :                 if (re->distance == DISTANCE_INFINITY &&
    1335           0 :                     re->type != ZEBRA_ROUTE_KERNEL) {
    1336           0 :                         UNSET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
    1337           0 :                         continue;
    1338             :                 }
    1339             : 
    1340          18 :                 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_FIB_OVERRIDE)) {
    1341           0 :                         best = rib_choose_best(new_fib, re);
    1342           0 :                         if (new_fib && best != new_fib)
    1343           0 :                                 UNSET_FLAG(new_fib->status,
    1344             :                                            ROUTE_ENTRY_CHANGED);
    1345             :                         new_fib = best;
    1346             :                 } else {
    1347          18 :                         best = rib_choose_best(new_selected, re);
    1348          18 :                         if (new_selected && best != new_selected)
    1349           2 :                                 UNSET_FLAG(new_selected->status,
    1350             :                                            ROUTE_ENTRY_CHANGED);
    1351             :                         new_selected = best;
    1352             :                 }
    1353          18 :                 if (best != re)
    1354           0 :                         UNSET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
    1355             :         } /* RNODE_FOREACH_RE */
    1356             : 
    1357             :         /* If no FIB override route, use the selected route also for FIB */
    1358          16 :         if (new_fib == NULL)
    1359          16 :                 new_fib = new_selected;
    1360             : 
    1361             :         /* After the cycle is finished, the following pointers will be set:
    1362             :          * old_selected --- RE entry currently having SELECTED
    1363             :          * new_selected --- RE entry that is newly SELECTED
    1364             :          * old_fib      --- RE entry currently in kernel FIB
    1365             :          * new_fib      --- RE entry that is newly to be in kernel FIB
    1366             :          *
    1367             :          * new_selected will get SELECTED flag, and is going to be redistributed
    1368             :          * the zclients. new_fib (which can be new_selected) will be installed
    1369             :          * in kernel.
    1370             :          */
    1371             : 
    1372          16 :         if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
    1373          16 :                 struct route_entry *entry;
    1374             : 
    1375          32 :                 entry = old_selected
    1376             :                                 ? old_selected
    1377          16 :                                 : new_selected
    1378             :                                           ? new_selected
    1379          14 :                                           : old_fib ? old_fib
    1380           0 :                                                     : new_fib ? new_fib : NULL;
    1381             : 
    1382          16 :                 zlog_debug(
    1383             :                         "%s(%u:%u):%pRN: After processing: old_selected %p new_selected %p old_fib %p new_fib %p",
    1384             :                         VRF_LOGNAME(vrf), vrf_id, entry ? entry->table : 0, rn,
    1385             :                         (void *)old_selected, (void *)new_selected,
    1386             :                         (void *)old_fib, (void *)new_fib);
    1387             :         }
    1388             : 
    1389             :         /* Buffer ROUTE_ENTRY_CHANGED here, because it will get cleared if
    1390             :          * fib == selected */
    1391          16 :         bool selected_changed = new_selected && CHECK_FLAG(new_selected->status,
    1392             :                                                            ROUTE_ENTRY_CHANGED);
    1393             : 
    1394             :         /* Update SELECTED entry */
    1395          16 :         if (old_selected != new_selected || selected_changed) {
    1396             : 
    1397          14 :                 if (new_selected && new_selected != new_fib)
    1398           0 :                         UNSET_FLAG(new_selected->status, ROUTE_ENTRY_CHANGED);
    1399             : 
    1400          14 :                 if (new_selected)
    1401          14 :                         SET_FLAG(new_selected->flags, ZEBRA_FLAG_SELECTED);
    1402             : 
    1403          14 :                 if (old_selected) {
    1404             :                         /*
    1405             :                          * If we're removing the old entry, we should tell
    1406             :                          * redist subscribers about that *if* they aren't
    1407             :                          * going to see a redist for the new entry.
    1408             :                          */
    1409           0 :                         if (!new_selected || CHECK_FLAG(old_selected->status,
    1410             :                                                         ROUTE_ENTRY_REMOVED))
    1411           0 :                                 redistribute_delete(rn, old_selected,
    1412             :                                                     new_selected);
    1413             : 
    1414           0 :                         if (old_selected != new_selected)
    1415           0 :                                 UNSET_FLAG(old_selected->flags,
    1416             :                                            ZEBRA_FLAG_SELECTED);
    1417             :                 }
    1418             :         }
    1419             : 
    1420             :         /* Update fib according to selection results */
    1421          16 :         if (new_fib && old_fib)
    1422           1 :                 rib_process_update_fib(zvrf, rn, old_fib, new_fib);
    1423          15 :         else if (new_fib)
    1424          15 :                 rib_process_add_fib(zvrf, rn, new_fib);
    1425           0 :         else if (old_fib)
    1426           0 :                 rib_process_del_fib(zvrf, rn, old_fib);
    1427             : 
    1428             :         /* Remove all RE entries queued for removal */
    1429          50 :         RNODE_FOREACH_RE_SAFE (rn, re, next) {
    1430          18 :                 if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) {
    1431           0 :                         if (IS_ZEBRA_DEBUG_RIB) {
    1432           0 :                                 rnode_debug(rn, vrf_id, "rn %p, removing re %p",
    1433             :                                             (void *)rn, (void *)re);
    1434             :                         }
    1435           0 :                         rib_unlink(rn, re);
    1436             :                 }
    1437             :         }
    1438             : 
    1439             :         /*
    1440             :          * Check if the dest can be deleted now.
    1441             :          */
    1442          16 :         rib_gc_dest(rn);
    1443             : }
    1444             : 
    1445           8 : static void zebra_rib_evaluate_mpls(struct route_node *rn)
    1446             : {
    1447           8 :         rib_dest_t *dest = rib_dest_from_rnode(rn);
    1448           8 :         struct zebra_vrf *zvrf = vrf_info_lookup(VRF_DEFAULT);
    1449             : 
    1450           8 :         if (!dest)
    1451             :                 return;
    1452             : 
    1453           8 :         if (CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_LSPS)) {
    1454           1 :                 if (IS_ZEBRA_DEBUG_MPLS)
    1455           0 :                         zlog_debug(
    1456             :                                 "%s(%u): Scheduling all LSPs upon RIB completion",
    1457             :                                 zvrf_name(zvrf), zvrf_id(zvrf));
    1458           1 :                 zebra_mpls_lsp_schedule(zvrf);
    1459           1 :                 mpls_unmark_lsps_for_processing(rn);
    1460             :         }
    1461             : }
    1462             : 
    1463             : /*
    1464             :  * Utility to match route with dplane context data
    1465             :  */
    1466           9 : static bool rib_route_match_ctx(const struct route_entry *re,
    1467             :                                 const struct zebra_dplane_ctx *ctx,
    1468             :                                 bool is_update)
    1469             : {
    1470           9 :         bool result = false;
    1471             : 
    1472           9 :         if (is_update) {
    1473             :                 /*
    1474             :                  * In 'update' case, we test info about the 'previous' or
    1475             :                  * 'old' route
    1476             :                  */
    1477           0 :                 if ((re->type == dplane_ctx_get_old_type(ctx)) &&
    1478           0 :                     (re->instance == dplane_ctx_get_old_instance(ctx))) {
    1479           0 :                         result = true;
    1480             : 
    1481             :                         /* We use an extra test for statics, and another for
    1482             :                          * kernel routes.
    1483             :                          */
    1484           0 :                         if (re->type == ZEBRA_ROUTE_STATIC &&
    1485           0 :                             (re->distance != dplane_ctx_get_old_distance(ctx) ||
    1486           0 :                              re->tag != dplane_ctx_get_old_tag(ctx))) {
    1487             :                                 result = false;
    1488           0 :                         } else if (re->type == ZEBRA_ROUTE_KERNEL &&
    1489           0 :                                    re->metric !=
    1490           0 :                                    dplane_ctx_get_old_metric(ctx)) {
    1491           0 :                                 result = false;
    1492             :                         }
    1493             :                 }
    1494             : 
    1495             :         } else {
    1496             :                 /*
    1497             :                  * Ordinary, single-route case using primary context info
    1498             :                  */
    1499           9 :                 if ((dplane_ctx_get_op(ctx) != DPLANE_OP_ROUTE_DELETE) &&
    1500           9 :                     CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) {
    1501             :                         /* Skip route that's been deleted */
    1502           0 :                         goto done;
    1503             :                 }
    1504             : 
    1505          18 :                 if ((re->type == dplane_ctx_get_type(ctx)) &&
    1506           9 :                     (re->instance == dplane_ctx_get_instance(ctx))) {
    1507           9 :                         result = true;
    1508             : 
    1509             :                         /* We use an extra test for statics, and another for
    1510             :                          * kernel routes.
    1511             :                          */
    1512           9 :                         if (re->type == ZEBRA_ROUTE_STATIC &&
    1513           0 :                             (re->distance != dplane_ctx_get_distance(ctx) ||
    1514           0 :                              re->tag != dplane_ctx_get_tag(ctx))) {
    1515             :                                 result = false;
    1516           9 :                         } else if (re->type == ZEBRA_ROUTE_KERNEL &&
    1517           0 :                                    re->metric != dplane_ctx_get_metric(ctx)) {
    1518             :                                 result = false;
    1519           9 :                         } else if (re->type == ZEBRA_ROUTE_CONNECT) {
    1520           9 :                                 result = nexthop_group_equal_no_recurse(
    1521           9 :                                         &re->nhe->nhg, dplane_ctx_get_ng(ctx));
    1522             :                         }
    1523             :                 }
    1524             :         }
    1525             : 
    1526           0 : done:
    1527           9 :         return result;
    1528             : }
    1529             : 
    1530           8 : static void zebra_rib_fixup_system(struct route_node *rn)
    1531             : {
    1532           8 :         struct route_entry *re;
    1533             : 
    1534          34 :         RNODE_FOREACH_RE(rn, re) {
    1535           9 :                 struct nexthop *nhop;
    1536             : 
    1537           9 :                 if (!RIB_SYSTEM_ROUTE(re))
    1538           0 :                         continue;
    1539             : 
    1540           9 :                 if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
    1541           0 :                         continue;
    1542             : 
    1543           9 :                 SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
    1544           9 :                 UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
    1545           9 :                 UNSET_FLAG(re->status, ROUTE_ENTRY_ROUTE_REPLACING);
    1546             : 
    1547          18 :                 for (ALL_NEXTHOPS(re->nhe->nhg, nhop)) {
    1548           9 :                         if (CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_RECURSIVE))
    1549           0 :                                 continue;
    1550             : 
    1551           9 :                         SET_FLAG(nhop->flags, NEXTHOP_FLAG_FIB);
    1552             :                 }
    1553             :         }
    1554           8 : }
    1555             : 
    1556             : /* Route comparison logic, with various special cases. */
    1557           2 : static bool rib_compare_routes(const struct route_entry *re1,
    1558             :                                const struct route_entry *re2)
    1559             : {
    1560           2 :         if (re1->type != re2->type)
    1561             :                 return false;
    1562             : 
    1563           2 :         if (re1->instance != re2->instance)
    1564             :                 return false;
    1565             : 
    1566           2 :         if (re1->type == ZEBRA_ROUTE_KERNEL && re1->metric != re2->metric)
    1567             :                 return false;
    1568             : 
    1569           2 :         if (CHECK_FLAG(re1->flags, ZEBRA_FLAG_RR_USE_DISTANCE) &&
    1570           0 :             re1->distance != re2->distance)
    1571             :                 return false;
    1572             : 
    1573             :         /* We support multiple connected routes: this supports multiple
    1574             :          * v6 link-locals, and we also support multiple addresses in the same
    1575             :          * subnet on a single interface.
    1576             :          */
    1577           2 :         if (re1->type != ZEBRA_ROUTE_CONNECT)
    1578           0 :                 return true;
    1579             : 
    1580             :         return false;
    1581             : }
    1582             : 
    1583             : /*
    1584             :  * Compare nexthop lists from a route and a dplane context; test whether
    1585             :  * the list installed in the FIB matches the route's list.
    1586             :  * Set 'changed_p' to 'true' if there were changes to the route's
    1587             :  * installed nexthops.
    1588             :  *
    1589             :  * Return 'false' if any ACTIVE route nexthops are not mentioned in the FIB
    1590             :  * list.
    1591             :  */
    1592           8 : static bool rib_update_nhg_from_ctx(struct nexthop_group *re_nhg,
    1593             :                                     const struct nexthop_group *ctx_nhg,
    1594             :                                     bool *changed_p)
    1595             : {
    1596           8 :         bool matched_p = true;
    1597           8 :         struct nexthop *nexthop, *ctx_nexthop;
    1598             : 
    1599             :         /* Get the first `installed` one to check against.
    1600             :          * If the dataplane doesn't set these to be what was actually installed,
    1601             :          * it will just be whatever was in re->nhe->nhg?
    1602             :          */
    1603           8 :         ctx_nexthop = ctx_nhg->nexthop;
    1604             : 
    1605           8 :         if (CHECK_FLAG(ctx_nexthop->flags, NEXTHOP_FLAG_RECURSIVE)
    1606             :             || !CHECK_FLAG(ctx_nexthop->flags, NEXTHOP_FLAG_ACTIVE))
    1607           0 :                 ctx_nexthop = nexthop_next_active_resolved(ctx_nexthop);
    1608             : 
    1609          16 :         for (ALL_NEXTHOPS_PTR(re_nhg, nexthop)) {
    1610             : 
    1611           8 :                 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
    1612           0 :                         continue;
    1613             : 
    1614           8 :                 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
    1615           0 :                         continue;
    1616             : 
    1617             :                 /* Check for a FIB nexthop corresponding to the RIB nexthop */
    1618           8 :                 if (!nexthop_same(ctx_nexthop, nexthop)) {
    1619             :                         /* If the FIB doesn't know about the nexthop,
    1620             :                          * it's not installed
    1621             :                          */
    1622           0 :                         if (IS_ZEBRA_DEBUG_RIB_DETAILED ||
    1623           0 :                             IS_ZEBRA_DEBUG_NHG_DETAIL) {
    1624           0 :                                 zlog_debug("%s: no ctx match for rib nh %pNHv %s",
    1625             :                                            __func__, nexthop,
    1626             :                                            (CHECK_FLAG(nexthop->flags,
    1627             :                                                        NEXTHOP_FLAG_FIB) ?
    1628             :                                             "(FIB)":""));
    1629             :                         }
    1630           0 :                         matched_p = false;
    1631             : 
    1632           0 :                         if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
    1633           0 :                                 *changed_p = true;
    1634             : 
    1635           0 :                         UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
    1636             : 
    1637             :                         /* Keep checking nexthops */
    1638           0 :                         continue;
    1639             :                 }
    1640             : 
    1641           8 :                 if (CHECK_FLAG(ctx_nexthop->flags, NEXTHOP_FLAG_FIB)) {
    1642           8 :                         if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) {
    1643           0 :                                 if (IS_ZEBRA_DEBUG_NHG_DETAIL)
    1644           0 :                                         zlog_debug("%s: rib nh %pNHv -> installed",
    1645             :                                                    __func__, nexthop);
    1646             : 
    1647           0 :                                 *changed_p = true;
    1648             :                         }
    1649             : 
    1650           8 :                         SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
    1651             :                 } else {
    1652           0 :                         if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) {
    1653           0 :                                 if (IS_ZEBRA_DEBUG_NHG_DETAIL)
    1654           0 :                                         zlog_debug("%s: rib nh %pNHv -> uninstalled",
    1655             :                                                    __func__, nexthop);
    1656             : 
    1657           0 :                                 *changed_p = true;
    1658             :                         }
    1659             : 
    1660           0 :                         UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
    1661             :                 }
    1662             : 
    1663           8 :                 ctx_nexthop = nexthop_next_active_resolved(ctx_nexthop);
    1664             :         }
    1665             : 
    1666           8 :         return matched_p;
    1667             : }
    1668             : 
    1669             : /*
    1670             :  * Update a route from a dplane context. This consolidates common code
    1671             :  * that can be used in processing of results from FIB updates, and in
    1672             :  * async notification processing.
    1673             :  * The return is 'true' if the installed nexthops changed; 'false' otherwise.
    1674             :  */
    1675           8 : static bool rib_update_re_from_ctx(struct route_entry *re,
    1676             :                                    struct route_node *rn,
    1677             :                                    struct zebra_dplane_ctx *ctx)
    1678             : {
    1679           8 :         struct nexthop *nexthop;
    1680           8 :         bool matched;
    1681           8 :         const struct nexthop_group *ctxnhg;
    1682           8 :         struct nexthop_group *re_nhg;
    1683           8 :         bool is_selected = false; /* Is 're' currently the selected re? */
    1684           8 :         bool changed_p = false; /* Change to nexthops? */
    1685           8 :         rib_dest_t *dest;
    1686           8 :         struct vrf *vrf;
    1687             : 
    1688           8 :         vrf = vrf_lookup_by_id(re->vrf_id);
    1689             : 
    1690           8 :         dest = rib_dest_from_rnode(rn);
    1691           8 :         if (dest)
    1692           8 :                 is_selected = (re == dest->selected_fib);
    1693             : 
    1694           8 :         if (IS_ZEBRA_DEBUG_RIB_DETAILED)
    1695           8 :                 zlog_debug("update_from_ctx: %s(%u:%u):%pRN: %sSELECTED, re %p",
    1696             :                            VRF_LOGNAME(vrf), re->vrf_id, re->table, rn,
    1697             :                            (is_selected ? "" : "NOT "), re);
    1698             : 
    1699             :         /* Update zebra's nexthop FIB flag for each nexthop that was installed.
    1700             :          * If the installed set differs from the set requested by the rib/owner,
    1701             :          * we use the fib-specific nexthop-group to record the actual FIB
    1702             :          * status.
    1703             :          */
    1704           8 :         matched = false;
    1705           8 :         ctxnhg = dplane_ctx_get_ng(ctx);
    1706             : 
    1707             :         /* Check route's fib group and incoming notif group for equivalence.
    1708             :          *
    1709             :          * Let's assume the nexthops are ordered here to save time.
    1710             :          */
    1711             :         /* TODO -- this isn't testing or comparing the FIB flags; we should
    1712             :          * do a more explicit loop, checking the incoming notification's flags.
    1713             :          */
    1714           8 :         if (re->fib_ng.nexthop && ctxnhg->nexthop &&
    1715           0 :             nexthop_group_equal(&re->fib_ng, ctxnhg))
    1716           0 :                 matched = true;
    1717             : 
    1718             :         /* If the new FIB set matches the existing FIB set, we're done. */
    1719           0 :         if (matched) {
    1720           0 :                 if (IS_ZEBRA_DEBUG_RIB)
    1721           0 :                         zlog_debug(
    1722             :                                 "%s(%u:%u):%pRN update_from_ctx(): existing fib nhg, no change",
    1723             :                                 VRF_LOGNAME(vrf), re->vrf_id, re->table, rn);
    1724           0 :                 goto check_backups;
    1725             : 
    1726           8 :         } else if (CHECK_FLAG(re->status, ROUTE_ENTRY_USE_FIB_NHG)) {
    1727             :                 /*
    1728             :                  * Free stale fib list and move on to check the rib nhg.
    1729             :                  */
    1730           0 :                 if (IS_ZEBRA_DEBUG_RIB)
    1731           0 :                         zlog_debug(
    1732             :                                 "%s(%u:%u):%pRN update_from_ctx(): replacing fib nhg",
    1733             :                                 VRF_LOGNAME(vrf), re->vrf_id, re->table, rn);
    1734           0 :                 nexthops_free(re->fib_ng.nexthop);
    1735           0 :                 re->fib_ng.nexthop = NULL;
    1736             : 
    1737           0 :                 UNSET_FLAG(re->status, ROUTE_ENTRY_USE_FIB_NHG);
    1738             : 
    1739             :                 /* Note that the installed nexthops have changed */
    1740           0 :                 changed_p = true;
    1741             :         } else {
    1742           8 :                 if (IS_ZEBRA_DEBUG_RIB)
    1743           8 :                         zlog_debug(
    1744             :                                 "%s(%u:%u):%pRN update_from_ctx(): no fib nhg",
    1745             :                                 VRF_LOGNAME(vrf), re->vrf_id, re->table, rn);
    1746             :         }
    1747             : 
    1748             :         /*
    1749             :          * Compare with the rib nexthop group. The comparison here is different:
    1750             :          * the RIB group may be a superset of the list installed in the FIB. We
    1751             :          * walk the RIB group, looking for the 'installable' candidate
    1752             :          * nexthops, and then check those against the set
    1753             :          * that is actually installed.
    1754             :          *
    1755             :          * Assume nexthops are ordered here as well.
    1756             :          */
    1757             : 
    1758             :         /* If nothing is installed, we can skip some of the checking/comparison
    1759             :          * of nexthops.
    1760             :          */
    1761           8 :         if (ctxnhg->nexthop == NULL) {
    1762           0 :                 changed_p = true;
    1763           0 :                 goto no_nexthops;
    1764             :         }
    1765             : 
    1766           8 :         matched = rib_update_nhg_from_ctx(&(re->nhe->nhg), ctxnhg, &changed_p);
    1767             : 
    1768             :         /* If all nexthops were processed, we're done */
    1769           8 :         if (matched) {
    1770           8 :                 if (IS_ZEBRA_DEBUG_RIB)
    1771          16 :                         zlog_debug(
    1772             :                                 "%s(%u:%u):%pRN update_from_ctx(): rib nhg matched, changed '%s'",
    1773             :                                 VRF_LOGNAME(vrf), re->vrf_id, re->table, rn,
    1774             :                                 (changed_p ? "true" : "false"));
    1775           8 :                 goto check_backups;
    1776             :         }
    1777             : 
    1778           0 : no_nexthops:
    1779             : 
    1780             :         /* FIB nexthop set differs from the RIB set:
    1781             :          * create a fib-specific nexthop-group
    1782             :          */
    1783           0 :         if (IS_ZEBRA_DEBUG_RIB)
    1784           0 :                 zlog_debug(
    1785             :                         "%s(%u:%u):%pRN update_from_ctx(): changed %s, adding new fib nhg%s",
    1786             :                         VRF_LOGNAME(vrf), re->vrf_id, re->table, rn,
    1787             :                         (changed_p ? "true" : "false"),
    1788             :                         ctxnhg->nexthop != NULL ? "" : " (empty)");
    1789             : 
    1790             :         /* Set the flag about the dedicated fib list */
    1791           0 :         if (zrouter.asic_notification_nexthop_control) {
    1792           0 :                 SET_FLAG(re->status, ROUTE_ENTRY_USE_FIB_NHG);
    1793           0 :                 if (ctxnhg->nexthop)
    1794           0 :                         copy_nexthops(&(re->fib_ng.nexthop), ctxnhg->nexthop,
    1795             :                                       NULL);
    1796             :         }
    1797             : 
    1798           0 : check_backups:
    1799             : 
    1800             :         /*
    1801             :          * Check the status of the route's backup nexthops, if any.
    1802             :          * The logic for backups is somewhat different: if any backup is
    1803             :          * installed, a new fib nhg will be attached to the route.
    1804             :          */
    1805           8 :         re_nhg = zebra_nhg_get_backup_nhg(re->nhe);
    1806           8 :         if (re_nhg == NULL)
    1807           8 :                 goto done;      /* No backup nexthops */
    1808             : 
    1809             :         /* First check the route's 'fib' list of backups, if it's present
    1810             :          * from some previous event.
    1811             :          */
    1812           0 :         re_nhg = &re->fib_backup_ng;
    1813           0 :         ctxnhg = dplane_ctx_get_backup_ng(ctx);
    1814             : 
    1815           0 :         matched = false;
    1816           0 :         if (re_nhg->nexthop && ctxnhg && nexthop_group_equal(re_nhg, ctxnhg))
    1817           0 :                 matched = true;
    1818             : 
    1819             :         /* If the new FIB set matches an existing FIB set, we're done. */
    1820           0 :         if (matched) {
    1821           0 :                 if (IS_ZEBRA_DEBUG_RIB)
    1822           0 :                         zlog_debug(
    1823             :                                 "%s(%u):%pRN update_from_ctx(): existing fib backup nhg, no change",
    1824             :                                 VRF_LOGNAME(vrf), re->vrf_id, rn);
    1825           0 :                 goto done;
    1826             : 
    1827           0 :         } else if (re->fib_backup_ng.nexthop) {
    1828             :                 /*
    1829             :                  * Free stale fib backup list and move on to check
    1830             :                  * the route's backups.
    1831             :                  */
    1832           0 :                 if (IS_ZEBRA_DEBUG_RIB)
    1833           0 :                         zlog_debug(
    1834             :                                 "%s(%u):%pRN update_from_ctx(): replacing fib backup nhg",
    1835             :                                 VRF_LOGNAME(vrf), re->vrf_id, rn);
    1836           0 :                 nexthops_free(re->fib_backup_ng.nexthop);
    1837           0 :                 re->fib_backup_ng.nexthop = NULL;
    1838             : 
    1839             :                 /* Note that the installed nexthops have changed */
    1840           0 :                 changed_p = true;
    1841             :         } else {
    1842           0 :                 if (IS_ZEBRA_DEBUG_RIB)
    1843           0 :                         zlog_debug(
    1844             :                                 "%s(%u):%pRN update_from_ctx(): no fib backup nhg",
    1845             :                                 VRF_LOGNAME(vrf), re->vrf_id, rn);
    1846             :         }
    1847             : 
    1848             :         /*
    1849             :          * If a FIB backup nexthop set exists, attach a copy
    1850             :          * to the route if any backup is installed
    1851             :          */
    1852           0 :         if (ctxnhg && ctxnhg->nexthop) {
    1853             : 
    1854           0 :                 for (ALL_NEXTHOPS_PTR(ctxnhg, nexthop)) {
    1855           0 :                         if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
    1856             :                                 break;
    1857             :                 }
    1858             : 
    1859             :                 /* If no installed backups, we're done */
    1860           0 :                 if (nexthop == NULL)
    1861           0 :                         goto done;
    1862             : 
    1863           0 :                 if (IS_ZEBRA_DEBUG_RIB)
    1864           0 :                         zlog_debug(
    1865             :                                 "%s(%u):%pRN update_from_ctx(): changed %s, adding new backup fib nhg",
    1866             :                                 VRF_LOGNAME(vrf), re->vrf_id, rn,
    1867             :                                 (changed_p ? "true" : "false"));
    1868             : 
    1869           0 :                 copy_nexthops(&(re->fib_backup_ng.nexthop), ctxnhg->nexthop,
    1870             :                               NULL);
    1871             :         }
    1872             : 
    1873           0 : done:
    1874             : 
    1875           8 :         return changed_p;
    1876             : }
    1877             : 
    1878             : /*
    1879             :  * Helper to locate a zebra route-node from a dplane context. This is used
    1880             :  * when processing dplane results, e.g. Note well: the route-node is returned
    1881             :  * with a ref held - route_unlock_node() must be called eventually.
    1882             :  */
    1883          16 : struct route_node *rib_find_rn_from_ctx(const struct zebra_dplane_ctx *ctx)
    1884             : {
    1885          16 :         struct route_table *table = NULL;
    1886          16 :         struct route_node *rn = NULL;
    1887          16 :         const struct prefix *dest_pfx, *src_pfx;
    1888             : 
    1889             :         /* Locate rn and re(s) from ctx */
    1890             : 
    1891          16 :         table = zebra_vrf_lookup_table_with_table_id(
    1892             :                 dplane_ctx_get_afi(ctx), dplane_ctx_get_safi(ctx),
    1893             :                 dplane_ctx_get_vrf(ctx), dplane_ctx_get_table(ctx));
    1894          16 :         if (table == NULL) {
    1895           0 :                 if (IS_ZEBRA_DEBUG_DPLANE) {
    1896           0 :                         zlog_debug(
    1897             :                                 "Failed to find route for ctx: no table for afi %d, safi %d, vrf %s(%u)",
    1898             :                                 dplane_ctx_get_afi(ctx),
    1899             :                                 dplane_ctx_get_safi(ctx),
    1900             :                                 vrf_id_to_name(dplane_ctx_get_vrf(ctx)),
    1901             :                                 dplane_ctx_get_vrf(ctx));
    1902             :                 }
    1903           0 :                 goto done;
    1904             :         }
    1905             : 
    1906          16 :         dest_pfx = dplane_ctx_get_dest(ctx);
    1907          16 :         src_pfx = dplane_ctx_get_src(ctx);
    1908             : 
    1909          16 :         rn = srcdest_rnode_get(table, dest_pfx,
    1910             :                                src_pfx ? (struct prefix_ipv6 *)src_pfx : NULL);
    1911             : 
    1912          16 : done:
    1913          16 :         return rn;
    1914             : }
    1915             : 
    1916             : 
    1917             : 
    1918             : /*
    1919             :  * Route-update results processing after async dataplane update.
    1920             :  */
    1921           8 : static void rib_process_result(struct zebra_dplane_ctx *ctx)
    1922             : {
    1923           8 :         struct zebra_vrf *zvrf = NULL;
    1924           8 :         struct vrf *vrf;
    1925           8 :         struct route_node *rn = NULL;
    1926           8 :         struct route_entry *re = NULL, *old_re = NULL, *rib;
    1927           8 :         bool is_update = false;
    1928           8 :         enum dplane_op_e op;
    1929           8 :         enum zebra_dplane_result status;
    1930           8 :         uint32_t seq;
    1931           8 :         rib_dest_t *dest;
    1932           8 :         bool fib_changed = false;
    1933           8 :         struct rib_table_info *info;
    1934           8 :         bool rt_delete = false;
    1935             : 
    1936           8 :         zvrf = vrf_info_lookup(dplane_ctx_get_vrf(ctx));
    1937           8 :         vrf = vrf_lookup_by_id(dplane_ctx_get_vrf(ctx));
    1938             : 
    1939             :         /* Locate rn and re(s) from ctx */
    1940           8 :         rn = rib_find_rn_from_ctx(ctx);
    1941           8 :         if (rn == NULL) {
    1942           0 :                 if (IS_ZEBRA_DEBUG_DPLANE) {
    1943           0 :                         zlog_debug(
    1944             :                                 "Failed to process dplane results: no route for %s(%u):%pRN",
    1945             :                                 VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), rn);
    1946             :                 }
    1947           0 :                 goto done;
    1948             :         }
    1949             : 
    1950           8 :         dest = rib_dest_from_rnode(rn);
    1951           8 :         info = srcdest_rnode_table_info(rn);
    1952             : 
    1953           8 :         op = dplane_ctx_get_op(ctx);
    1954           8 :         status = dplane_ctx_get_status(ctx);
    1955             : 
    1956           8 :         if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
    1957           0 :                 zlog_debug(
    1958             :                         "%s(%u:%u):%pRN Processing dplane result ctx %p, op %s result %s",
    1959             :                         VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
    1960             :                         dplane_ctx_get_table(ctx), rn, ctx, dplane_op2str(op),
    1961             :                         dplane_res2str(status));
    1962             : 
    1963             :         /*
    1964             :          * Update is a bit of a special case, where we may have both old and new
    1965             :          * routes to post-process.
    1966             :          */
    1967           8 :         is_update = dplane_ctx_is_update(ctx);
    1968             : 
    1969             :         /*
    1970             :          * Take a pass through the routes, look for matches with the context
    1971             :          * info.
    1972             :          */
    1973          18 :         RNODE_FOREACH_RE(rn, rib) {
    1974             : 
    1975           9 :                 if (re == NULL) {
    1976           9 :                         if (rib_route_match_ctx(rib, ctx, false))
    1977           8 :                                 re = rib;
    1978             :                 }
    1979             : 
    1980             :                 /* Check for old route match */
    1981           9 :                 if (is_update && (old_re == NULL)) {
    1982           0 :                         if (rib_route_match_ctx(rib, ctx, true /*is_update*/))
    1983           0 :                                 old_re = rib;
    1984             :                 }
    1985             : 
    1986             :                 /* Have we found the routes we need to work on? */
    1987           9 :                 if (re && ((!is_update || old_re)))
    1988             :                         break;
    1989             :         }
    1990             : 
    1991           8 :         seq = dplane_ctx_get_seq(ctx);
    1992             : 
    1993             :         /*
    1994             :          * Check sequence number(s) to detect stale results before continuing
    1995             :          */
    1996           8 :         if (re) {
    1997           8 :                 if (re->dplane_sequence != seq) {
    1998           0 :                         if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
    1999           0 :                                 zlog_debug(
    2000             :                                         "%s(%u):%pRN Stale dplane result for re %p",
    2001             :                                         VRF_LOGNAME(vrf),
    2002             :                                         dplane_ctx_get_vrf(ctx), rn, re);
    2003             :                 } else {
    2004           8 :                         if (!zrouter.asic_offloaded ||
    2005           0 :                             (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED) ||
    2006             :                              CHECK_FLAG(re->flags,
    2007             :                                         ZEBRA_FLAG_OFFLOAD_FAILED))) {
    2008           8 :                                 UNSET_FLAG(re->status,
    2009             :                                            ROUTE_ENTRY_ROUTE_REPLACING);
    2010           8 :                                 UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
    2011             :                         }
    2012             :                 }
    2013             :         }
    2014             : 
    2015           8 :         if (old_re) {
    2016           0 :                 if (old_re->dplane_sequence != dplane_ctx_get_old_seq(ctx)) {
    2017           0 :                         if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
    2018           0 :                                 zlog_debug(
    2019             :                                         "%s(%u:%u):%pRN Stale dplane result for old_re %p",
    2020             :                                         VRF_LOGNAME(vrf),
    2021             :                                         dplane_ctx_get_vrf(ctx), old_re->table,
    2022             :                                         rn, old_re);
    2023             :                 } else
    2024           0 :                         UNSET_FLAG(old_re->status, ROUTE_ENTRY_QUEUED);
    2025             :         }
    2026             : 
    2027           8 :         switch (op) {
    2028           8 :         case DPLANE_OP_ROUTE_INSTALL:
    2029             :         case DPLANE_OP_ROUTE_UPDATE:
    2030           8 :                 if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) {
    2031           8 :                         if (re) {
    2032           8 :                                 UNSET_FLAG(re->status, ROUTE_ENTRY_FAILED);
    2033           8 :                                 SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
    2034             :                         }
    2035             :                         /*
    2036             :                          * On an update operation from the same route type
    2037             :                          * context retrieval currently has no way to know
    2038             :                          * which was the old and which was the new.
    2039             :                          * So don't unset our flags that we just set.
    2040             :                          * We know redistribution is ok because the
    2041             :                          * old_re in this case is used for nothing
    2042             :                          * more than knowing whom to contact if necessary.
    2043             :                          */
    2044           8 :                         if (old_re && old_re != re) {
    2045           0 :                                 UNSET_FLAG(old_re->status, ROUTE_ENTRY_FAILED);
    2046           0 :                                 UNSET_FLAG(old_re->status,
    2047             :                                            ROUTE_ENTRY_INSTALLED);
    2048             :                         }
    2049             : 
    2050             :                         /* Update zebra route based on the results in
    2051             :                          * the context struct.
    2052             :                          */
    2053           8 :                         if (re) {
    2054           8 :                                 fib_changed =
    2055           8 :                                         rib_update_re_from_ctx(re, rn, ctx);
    2056             : 
    2057           8 :                                 if (!fib_changed) {
    2058           8 :                                         if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
    2059           0 :                                                 zlog_debug(
    2060             :                                                         "%s(%u:%u):%pRN no fib change for re",
    2061             :                                                         VRF_LOGNAME(vrf),
    2062             :                                                         dplane_ctx_get_vrf(ctx),
    2063             :                                                         dplane_ctx_get_table(
    2064             :                                                                 ctx),
    2065             :                                                         rn);
    2066             :                                 }
    2067             : 
    2068             :                                 /* Redistribute if this is the selected re */
    2069           8 :                                 if (dest && re == dest->selected_fib)
    2070           8 :                                         redistribute_update(rn, re, old_re);
    2071             :                         }
    2072             : 
    2073             :                         /*
    2074             :                          * System routes are weird in that they
    2075             :                          * allow multiple to be installed that match
    2076             :                          * to the same prefix, so after we get the
    2077             :                          * result we need to clean them up so that
    2078             :                          * we can actually use them.
    2079             :                          */
    2080           8 :                         if ((re && RIB_SYSTEM_ROUTE(re)) ||
    2081           0 :                             (old_re && RIB_SYSTEM_ROUTE(old_re)))
    2082           8 :                                 zebra_rib_fixup_system(rn);
    2083             : 
    2084           8 :                         if (zvrf)
    2085           8 :                                 zvrf->installs++;
    2086             : 
    2087             :                         /* Notify route owner */
    2088           8 :                         if (zebra_router_notify_on_ack())
    2089           8 :                                 zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_INSTALLED);
    2090             :                         else {
    2091           0 :                                 if (re) {
    2092           0 :                                         if (CHECK_FLAG(re->flags,
    2093             :                                                        ZEBRA_FLAG_OFFLOADED))
    2094           0 :                                                 zsend_route_notify_owner_ctx(
    2095             :                                                         ctx,
    2096             :                                                         ZAPI_ROUTE_INSTALLED);
    2097           0 :                                         if (CHECK_FLAG(
    2098             :                                                     re->flags,
    2099             :                                                     ZEBRA_FLAG_OFFLOAD_FAILED))
    2100           0 :                                                 zsend_route_notify_owner_ctx(
    2101             :                                                         ctx,
    2102             :                                                         ZAPI_ROUTE_FAIL_INSTALL);
    2103             :                                 }
    2104             :                         }
    2105             :                 } else {
    2106           0 :                         if (re) {
    2107           0 :                                 SET_FLAG(re->status, ROUTE_ENTRY_FAILED);
    2108           0 :                                 UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
    2109           0 :                         } if (old_re)
    2110           0 :                                 SET_FLAG(old_re->status, ROUTE_ENTRY_FAILED);
    2111           0 :                         if (re)
    2112           0 :                                 zsend_route_notify_owner(
    2113             :                                         rn, re, ZAPI_ROUTE_FAIL_INSTALL,
    2114             :                                         info->afi, info->safi);
    2115             : 
    2116           0 :                         zlog_warn("%s(%u:%u):%pRN: Route install failed",
    2117             :                                   VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
    2118             :                                   dplane_ctx_get_table(ctx), rn);
    2119             :                 }
    2120             :                 break;
    2121           0 :         case DPLANE_OP_ROUTE_DELETE:
    2122           0 :                 rt_delete = true;
    2123           0 :                 if (re)
    2124           0 :                         SET_FLAG(re->status, ROUTE_ENTRY_FAILED);
    2125             :                 /*
    2126             :                  * In the delete case, the zebra core datastructs were
    2127             :                  * updated (or removed) at the time the delete was issued,
    2128             :                  * so we're just notifying the route owner.
    2129             :                  */
    2130           0 :                 if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) {
    2131           0 :                         if (re) {
    2132           0 :                                 UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
    2133           0 :                                 UNSET_FLAG(re->status, ROUTE_ENTRY_FAILED);
    2134             :                         }
    2135           0 :                         zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_REMOVED);
    2136             : 
    2137           0 :                         if (zvrf)
    2138           0 :                                 zvrf->removals++;
    2139             :                 } else {
    2140           0 :                         if (re)
    2141           0 :                                 SET_FLAG(re->status, ROUTE_ENTRY_FAILED);
    2142           0 :                         zsend_route_notify_owner_ctx(ctx,
    2143             :                                                      ZAPI_ROUTE_REMOVE_FAIL);
    2144             : 
    2145           0 :                         zlog_warn("%s(%u:%u):%pRN: Route Deletion failure",
    2146             :                                   VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
    2147             :                                   dplane_ctx_get_table(ctx), rn);
    2148             :                 }
    2149             : 
    2150             :                 /*
    2151             :                  * System routes are weird in that they
    2152             :                  * allow multiple to be installed that match
    2153             :                  * to the same prefix, so after we get the
    2154             :                  * result we need to clean them up so that
    2155             :                  * we can actually use them.
    2156             :                  */
    2157           0 :                 if ((re && RIB_SYSTEM_ROUTE(re)) ||
    2158           0 :                     (old_re && RIB_SYSTEM_ROUTE(old_re)))
    2159           0 :                         zebra_rib_fixup_system(rn);
    2160             :                 break;
    2161             : 
    2162             :         case DPLANE_OP_NONE:
    2163             :         case DPLANE_OP_ROUTE_NOTIFY:
    2164             :         case DPLANE_OP_NH_INSTALL:
    2165             :         case DPLANE_OP_NH_UPDATE:
    2166             :         case DPLANE_OP_NH_DELETE:
    2167             :         case DPLANE_OP_LSP_INSTALL:
    2168             :         case DPLANE_OP_LSP_UPDATE:
    2169             :         case DPLANE_OP_LSP_DELETE:
    2170             :         case DPLANE_OP_LSP_NOTIFY:
    2171             :         case DPLANE_OP_PW_INSTALL:
    2172             :         case DPLANE_OP_PW_UNINSTALL:
    2173             :         case DPLANE_OP_SYS_ROUTE_ADD:
    2174             :         case DPLANE_OP_SYS_ROUTE_DELETE:
    2175             :         case DPLANE_OP_ADDR_INSTALL:
    2176             :         case DPLANE_OP_ADDR_UNINSTALL:
    2177             :         case DPLANE_OP_MAC_INSTALL:
    2178             :         case DPLANE_OP_MAC_DELETE:
    2179             :         case DPLANE_OP_NEIGH_INSTALL:
    2180             :         case DPLANE_OP_NEIGH_UPDATE:
    2181             :         case DPLANE_OP_NEIGH_DELETE:
    2182             :         case DPLANE_OP_VTEP_ADD:
    2183             :         case DPLANE_OP_VTEP_DELETE:
    2184             :         case DPLANE_OP_RULE_ADD:
    2185             :         case DPLANE_OP_RULE_DELETE:
    2186             :         case DPLANE_OP_RULE_UPDATE:
    2187             :         case DPLANE_OP_NEIGH_DISCOVER:
    2188             :         case DPLANE_OP_BR_PORT_UPDATE:
    2189             :         case DPLANE_OP_IPTABLE_ADD:
    2190             :         case DPLANE_OP_IPTABLE_DELETE:
    2191             :         case DPLANE_OP_IPSET_ADD:
    2192             :         case DPLANE_OP_IPSET_DELETE:
    2193             :         case DPLANE_OP_IPSET_ENTRY_ADD:
    2194             :         case DPLANE_OP_IPSET_ENTRY_DELETE:
    2195             :         case DPLANE_OP_NEIGH_IP_INSTALL:
    2196             :         case DPLANE_OP_NEIGH_IP_DELETE:
    2197             :         case DPLANE_OP_NEIGH_TABLE_UPDATE:
    2198             :         case DPLANE_OP_GRE_SET:
    2199             :         case DPLANE_OP_INTF_ADDR_ADD:
    2200             :         case DPLANE_OP_INTF_ADDR_DEL:
    2201             :         case DPLANE_OP_INTF_NETCONFIG:
    2202             :         case DPLANE_OP_INTF_INSTALL:
    2203             :         case DPLANE_OP_INTF_UPDATE:
    2204             :         case DPLANE_OP_INTF_DELETE:
    2205             :         case DPLANE_OP_TC_QDISC_INSTALL:
    2206             :         case DPLANE_OP_TC_QDISC_UNINSTALL:
    2207             :         case DPLANE_OP_TC_CLASS_ADD:
    2208             :         case DPLANE_OP_TC_CLASS_DELETE:
    2209             :         case DPLANE_OP_TC_CLASS_UPDATE:
    2210             :         case DPLANE_OP_TC_FILTER_ADD:
    2211             :         case DPLANE_OP_TC_FILTER_DELETE:
    2212             :         case DPLANE_OP_TC_FILTER_UPDATE:
    2213             :                 break;
    2214             :         }
    2215             : 
    2216           8 :         zebra_rib_evaluate_rn_nexthops(rn, seq, rt_delete);
    2217           8 :         zebra_rib_evaluate_mpls(rn);
    2218           8 : done:
    2219             : 
    2220           8 :         if (rn)
    2221           8 :                 route_unlock_node(rn);
    2222           8 : }
    2223             : 
    2224             : /*
    2225             :  * Count installed/FIB nexthops
    2226             :  */
    2227           0 : static int rib_count_installed_nh(struct route_entry *re)
    2228             : {
    2229           0 :         int count = 0;
    2230           0 :         struct nexthop *nexthop;
    2231           0 :         struct nexthop_group *nhg;
    2232             : 
    2233           0 :         nhg = rib_get_fib_nhg(re);
    2234             : 
    2235           0 :         for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
    2236             :                 /* The meaningful flag depends on where the installed
    2237             :                  * nexthops reside.
    2238             :                  */
    2239           0 :                 if (nhg == &(re->fib_ng)) {
    2240           0 :                         if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
    2241           0 :                                 count++;
    2242             :                 } else {
    2243           0 :                         if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
    2244           0 :                                 count++;
    2245             :                 }
    2246             :         }
    2247             : 
    2248           0 :         nhg = rib_get_fib_backup_nhg(re);
    2249           0 :         if (nhg) {
    2250           0 :                 for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
    2251           0 :                         if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
    2252           0 :                                 count++;
    2253             :                 }
    2254             :         }
    2255             : 
    2256           0 :         return count;
    2257             : }
    2258             : 
    2259             : /*
    2260             :  * Handle notification from async dataplane: the dataplane has detected
    2261             :  * some change to a route, and notifies zebra so that the control plane
    2262             :  * can reflect that change.
    2263             :  */
    2264           0 : static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
    2265             : {
    2266           0 :         struct route_node *rn = NULL;
    2267           0 :         struct route_entry *re = NULL;
    2268           0 :         struct vrf *vrf;
    2269           0 :         struct nexthop *nexthop;
    2270           0 :         rib_dest_t *dest;
    2271           0 :         bool fib_changed = false;
    2272           0 :         bool debug_p = IS_ZEBRA_DEBUG_DPLANE | IS_ZEBRA_DEBUG_RIB;
    2273           0 :         int start_count, end_count;
    2274             : 
    2275           0 :         vrf = vrf_lookup_by_id(dplane_ctx_get_vrf(ctx));
    2276             : 
    2277             :         /* Locate rn and re(s) from ctx */
    2278           0 :         rn = rib_find_rn_from_ctx(ctx);
    2279           0 :         if (rn == NULL) {
    2280           0 :                 if (debug_p) {
    2281           0 :                         zlog_debug(
    2282             :                                 "Failed to process dplane notification: no routes for %s(%u:%u):%pRN",
    2283             :                                 VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
    2284             :                                 dplane_ctx_get_table(ctx), rn);
    2285             :                 }
    2286           0 :                 goto done;
    2287             :         }
    2288             : 
    2289           0 :         dest = rib_dest_from_rnode(rn);
    2290             : 
    2291           0 :         if (debug_p)
    2292           0 :                 zlog_debug("%s(%u:%u):%pRN Processing dplane notif ctx %p",
    2293             :                            VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
    2294             :                            dplane_ctx_get_table(ctx), rn, ctx);
    2295             : 
    2296             :         /*
    2297             :          * Take a pass through the routes, look for matches with the context
    2298             :          * info.
    2299             :          */
    2300           0 :         RNODE_FOREACH_RE(rn, re) {
    2301           0 :                 if (rib_route_match_ctx(re, ctx, false /*!update*/))
    2302             :                         break;
    2303             :         }
    2304             : 
    2305             :         /* No match? Nothing we can do */
    2306           0 :         if (re == NULL) {
    2307           0 :                 if (debug_p)
    2308           0 :                         zlog_debug(
    2309             :                                 "%s(%u:%u):%pRN Unable to process dplane notification: no entry for type %s",
    2310             :                                 VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
    2311             :                                 dplane_ctx_get_table(ctx), rn,
    2312             :                                 zebra_route_string(dplane_ctx_get_type(ctx)));
    2313             : 
    2314           0 :                 goto done;
    2315             :         }
    2316             : 
    2317             :         /* Ensure we clear the QUEUED flag */
    2318           0 :         UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
    2319           0 :         UNSET_FLAG(re->status, ROUTE_ENTRY_ROUTE_REPLACING);
    2320             : 
    2321             :         /* Is this a notification that ... matters? We mostly care about
    2322             :          * the route that is currently selected for installation; we may also
    2323             :          * get an un-install notification, and handle that too.
    2324             :          */
    2325           0 :         if (re != dest->selected_fib) {
    2326             :                 /*
    2327             :                  * If we need to, clean up after a delete that was part of
    2328             :                  * an update operation.
    2329             :                  */
    2330           0 :                 end_count = 0;
    2331           0 :                 for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) {
    2332           0 :                         if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
    2333           0 :                                 end_count++;
    2334             :                 }
    2335             : 
    2336             :                 /* If no nexthops or none installed, ensure that this re
    2337             :                  * gets its 'installed' flag cleared.
    2338             :                  */
    2339           0 :                 if (end_count == 0) {
    2340           0 :                         if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED))
    2341           0 :                                 UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
    2342           0 :                         if (debug_p)
    2343           0 :                                 zlog_debug(
    2344             :                                         "%s(%u:%u):%pRN dplane notif, uninstalled type %s route",
    2345             :                                         VRF_LOGNAME(vrf),
    2346             :                                         dplane_ctx_get_vrf(ctx),
    2347             :                                         dplane_ctx_get_table(ctx), rn,
    2348             :                                         zebra_route_string(
    2349             :                                                 dplane_ctx_get_type(ctx)));
    2350             :                 } else {
    2351             :                         /* At least report on the event. */
    2352           0 :                         if (debug_p)
    2353           0 :                                 zlog_debug(
    2354             :                                         "%s(%u:%u):%pRN dplane notif, but type %s not selected_fib",
    2355             :                                         VRF_LOGNAME(vrf),
    2356             :                                         dplane_ctx_get_vrf(ctx),
    2357             :                                         dplane_ctx_get_table(ctx), rn,
    2358             :                                         zebra_route_string(
    2359             :                                                 dplane_ctx_get_type(ctx)));
    2360             :                 }
    2361           0 :                 goto done;
    2362             :         } else {
    2363           0 :                 uint32_t flags = dplane_ctx_get_flags(ctx);
    2364             : 
    2365           0 :                 if (CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOADED)) {
    2366           0 :                         UNSET_FLAG(re->flags, ZEBRA_FLAG_OFFLOAD_FAILED);
    2367           0 :                         SET_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED);
    2368             :                 }
    2369           0 :                 if (CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOAD_FAILED)) {
    2370           0 :                         UNSET_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED);
    2371           0 :                         SET_FLAG(re->flags, ZEBRA_FLAG_OFFLOAD_FAILED);
    2372             :                 }
    2373           0 :                 if (CHECK_FLAG(flags, ZEBRA_FLAG_TRAPPED))
    2374           0 :                         SET_FLAG(re->flags, ZEBRA_FLAG_TRAPPED);
    2375             :         }
    2376             : 
    2377             :         /* We'll want to determine whether the installation status of the
    2378             :          * route has changed: we'll check the status before processing,
    2379             :          * and then again if there's been a change.
    2380             :          */
    2381           0 :         start_count = 0;
    2382             : 
    2383           0 :         if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED))
    2384           0 :                 start_count = rib_count_installed_nh(re);
    2385             : 
    2386             :         /* Update zebra's nexthop FIB flags based on the context struct's
    2387             :          * nexthops.
    2388             :          */
    2389           0 :         fib_changed = rib_update_re_from_ctx(re, rn, ctx);
    2390             : 
    2391           0 :         if (!fib_changed) {
    2392           0 :                 if (debug_p)
    2393           0 :                         zlog_debug(
    2394             :                                 "%s(%u:%u):%pRN dplane notification: rib_update returns FALSE",
    2395             :                                 VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
    2396             :                                 dplane_ctx_get_table(ctx), rn);
    2397             :         }
    2398             : 
    2399             :         /*
    2400             :          * Perform follow-up work if the actual status of the prefix
    2401             :          * changed.
    2402             :          */
    2403           0 :         end_count = rib_count_installed_nh(re);
    2404             : 
    2405             :         /* Various fib transitions: changed nexthops; from installed to
    2406             :          * not-installed; or not-installed to installed.
    2407             :          */
    2408           0 :         if (zrouter.asic_notification_nexthop_control) {
    2409           0 :                 if (start_count > 0 && end_count > 0) {
    2410           0 :                         if (debug_p)
    2411           0 :                                 zlog_debug(
    2412             :                                         "%s(%u:%u):%pRN applied nexthop changes from dplane notification",
    2413             :                                         VRF_LOGNAME(vrf),
    2414             :                                         dplane_ctx_get_vrf(ctx),
    2415             :                                         dplane_ctx_get_table(ctx), rn);
    2416             : 
    2417             :                         /* Changed nexthops - update kernel/others */
    2418           0 :                         dplane_route_notif_update(rn, re,
    2419             :                                                   DPLANE_OP_ROUTE_UPDATE, ctx);
    2420             : 
    2421           0 :                 } else if (start_count == 0 && end_count > 0) {
    2422           0 :                         if (debug_p)
    2423           0 :                                 zlog_debug(
    2424             :                                         "%s(%u:%u):%pRN installed transition from dplane notification",
    2425             :                                         VRF_LOGNAME(vrf),
    2426             :                                         dplane_ctx_get_vrf(ctx),
    2427             :                                         dplane_ctx_get_table(ctx), rn);
    2428             : 
    2429             :                         /* We expect this to be the selected route, so we want
    2430             :                          * to tell others about this transition.
    2431             :                          */
    2432           0 :                         SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
    2433             : 
    2434             :                         /* Changed nexthops - update kernel/others */
    2435           0 :                         dplane_route_notif_update(rn, re,
    2436             :                                                   DPLANE_OP_ROUTE_UPDATE, ctx);
    2437             : 
    2438             :                         /* Redistribute, lsp, and nht update */
    2439           0 :                         redistribute_update(rn, re, NULL);
    2440             : 
    2441           0 :                 } else if (start_count > 0 && end_count == 0) {
    2442           0 :                         if (debug_p)
    2443           0 :                                 zlog_debug(
    2444             :                                         "%s(%u:%u):%pRN un-installed transition from dplane notification",
    2445             :                                         VRF_LOGNAME(vrf),
    2446             :                                         dplane_ctx_get_vrf(ctx),
    2447             :                                         dplane_ctx_get_table(ctx), rn);
    2448             : 
    2449             :                         /* Transition from _something_ installed to _nothing_
    2450             :                          * installed.
    2451             :                          */
    2452             :                         /* We expect this to be the selected route, so we want
    2453             :                          * to tell others about this transistion.
    2454             :                          */
    2455           0 :                         UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
    2456             : 
    2457             :                         /* Changed nexthops - update kernel/others */
    2458           0 :                         dplane_route_notif_update(rn, re,
    2459             :                                                   DPLANE_OP_ROUTE_DELETE, ctx);
    2460             : 
    2461             :                         /* Redistribute, lsp, and nht update */
    2462           0 :                         redistribute_delete(rn, re, NULL);
    2463             :                 }
    2464             :         }
    2465             : 
    2466           0 :         if (!zebra_router_notify_on_ack()) {
    2467           0 :                 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED))
    2468           0 :                         zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_INSTALLED);
    2469           0 :                 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOAD_FAILED))
    2470           0 :                         zsend_route_notify_owner_ctx(ctx,
    2471             :                                                      ZAPI_ROUTE_FAIL_INSTALL);
    2472             :         }
    2473             : 
    2474             :         /* Make any changes visible for lsp and nexthop-tracking processing */
    2475           0 :         zebra_rib_evaluate_rn_nexthops(rn, zebra_router_get_next_sequence(),
    2476             :                                        false);
    2477             : 
    2478           0 :         zebra_rib_evaluate_mpls(rn);
    2479             : 
    2480           0 : done:
    2481           0 :         if (rn)
    2482           0 :                 route_unlock_node(rn);
    2483           0 : }
    2484             : 
    2485             : /*
    2486             :  * Process a node from the EVPN/VXLAN subqueue.
    2487             :  */
    2488           0 : static void process_subq_evpn(struct listnode *lnode)
    2489             : {
    2490           0 :         struct wq_evpn_wrapper *w;
    2491             : 
    2492             :         /* In general, the list node points to a wrapper object
    2493             :          * holding the info necessary to make some update.
    2494             :          */
    2495           0 :         w = listgetdata(lnode);
    2496           0 :         if (!w)
    2497             :                 return;
    2498             : 
    2499           0 :         if (w->type == WQ_EVPN_WRAPPER_TYPE_VRFROUTE) {
    2500           0 :                 if (w->add_p)
    2501           0 :                         zebra_vxlan_evpn_vrf_route_add(w->vrf_id, &w->macaddr,
    2502           0 :                                                        &w->ip, &w->prefix);
    2503             :                 else
    2504           0 :                         zebra_vxlan_evpn_vrf_route_del(w->vrf_id, &w->ip,
    2505             :                                                        &w->prefix);
    2506           0 :         } else if (w->type == WQ_EVPN_WRAPPER_TYPE_REM_ES) {
    2507           0 :                 if (w->add_p)
    2508           0 :                         zebra_evpn_remote_es_add(&w->esi, w->ip.ipaddr_v4,
    2509           0 :                                                  w->esr_rxed, w->df_alg,
    2510           0 :                                                  w->df_pref);
    2511             :                 else
    2512           0 :                         zebra_evpn_remote_es_del(&w->esi, w->ip.ipaddr_v4);
    2513           0 :         } else if (w->type == WQ_EVPN_WRAPPER_TYPE_REM_MACIP) {
    2514           0 :                 uint16_t ipa_len = 0;
    2515             : 
    2516           0 :                 if (w->ip.ipa_type == IPADDR_V4)
    2517             :                         ipa_len = IPV4_MAX_BYTELEN;
    2518           0 :                 else if (w->ip.ipa_type == IPADDR_V6)
    2519           0 :                         ipa_len = IPV6_MAX_BYTELEN;
    2520             : 
    2521           0 :                 if (w->add_p)
    2522           0 :                         zebra_evpn_rem_macip_add(w->vni, &w->macaddr, ipa_len,
    2523           0 :                                                  &w->ip, w->flags, w->seq,
    2524           0 :                                                  w->vtep_ip, &w->esi);
    2525             :                 else
    2526           0 :                         zebra_evpn_rem_macip_del(w->vni, &w->macaddr, ipa_len,
    2527           0 :                                                  &w->ip, w->vtep_ip);
    2528           0 :         } else if (w->type == WQ_EVPN_WRAPPER_TYPE_REM_VTEP) {
    2529           0 :                 if (w->add_p)
    2530           0 :                         zebra_vxlan_remote_vtep_add(w->vrf_id, w->vni,
    2531           0 :                                                     w->vtep_ip, w->flags);
    2532             :                 else
    2533           0 :                         zebra_vxlan_remote_vtep_del(w->vrf_id, w->vni,
    2534             :                                                     w->vtep_ip);
    2535             :         }
    2536             : 
    2537             : 
    2538           0 :         XFREE(MTYPE_WQ_WRAPPER, w);
    2539             : }
    2540             : 
    2541             : /*
    2542             :  * Process the nexthop-group workqueue subqueue
    2543             :  */
    2544           0 : static void process_subq_nhg(struct listnode *lnode)
    2545             : {
    2546           0 :         struct nhg_ctx *ctx;
    2547           0 :         struct nhg_hash_entry *nhe, *newnhe;
    2548           0 :         struct wq_nhg_wrapper *w;
    2549           0 :         uint8_t qindex = META_QUEUE_NHG;
    2550             : 
    2551           0 :         w = listgetdata(lnode);
    2552             : 
    2553           0 :         if (!w)
    2554             :                 return;
    2555             : 
    2556             :         /* Two types of object - an update from the local kernel, or
    2557             :          * an nhg update from a daemon.
    2558             :          */
    2559           0 :         if (w->type == WQ_NHG_WRAPPER_TYPE_CTX) {
    2560           0 :                 ctx = w->u.ctx;
    2561             : 
    2562           0 :                 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
    2563           0 :                         zlog_debug(
    2564             :                                 "NHG Context id=%u dequeued from sub-queue %s",
    2565             :                                 ctx->id, subqueue2str(qindex));
    2566             : 
    2567             : 
    2568             :                 /* Process nexthop group updates coming 'up' from the OS */
    2569           0 :                 nhg_ctx_process(ctx);
    2570             : 
    2571           0 :         } else if (w->type == WQ_NHG_WRAPPER_TYPE_NHG) {
    2572           0 :                 nhe = w->u.nhe;
    2573             : 
    2574           0 :                 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
    2575           0 :                         zlog_debug("NHG %u dequeued from sub-queue %s", nhe->id,
    2576             :                                    subqueue2str(qindex));
    2577             : 
    2578             :                 /* Process incoming nhg update, probably from a proto daemon */
    2579           0 :                 newnhe = zebra_nhg_proto_add(nhe->id, nhe->type,
    2580           0 :                                              nhe->zapi_instance,
    2581             :                                              nhe->zapi_session, &nhe->nhg, 0);
    2582             : 
    2583             :                 /* Report error to daemon via ZAPI */
    2584           0 :                 if (newnhe == NULL)
    2585           0 :                         zsend_nhg_notify(nhe->type, nhe->zapi_instance,
    2586             :                                          nhe->zapi_session, nhe->id,
    2587             :                                          ZAPI_NHG_FAIL_INSTALL);
    2588             : 
    2589             :                 /* Free temp nhe - we own that memory. */
    2590           0 :                 zebra_nhg_free(nhe);
    2591             :         }
    2592             : 
    2593           0 :         XFREE(MTYPE_WQ_WRAPPER, w);
    2594             : }
    2595             : 
    2596           0 : static void process_subq_early_label(struct listnode *lnode)
    2597             : {
    2598           0 :         struct wq_label_wrapper *w = listgetdata(lnode);
    2599           0 :         struct zebra_vrf *zvrf;
    2600             : 
    2601           0 :         if (!w)
    2602             :                 return;
    2603             : 
    2604           0 :         zvrf = vrf_info_lookup(w->vrf_id);
    2605           0 :         if (!zvrf) {
    2606           0 :                 XFREE(MTYPE_WQ_WRAPPER, w);
    2607           0 :                 return;
    2608             :         }
    2609             : 
    2610           0 :         switch (w->type) {
    2611           0 :         case WQ_LABEL_FTN_UNINSTALL:
    2612           0 :                 zebra_mpls_ftn_uninstall(zvrf, w->ltype, &w->p, w->route_type,
    2613           0 :                                          w->route_instance);
    2614           0 :                 break;
    2615           0 :         case WQ_LABEL_LABELS_PROCESS:
    2616           0 :                 zebra_mpls_zapi_labels_process(w->add_p, zvrf, &w->zl);
    2617           0 :                 break;
    2618             :         }
    2619             : 
    2620           0 :         XFREE(MTYPE_WQ_WRAPPER, w);
    2621             : }
    2622             : 
    2623          16 : static void process_subq_route(struct listnode *lnode, uint8_t qindex)
    2624             : {
    2625          16 :         struct route_node *rnode = NULL;
    2626          16 :         rib_dest_t *dest = NULL;
    2627          16 :         struct zebra_vrf *zvrf = NULL;
    2628             : 
    2629          16 :         rnode = listgetdata(lnode);
    2630          16 :         dest = rib_dest_from_rnode(rnode);
    2631          16 :         assert(dest);
    2632             : 
    2633          16 :         zvrf = rib_dest_vrf(dest);
    2634             : 
    2635          16 :         rib_process(rnode);
    2636             : 
    2637          16 :         if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
    2638          16 :                 struct route_entry *re = NULL;
    2639             : 
    2640             :                 /*
    2641             :                  * rib_process may have freed the dest
    2642             :                  * as part of the garbage collection.  Let's
    2643             :                  * prevent stupidity from happening.
    2644             :                  */
    2645          16 :                 dest = rib_dest_from_rnode(rnode);
    2646          16 :                 if (dest)
    2647          16 :                         re = re_list_first(&dest->routes);
    2648             : 
    2649          48 :                 zlog_debug("%s(%u:%u):%pRN rn %p dequeued from sub-queue %s",
    2650             :                            zvrf_name(zvrf), zvrf_id(zvrf), re ? re->table : 0,
    2651             :                            rnode, rnode, subqueue2str(qindex));
    2652             :         }
    2653             : 
    2654          16 :         if (rnode->info)
    2655          16 :                 UNSET_FLAG(rib_dest_from_rnode(rnode)->flags,
    2656             :                            RIB_ROUTE_QUEUED(qindex));
    2657             : 
    2658          16 :         route_unlock_node(rnode);
    2659          16 : }
    2660             : 
    2661          16 : static void rib_re_nhg_free(struct route_entry *re)
    2662             : {
    2663          16 :         if (re->nhe && re->nhe_id) {
    2664          16 :                 assert(re->nhe->id == re->nhe_id);
    2665          16 :                 route_entry_update_nhe(re, NULL);
    2666           0 :         } else if (re->nhe && re->nhe->nhg.nexthop)
    2667           0 :                 nexthops_free(re->nhe->nhg.nexthop);
    2668             : 
    2669          16 :         nexthops_free(re->fib_ng.nexthop);
    2670          16 : }
    2671             : 
    2672             : struct zebra_early_route {
    2673             :         afi_t afi;
    2674             :         safi_t safi;
    2675             :         struct prefix p;
    2676             :         struct prefix_ipv6 src_p;
    2677             :         bool src_p_provided;
    2678             :         struct route_entry *re;
    2679             :         struct nhg_hash_entry *re_nhe;
    2680             :         bool startup;
    2681             :         bool deletion;
    2682             :         bool fromkernel;
    2683             : };
    2684             : 
    2685           0 : static void early_route_memory_free(struct zebra_early_route *ere)
    2686             : {
    2687           0 :         if (ere->re_nhe)
    2688           0 :                 zebra_nhg_free(ere->re_nhe);
    2689             : 
    2690           0 :         XFREE(MTYPE_RE, ere->re);
    2691           0 :         XFREE(MTYPE_WQ_WRAPPER, ere);
    2692           0 : }
    2693             : 
    2694          16 : static void process_subq_early_route_add(struct zebra_early_route *ere)
    2695             : {
    2696          16 :         struct route_entry *re = ere->re;
    2697          16 :         struct route_table *table;
    2698          16 :         struct nhg_hash_entry *nhe = NULL;
    2699          16 :         struct route_node *rn;
    2700          16 :         struct route_entry *same = NULL, *first_same = NULL;
    2701          16 :         int same_count = 0;
    2702          16 :         rib_dest_t *dest;
    2703             : 
    2704             :         /* Lookup table.  */
    2705          16 :         table = zebra_vrf_get_table_with_table_id(ere->afi, ere->safi,
    2706             :                                                   re->vrf_id, re->table);
    2707          16 :         if (!table) {
    2708           0 :                 early_route_memory_free(ere);
    2709           0 :                 return;
    2710             :         }
    2711             : 
    2712          16 :         if (re->nhe_id > 0) {
    2713           0 :                 nhe = zebra_nhg_lookup_id(re->nhe_id);
    2714             : 
    2715           0 :                 if (!nhe) {
    2716             :                         /*
    2717             :                          * We've received from the kernel a nexthop id
    2718             :                          * that we don't have saved yet.  More than likely
    2719             :                          * it has not been processed and is on the
    2720             :                          * queue to be processed.  Let's stop what we
    2721             :                          * are doing and cause the meta q to be processed
    2722             :                          * storing this for later.
    2723             :                          *
    2724             :                          * This is being done this way because zebra
    2725             :                          * runs with the assumption t
    2726             :                          */
    2727           0 :                         flog_err(
    2728             :                                 EC_ZEBRA_TABLE_LOOKUP_FAILED,
    2729             :                                 "Zebra failed to find the nexthop hash entry for id=%u in a route entry %pFX",
    2730             :                                 re->nhe_id, &ere->p);
    2731             : 
    2732           0 :                         early_route_memory_free(ere);
    2733           0 :                         return;
    2734             :                 }
    2735             :         } else {
    2736             :                 /* Lookup nhe from route information */
    2737          16 :                 nhe = zebra_nhg_rib_find_nhe(ere->re_nhe, ere->afi);
    2738          16 :                 if (!nhe) {
    2739           0 :                         char buf2[PREFIX_STRLEN] = "";
    2740             : 
    2741           0 :                         flog_err(
    2742             :                                 EC_ZEBRA_TABLE_LOOKUP_FAILED,
    2743             :                                 "Zebra failed to find or create a nexthop hash entry for %pFX%s%s",
    2744             :                                 &ere->p, ere->src_p_provided ? " from " : "",
    2745             :                                 ere->src_p_provided
    2746             :                                         ? prefix2str(&ere->src_p, buf2,
    2747             :                                                      sizeof(buf2))
    2748             :                                         : "");
    2749             : 
    2750           0 :                         early_route_memory_free(ere);
    2751           0 :                         return;
    2752             :                 }
    2753             :         }
    2754             : 
    2755             :         /*
    2756             :          * Attach the re to the nhe's nexthop group.
    2757             :          *
    2758             :          * TODO: This will need to change when we start getting IDs from upper
    2759             :          * level protocols, as the refcnt might be wrong, since it checks
    2760             :          * if old_id != new_id.
    2761             :          */
    2762          16 :         route_entry_update_nhe(re, nhe);
    2763             : 
    2764             :         /* Make it sure prefixlen is applied to the prefix. */
    2765          16 :         apply_mask(&ere->p);
    2766          16 :         if (ere->src_p_provided)
    2767           0 :                 apply_mask_ipv6(&ere->src_p);
    2768             : 
    2769             :         /* Lookup route node.*/
    2770          16 :         rn = srcdest_rnode_get(table, &ere->p,
    2771          16 :                                ere->src_p_provided ? &ere->src_p : NULL);
    2772             : 
    2773             :         /*
    2774             :          * If same type of route are installed, treat it as a implicit
    2775             :          * withdraw. If the user has specified the No route replace semantics
    2776             :          * for the install don't do a route replace.
    2777             :          */
    2778          36 :         RNODE_FOREACH_RE (rn, same) {
    2779           2 :                 if (CHECK_FLAG(same->status, ROUTE_ENTRY_REMOVED)) {
    2780           0 :                         same_count++;
    2781           0 :                         continue;
    2782             :                 }
    2783             : 
    2784             :                 /* Compare various route_entry properties */
    2785           2 :                 if (rib_compare_routes(re, same)) {
    2786           0 :                         same_count++;
    2787             : 
    2788           0 :                         if (first_same == NULL)
    2789           0 :                                 first_same = same;
    2790             :                 }
    2791             :         }
    2792             : 
    2793          16 :         same = first_same;
    2794             : 
    2795          16 :         if (!ere->startup && (re->flags & ZEBRA_FLAG_SELFROUTE) &&
    2796           0 :             zrouter.asic_offloaded) {
    2797           0 :                 if (!same) {
    2798           0 :                         if (IS_ZEBRA_DEBUG_RIB)
    2799           0 :                                 zlog_debug(
    2800             :                                         "prefix: %pRN is a self route where we do not have an entry for it.  Dropping this update, it's useless",
    2801             :                                         rn);
    2802             :                         /*
    2803             :                          * We are not on startup, this is a self route
    2804             :                          * and we have asic offload.  Which means
    2805             :                          * we are getting a callback for a entry
    2806             :                          * that was already deleted to the kernel
    2807             :                          * but an earlier response was just handed
    2808             :                          * back.  Drop it on the floor
    2809             :                          */
    2810           0 :                         early_route_memory_free(ere);
    2811           0 :                         return;
    2812             :                 }
    2813             :         }
    2814             : 
    2815             :         /* Set default distance by route type. */
    2816          16 :         if (re->distance == 0) {
    2817          16 :                 if (same && !zebra_router_notify_on_ack())
    2818           0 :                         re->distance = same->distance;
    2819             :                 else
    2820          32 :                         re->distance = route_distance(re->type);
    2821             :         }
    2822             : 
    2823          16 :         if (re->metric == ROUTE_INSTALLATION_METRIC &&
    2824           0 :             CHECK_FLAG(re->flags, ZEBRA_FLAG_SELFROUTE)) {
    2825           0 :                 if (same && !zebra_router_notify_on_ack())
    2826           0 :                         re->metric = same->metric;
    2827             :                 else
    2828           0 :                         re->metric = 0;
    2829             :         }
    2830             : 
    2831             :         /* If this route is kernel/connected route, notify the dataplane. */
    2832          16 :         if (RIB_SYSTEM_ROUTE(re)) {
    2833             :                 /* Notify dataplane */
    2834          16 :                 dplane_sys_route_add(rn, re);
    2835             :         }
    2836             : 
    2837             :         /* Link new re to node.*/
    2838          16 :         if (IS_ZEBRA_DEBUG_RIB) {
    2839          16 :                 rnode_debug(
    2840             :                         rn, re->vrf_id,
    2841             :                         "Inserting route rn %p, re %p (%s) existing %p, same_count %d",
    2842             :                         rn, re, zebra_route_string(re->type), same, same_count);
    2843             : 
    2844          16 :                 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
    2845          16 :                         route_entry_dump(
    2846             :                                 &ere->p,
    2847             :                                 ere->src_p_provided ? &ere->src_p : NULL, re);
    2848             :         }
    2849             : 
    2850          16 :         SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
    2851          16 :         rib_addnode(rn, re, 1);
    2852             : 
    2853             :         /* Free implicit route.*/
    2854          16 :         if (same)
    2855           0 :                 rib_delnode(rn, same);
    2856             : 
    2857             :         /* See if we can remove some RE entries that are queued for
    2858             :          * removal, but won't be considered in rib processing.
    2859             :          */
    2860          16 :         dest = rib_dest_from_rnode(rn);
    2861          50 :         RNODE_FOREACH_RE_SAFE (rn, re, same) {
    2862          18 :                 if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) {
    2863             :                         /* If the route was used earlier, must retain it. */
    2864           0 :                         if (dest && re == dest->selected_fib)
    2865           0 :                                 continue;
    2866             : 
    2867           0 :                         if (IS_ZEBRA_DEBUG_RIB)
    2868           0 :                                 rnode_debug(rn, re->vrf_id,
    2869             :                                             "rn %p, removing unneeded re %p",
    2870             :                                             rn, re);
    2871             : 
    2872           0 :                         rib_unlink(rn, re);
    2873             :                 }
    2874             :         }
    2875             : 
    2876          16 :         route_unlock_node(rn);
    2877          16 :         if (ere->re_nhe)
    2878          16 :                 zebra_nhg_free(ere->re_nhe);
    2879          16 :         XFREE(MTYPE_WQ_WRAPPER, ere);
    2880             : }
    2881             : 
    2882           0 : static void process_subq_early_route_delete(struct zebra_early_route *ere)
    2883             : {
    2884           0 :         struct route_table *table;
    2885           0 :         struct route_node *rn;
    2886           0 :         struct route_entry *re;
    2887           0 :         struct route_entry *fib = NULL;
    2888           0 :         struct route_entry *same = NULL;
    2889           0 :         struct nexthop *rtnh;
    2890           0 :         char buf2[INET6_ADDRSTRLEN];
    2891           0 :         rib_dest_t *dest;
    2892             : 
    2893           0 :         if (ere->src_p_provided)
    2894           0 :                 assert(!ere->src_p.prefixlen || ere->afi == AFI_IP6);
    2895             : 
    2896             :         /* Lookup table.  */
    2897           0 :         table = zebra_vrf_lookup_table_with_table_id(
    2898           0 :                 ere->afi, ere->safi, ere->re->vrf_id, ere->re->table);
    2899           0 :         if (!table) {
    2900           0 :                 early_route_memory_free(ere);
    2901           0 :                 return;
    2902             :         }
    2903             : 
    2904             :         /* Apply mask. */
    2905           0 :         apply_mask(&ere->p);
    2906           0 :         if (ere->src_p_provided)
    2907           0 :                 apply_mask_ipv6(&ere->src_p);
    2908             : 
    2909             :         /* Lookup route node. */
    2910           0 :         rn = srcdest_rnode_lookup(table, &ere->p,
    2911           0 :                                   ere->src_p_provided ? &ere->src_p : NULL);
    2912           0 :         if (!rn) {
    2913           0 :                 if (IS_ZEBRA_DEBUG_RIB) {
    2914           0 :                         char src_buf[PREFIX_STRLEN];
    2915           0 :                         struct vrf *vrf = vrf_lookup_by_id(ere->re->vrf_id);
    2916             : 
    2917           0 :                         if (ere->src_p_provided && ere->src_p.prefixlen)
    2918           0 :                                 prefix2str(&ere->src_p, src_buf,
    2919             :                                            sizeof(src_buf));
    2920             :                         else
    2921           0 :                                 src_buf[0] = '\0';
    2922             : 
    2923           0 :                         zlog_debug("%s[%d]:%pRN%s%s doesn't exist in rib",
    2924             :                                    vrf->name, ere->re->table, rn,
    2925             :                                    (src_buf[0] != '\0') ? " from " : "",
    2926             :                                    src_buf);
    2927             :                 }
    2928           0 :                 early_route_memory_free(ere);
    2929           0 :                 return;
    2930             :         }
    2931             : 
    2932           0 :         dest = rib_dest_from_rnode(rn);
    2933           0 :         fib = dest->selected_fib;
    2934             : 
    2935           0 :         struct nexthop *nh = NULL;
    2936             : 
    2937           0 :         if (ere->re->nhe)
    2938           0 :                 nh = ere->re->nhe->nhg.nexthop;
    2939             : 
    2940             :         /* Lookup same type route. */
    2941           0 :         RNODE_FOREACH_RE (rn, re) {
    2942           0 :                 if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
    2943           0 :                         continue;
    2944             : 
    2945           0 :                 if (re->type != ere->re->type)
    2946           0 :                         continue;
    2947           0 :                 if (re->instance != ere->re->instance)
    2948           0 :                         continue;
    2949           0 :                 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_RR_USE_DISTANCE) &&
    2950           0 :                     ere->re->distance != re->distance)
    2951           0 :                         continue;
    2952             : 
    2953           0 :                 if (re->type == ZEBRA_ROUTE_KERNEL &&
    2954           0 :                     re->metric != ere->re->metric)
    2955           0 :                         continue;
    2956           0 :                 if (re->type == ZEBRA_ROUTE_CONNECT && (rtnh = nh) &&
    2957           0 :                     rtnh->type == NEXTHOP_TYPE_IFINDEX && nh) {
    2958           0 :                         if (rtnh->ifindex != nh->ifindex)
    2959             :                                 continue;
    2960             :                         same = re;
    2961             :                         break;
    2962             :                 }
    2963             : 
    2964             :                 /* Make sure that the route found has the same gateway. */
    2965           0 :                 if (ere->re->nhe_id && re->nhe_id == ere->re->nhe_id) {
    2966             :                         same = re;
    2967             :                         break;
    2968             :                 }
    2969             : 
    2970           0 :                 if (nh == NULL) {
    2971             :                         same = re;
    2972             :                         break;
    2973             :                 }
    2974           0 :                 for (ALL_NEXTHOPS(re->nhe->nhg, rtnh)) {
    2975             :                         /*
    2976             :                          * No guarantee all kernel send nh with labels
    2977             :                          * on delete.
    2978             :                          */
    2979           0 :                         if (nexthop_same_no_labels(rtnh, nh)) {
    2980             :                                 same = re;
    2981             :                                 break;
    2982             :                         }
    2983             :                 }
    2984             : 
    2985           0 :                 if (same)
    2986             :                         break;
    2987             :         }
    2988             :         /*
    2989             :          * If same type of route can't be found and this message is from
    2990             :          * kernel.
    2991             :          */
    2992           0 :         if (!same) {
    2993             :                 /*
    2994             :                  * In the past(HA!) we could get here because
    2995             :                  * we were receiving a route delete from the
    2996             :                  * kernel and we're not marking the proto
    2997             :                  * as coming from it's appropriate originator.
    2998             :                  * Now that we are properly noticing the fact
    2999             :                  * that the kernel has deleted our route we
    3000             :                  * are not going to get called in this path
    3001             :                  * I am going to leave this here because
    3002             :                  * this might still work this way on non-linux
    3003             :                  * platforms as well as some weird state I have
    3004             :                  * not properly thought of yet.
    3005             :                  * If we can show that this code path is
    3006             :                  * dead then we can remove it.
    3007             :                  */
    3008           0 :                 if (fib && CHECK_FLAG(ere->re->flags, ZEBRA_FLAG_SELFROUTE)) {
    3009           0 :                         if (IS_ZEBRA_DEBUG_RIB) {
    3010           0 :                                 rnode_debug(
    3011             :                                         rn, ere->re->vrf_id,
    3012             :                                         "rn %p, re %p (%s) was deleted from kernel, adding",
    3013             :                                         rn, fib, zebra_route_string(fib->type));
    3014             :                         }
    3015           0 :                         if (zrouter.allow_delete ||
    3016           0 :                             CHECK_FLAG(dest->flags, RIB_ROUTE_ANY_QUEUED)) {
    3017           0 :                                 UNSET_FLAG(fib->status, ROUTE_ENTRY_INSTALLED);
    3018             :                                 /* Unset flags. */
    3019           0 :                                 for (rtnh = fib->nhe->nhg.nexthop; rtnh;
    3020           0 :                                      rtnh = rtnh->next)
    3021           0 :                                         UNSET_FLAG(rtnh->flags,
    3022             :                                                    NEXTHOP_FLAG_FIB);
    3023             : 
    3024             :                                 /*
    3025             :                                  * This is a non FRR route
    3026             :                                  * as such we should mark
    3027             :                                  * it as deleted
    3028             :                                  */
    3029           0 :                                 dest->selected_fib = NULL;
    3030             :                         } else {
    3031             :                                 /*
    3032             :                                  * This means someone else, other than Zebra,
    3033             :                                  * has deleted a Zebra router from the kernel.
    3034             :                                  * We will add it back
    3035             :                                  */
    3036           0 :                                 rib_install_kernel(rn, fib, NULL);
    3037             :                         }
    3038             :                 } else {
    3039           0 :                         if (IS_ZEBRA_DEBUG_RIB) {
    3040           0 :                                 if (nh)
    3041           0 :                                         rnode_debug(
    3042             :                                                 rn, ere->re->vrf_id,
    3043             :                                                 "via %s ifindex %d type %d doesn't exist in rib",
    3044             :                                                 inet_ntop(afi2family(ere->afi),
    3045             :                                                           &nh->gate, buf2,
    3046             :                                                           sizeof(buf2)),
    3047             :                                                 nh->ifindex, ere->re->type);
    3048             :                                 else
    3049           0 :                                         rnode_debug(
    3050             :                                                 rn, ere->re->vrf_id,
    3051             :                                                 "type %d doesn't exist in rib",
    3052             :                                                 ere->re->type);
    3053             :                         }
    3054           0 :                         route_unlock_node(rn);
    3055           0 :                         early_route_memory_free(ere);
    3056           0 :                         return;
    3057             :                 }
    3058             :         }
    3059             : 
    3060           0 :         if (same) {
    3061           0 :                 struct nexthop *tmp_nh;
    3062             : 
    3063           0 :                 if (ere->fromkernel &&
    3064           0 :                     CHECK_FLAG(ere->re->flags, ZEBRA_FLAG_SELFROUTE) &&
    3065           0 :                     !zrouter.allow_delete) {
    3066           0 :                         rib_install_kernel(rn, same, NULL);
    3067           0 :                         route_unlock_node(rn);
    3068             : 
    3069           0 :                         early_route_memory_free(ere);
    3070           0 :                         return;
    3071             :                 }
    3072             : 
    3073             :                 /* Special handling for IPv4 or IPv6 routes sourced from
    3074             :                  * EVPN - the nexthop (and associated MAC) need to be
    3075             :                  * uninstalled if no more refs.
    3076             :                  */
    3077           0 :                 for (ALL_NEXTHOPS(re->nhe->nhg, tmp_nh)) {
    3078           0 :                         struct ipaddr vtep_ip;
    3079             : 
    3080           0 :                         if (CHECK_FLAG(tmp_nh->flags, NEXTHOP_FLAG_EVPN)) {
    3081           0 :                                 memset(&vtep_ip, 0, sizeof(struct ipaddr));
    3082           0 :                                 if (ere->afi == AFI_IP) {
    3083           0 :                                         vtep_ip.ipa_type = IPADDR_V4;
    3084           0 :                                         memcpy(&(vtep_ip.ipaddr_v4),
    3085             :                                                &(tmp_nh->gate.ipv4),
    3086             :                                                sizeof(struct in_addr));
    3087             :                                 } else {
    3088           0 :                                         vtep_ip.ipa_type = IPADDR_V6;
    3089           0 :                                         memcpy(&(vtep_ip.ipaddr_v6),
    3090             :                                                &(tmp_nh->gate.ipv6),
    3091             :                                                sizeof(struct in6_addr));
    3092             :                                 }
    3093           0 :                                 zebra_rib_queue_evpn_route_del(
    3094             :                                         re->vrf_id, &vtep_ip, &ere->p);
    3095             :                         }
    3096             :                 }
    3097             : 
    3098             :                 /* Notify dplane if system route changes */
    3099           0 :                 if (RIB_SYSTEM_ROUTE(re))
    3100           0 :                         dplane_sys_route_del(rn, same);
    3101             : 
    3102           0 :                 rib_delnode(rn, same);
    3103             :         }
    3104             : 
    3105           0 :         route_unlock_node(rn);
    3106             : 
    3107           0 :         early_route_memory_free(ere);
    3108             : }
    3109             : 
    3110             : /*
    3111             :  * When FRR receives a route we need to match the route up to
    3112             :  * nexthop groups.  That we also may have just received
    3113             :  * place the data on this queue so that this work of finding
    3114             :  * the nexthop group entries for the route entry is always
    3115             :  * done after the nexthop group has had a chance to be processed
    3116             :  */
    3117          16 : static void process_subq_early_route(struct listnode *lnode)
    3118             : {
    3119          16 :         struct zebra_early_route *ere = listgetdata(lnode);
    3120             : 
    3121          16 :         if (ere->deletion)
    3122           0 :                 process_subq_early_route_delete(ere);
    3123             :         else
    3124          16 :                 process_subq_early_route_add(ere);
    3125          16 : }
    3126             : 
    3127             : /*
    3128             :  * Examine the specified subqueue; process one entry and return 1 if
    3129             :  * there is a node, return 0 otherwise.
    3130             :  */
    3131         128 : static unsigned int process_subq(struct list *subq,
    3132             :                                  enum meta_queue_indexes qindex)
    3133             : {
    3134         128 :         struct listnode *lnode = listhead(subq);
    3135             : 
    3136         128 :         if (!lnode)
    3137             :                 return 0;
    3138             : 
    3139          32 :         switch (qindex) {
    3140           0 :         case META_QUEUE_EVPN:
    3141           0 :                 process_subq_evpn(lnode);
    3142           0 :                 break;
    3143           0 :         case META_QUEUE_NHG:
    3144           0 :                 process_subq_nhg(lnode);
    3145           0 :                 break;
    3146          16 :         case META_QUEUE_EARLY_ROUTE:
    3147          16 :                 process_subq_early_route(lnode);
    3148          16 :                 break;
    3149           0 :         case META_QUEUE_EARLY_LABEL:
    3150           0 :                 process_subq_early_label(lnode);
    3151           0 :                 break;
    3152          16 :         case META_QUEUE_CONNECTED:
    3153             :         case META_QUEUE_KERNEL:
    3154             :         case META_QUEUE_STATIC:
    3155             :         case META_QUEUE_NOTBGP:
    3156             :         case META_QUEUE_BGP:
    3157             :         case META_QUEUE_OTHER:
    3158          16 :                 process_subq_route(lnode, qindex);
    3159          16 :                 break;
    3160             :         }
    3161             : 
    3162          32 :         list_delete_node(subq, lnode);
    3163             : 
    3164          32 :         return 1;
    3165             : }
    3166             : 
    3167             : /* Dispatch the meta queue by picking and processing the next node from
    3168             :  * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and
    3169             :  * data is pointed to the meta queue structure.
    3170             :  */
    3171          32 : static wq_item_status meta_queue_process(struct work_queue *dummy, void *data)
    3172             : {
    3173          32 :         struct meta_queue *mq = data;
    3174          32 :         unsigned i;
    3175          32 :         uint32_t queue_len, queue_limit;
    3176             : 
    3177             :         /* Ensure there's room for more dataplane updates */
    3178          32 :         queue_limit = dplane_get_in_queue_limit();
    3179          32 :         queue_len = dplane_get_in_queue_len();
    3180          32 :         if (queue_len > queue_limit) {
    3181           0 :                 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
    3182           0 :                         zlog_debug(
    3183             :                                 "rib queue: dplane queue len %u, limit %u, retrying",
    3184             :                                 queue_len, queue_limit);
    3185             : 
    3186             :                 /* Ensure that the meta-queue is actually enqueued */
    3187           0 :                 if (work_queue_empty(zrouter.ribq))
    3188           0 :                         work_queue_add(zrouter.ribq, zrouter.mq);
    3189             : 
    3190           0 :                 return WQ_QUEUE_BLOCKED;
    3191             :         }
    3192             : 
    3193         128 :         for (i = 0; i < MQ_SIZE; i++)
    3194         128 :                 if (process_subq(mq->subq[i], i)) {
    3195          32 :                         mq->size--;
    3196          32 :                         break;
    3197             :                 }
    3198          32 :         return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
    3199             : }
    3200             : 
    3201             : 
    3202             : /*
    3203             :  * Look into the RN and queue it into the highest priority queue
    3204             :  * at this point in time for processing.
    3205             :  *
    3206             :  * We will enqueue a route node only once per invocation.
    3207             :  *
    3208             :  * There are two possibilities here that should be kept in mind.
    3209             :  * If the original invocation has not been pulled off for processing
    3210             :  * yet, A subsuquent invocation can have a route entry with a better
    3211             :  * meta queue index value and we can have a situation where
    3212             :  * we might have the same node enqueued 2 times.  Not necessarily
    3213             :  * an optimal situation but it should be ok.
    3214             :  *
    3215             :  * The other possibility is that the original invocation has not
    3216             :  * been pulled off for processing yet, A subsusquent invocation
    3217             :  * doesn't have a route_entry with a better meta-queue and the
    3218             :  * original metaqueue index value will win and we'll end up with
    3219             :  * the route node enqueued once.
    3220             :  */
    3221          16 : static int rib_meta_queue_add(struct meta_queue *mq, void *data)
    3222             : {
    3223          16 :         struct route_node *rn = NULL;
    3224          16 :         struct route_entry *re = NULL, *curr_re = NULL;
    3225          16 :         uint8_t qindex = MQ_SIZE, curr_qindex = MQ_SIZE;
    3226             : 
    3227          16 :         rn = (struct route_node *)data;
    3228             : 
    3229          68 :         RNODE_FOREACH_RE (rn, curr_re) {
    3230          18 :                 curr_qindex = route_info[curr_re->type].meta_q_map;
    3231             : 
    3232          18 :                 if (curr_qindex <= qindex) {
    3233          18 :                         re = curr_re;
    3234          18 :                         qindex = curr_qindex;
    3235             :                 }
    3236             :         }
    3237             : 
    3238          16 :         if (!re)
    3239             :                 return -1;
    3240             : 
    3241             :         /* Invariant: at this point we always have rn->info set. */
    3242          16 :         if (CHECK_FLAG(rib_dest_from_rnode(rn)->flags,
    3243             :                        RIB_ROUTE_QUEUED(qindex))) {
    3244           0 :                 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
    3245           0 :                         rnode_debug(rn, re->vrf_id,
    3246             :                                     "rn %p is already queued in sub-queue %s",
    3247             :                                     (void *)rn, subqueue2str(qindex));
    3248           0 :                 return -1;
    3249             :         }
    3250             : 
    3251          16 :         SET_FLAG(rib_dest_from_rnode(rn)->flags, RIB_ROUTE_QUEUED(qindex));
    3252          16 :         listnode_add(mq->subq[qindex], rn);
    3253          16 :         route_lock_node(rn);
    3254          16 :         mq->size++;
    3255             : 
    3256          16 :         if (IS_ZEBRA_DEBUG_RIB_DETAILED)
    3257          16 :                 rnode_debug(rn, re->vrf_id, "queued rn %p into sub-queue %s",
    3258             :                             (void *)rn, subqueue2str(qindex));
    3259             : 
    3260             :         return 0;
    3261             : }
    3262             : 
    3263           0 : static int early_label_meta_queue_add(struct meta_queue *mq, void *data)
    3264             : {
    3265           0 :         listnode_add(mq->subq[META_QUEUE_EARLY_LABEL], data);
    3266           0 :         mq->size++;
    3267           0 :         return 0;
    3268             : }
    3269             : 
    3270           0 : static int rib_meta_queue_nhg_ctx_add(struct meta_queue *mq, void *data)
    3271             : {
    3272           0 :         struct nhg_ctx *ctx = NULL;
    3273           0 :         uint8_t qindex = META_QUEUE_NHG;
    3274           0 :         struct wq_nhg_wrapper *w;
    3275             : 
    3276           0 :         ctx = (struct nhg_ctx *)data;
    3277             : 
    3278           0 :         if (!ctx)
    3279             :                 return -1;
    3280             : 
    3281           0 :         w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_nhg_wrapper));
    3282             : 
    3283           0 :         w->type = WQ_NHG_WRAPPER_TYPE_CTX;
    3284           0 :         w->u.ctx = ctx;
    3285             : 
    3286           0 :         listnode_add(mq->subq[qindex], w);
    3287           0 :         mq->size++;
    3288             : 
    3289           0 :         if (IS_ZEBRA_DEBUG_RIB_DETAILED)
    3290           0 :                 zlog_debug("NHG Context id=%u queued into sub-queue %s",
    3291             :                            ctx->id, subqueue2str(qindex));
    3292             : 
    3293             :         return 0;
    3294             : }
    3295             : 
    3296           0 : static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data)
    3297             : {
    3298           0 :         struct nhg_hash_entry *nhe = NULL;
    3299           0 :         uint8_t qindex = META_QUEUE_NHG;
    3300           0 :         struct wq_nhg_wrapper *w;
    3301             : 
    3302           0 :         nhe = (struct nhg_hash_entry *)data;
    3303             : 
    3304           0 :         if (!nhe)
    3305             :                 return -1;
    3306             : 
    3307           0 :         w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_nhg_wrapper));
    3308             : 
    3309           0 :         w->type = WQ_NHG_WRAPPER_TYPE_NHG;
    3310           0 :         w->u.nhe = nhe;
    3311             : 
    3312           0 :         listnode_add(mq->subq[qindex], w);
    3313           0 :         mq->size++;
    3314             : 
    3315           0 :         if (IS_ZEBRA_DEBUG_RIB_DETAILED)
    3316           0 :                 zlog_debug("NHG id=%u queued into sub-queue %s", nhe->id,
    3317             :                            subqueue2str(qindex));
    3318             : 
    3319             :         return 0;
    3320             : }
    3321             : 
    3322           0 : static int rib_meta_queue_evpn_add(struct meta_queue *mq, void *data)
    3323             : {
    3324           0 :         listnode_add(mq->subq[META_QUEUE_EVPN], data);
    3325           0 :         mq->size++;
    3326             : 
    3327           0 :         return 0;
    3328             : }
    3329             : 
    3330          32 : static int mq_add_handler(void *data,
    3331             :                           int (*mq_add_func)(struct meta_queue *mq, void *data))
    3332             : {
    3333          32 :         if (zrouter.ribq == NULL) {
    3334           0 :                 flog_err(EC_ZEBRA_WQ_NONEXISTENT,
    3335             :                          "%s: work_queue does not exist!", __func__);
    3336           0 :                 return -1;
    3337             :         }
    3338             : 
    3339             :         /*
    3340             :          * The RIB queue should normally be either empty or holding the only
    3341             :          * work_queue_item element. In the latter case this element would
    3342             :          * hold a pointer to the meta queue structure, which must be used to
    3343             :          * actually queue the route nodes to process. So create the MQ
    3344             :          * holder, if necessary, then push the work into it in any case.
    3345             :          * This semantics was introduced after 0.99.9 release.
    3346             :          */
    3347          32 :         if (work_queue_empty(zrouter.ribq))
    3348           3 :                 work_queue_add(zrouter.ribq, zrouter.mq);
    3349             : 
    3350          32 :         return mq_add_func(zrouter.mq, data);
    3351             : }
    3352             : 
    3353           0 : void mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
    3354             :                         struct prefix *prefix, uint8_t route_type,
    3355             :                         uint8_t route_instance)
    3356             : {
    3357           0 :         struct wq_label_wrapper *w;
    3358             : 
    3359           0 :         w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_label_wrapper));
    3360             : 
    3361           0 :         w->type = WQ_LABEL_FTN_UNINSTALL;
    3362           0 :         w->vrf_id = zvrf->vrf->vrf_id;
    3363           0 :         w->p = *prefix;
    3364           0 :         w->ltype = type;
    3365           0 :         w->route_type = route_type;
    3366           0 :         w->route_instance = route_instance;
    3367             : 
    3368           0 :         if (IS_ZEBRA_DEBUG_RIB_DETAILED)
    3369           0 :                 zlog_debug("Early Label Handling for %pFX", prefix);
    3370             : 
    3371           0 :         mq_add_handler(w, early_label_meta_queue_add);
    3372           0 : }
    3373             : 
    3374           0 : void mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
    3375             :                               const struct zapi_labels *zl)
    3376             : {
    3377           0 :         struct wq_label_wrapper *w;
    3378             : 
    3379           0 :         w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_label_wrapper));
    3380           0 :         w->type = WQ_LABEL_LABELS_PROCESS;
    3381           0 :         w->vrf_id = zvrf->vrf->vrf_id;
    3382           0 :         w->add_p = add_p;
    3383           0 :         w->zl = *zl;
    3384             : 
    3385           0 :         if (IS_ZEBRA_DEBUG_RIB_DETAILED)
    3386           0 :                 zlog_debug("Early Label Handling: Labels Process");
    3387             : 
    3388           0 :         mq_add_handler(w, early_label_meta_queue_add);
    3389           0 : }
    3390             : 
    3391             : /* Add route_node to work queue and schedule processing */
    3392          16 : int rib_queue_add(struct route_node *rn)
    3393             : {
    3394          16 :         assert(rn);
    3395             : 
    3396             :         /* Pointless to queue a route_node with no RIB entries to add or remove
    3397             :          */
    3398          32 :         if (!rnode_to_ribs(rn)) {
    3399           0 :                 zlog_debug("%s: called for route_node (%p, %u) with no ribs",
    3400             :                            __func__, (void *)rn, route_node_get_lock_count(rn));
    3401           0 :                 zlog_backtrace(LOG_DEBUG);
    3402           0 :                 return -1;
    3403             :         }
    3404             : 
    3405          16 :         return mq_add_handler(rn, rib_meta_queue_add);
    3406             : }
    3407             : 
    3408             : /*
    3409             :  * Enqueue incoming nhg info from OS for processing
    3410             :  */
    3411           0 : int rib_queue_nhg_ctx_add(struct nhg_ctx *ctx)
    3412             : {
    3413           0 :         assert(ctx);
    3414             : 
    3415           0 :         return mq_add_handler(ctx, rib_meta_queue_nhg_ctx_add);
    3416             : }
    3417             : 
    3418             : /*
    3419             :  * Enqueue incoming nhg from proto daemon for processing
    3420             :  */
    3421           0 : int rib_queue_nhe_add(struct nhg_hash_entry *nhe)
    3422             : {
    3423           0 :         if (nhe == NULL)
    3424             :                 return -1;
    3425             : 
    3426           0 :         return mq_add_handler(nhe, rib_meta_queue_nhg_add);
    3427             : }
    3428             : 
    3429             : /*
    3430             :  * Enqueue evpn route for processing
    3431             :  */
    3432           0 : int zebra_rib_queue_evpn_route_add(vrf_id_t vrf_id, const struct ethaddr *rmac,
    3433             :                                    const struct ipaddr *vtep_ip,
    3434             :                                    const struct prefix *host_prefix)
    3435             : {
    3436           0 :         struct wq_evpn_wrapper *w;
    3437             : 
    3438           0 :         w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_evpn_wrapper));
    3439             : 
    3440           0 :         w->type = WQ_EVPN_WRAPPER_TYPE_VRFROUTE;
    3441           0 :         w->add_p = true;
    3442           0 :         w->vrf_id = vrf_id;
    3443           0 :         w->macaddr = *rmac;
    3444           0 :         w->ip = *vtep_ip;
    3445           0 :         w->prefix = *host_prefix;
    3446             : 
    3447           0 :         if (IS_ZEBRA_DEBUG_RIB_DETAILED)
    3448           0 :                 zlog_debug("%s: (%u)%pIA, host prefix %pFX enqueued", __func__,
    3449             :                            vrf_id, vtep_ip, host_prefix);
    3450             : 
    3451           0 :         return mq_add_handler(w, rib_meta_queue_evpn_add);
    3452             : }
    3453             : 
    3454           0 : int zebra_rib_queue_evpn_route_del(vrf_id_t vrf_id,
    3455             :                                    const struct ipaddr *vtep_ip,
    3456             :                                    const struct prefix *host_prefix)
    3457             : {
    3458           0 :         struct wq_evpn_wrapper *w;
    3459             : 
    3460           0 :         w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_evpn_wrapper));
    3461             : 
    3462           0 :         w->type = WQ_EVPN_WRAPPER_TYPE_VRFROUTE;
    3463           0 :         w->add_p = false;
    3464           0 :         w->vrf_id = vrf_id;
    3465           0 :         w->ip = *vtep_ip;
    3466           0 :         w->prefix = *host_prefix;
    3467             : 
    3468           0 :         if (IS_ZEBRA_DEBUG_RIB_DETAILED)
    3469           0 :                 zlog_debug("%s: (%u)%pIA, host prefix %pFX enqueued", __func__,
    3470             :                            vrf_id, vtep_ip, host_prefix);
    3471             : 
    3472           0 :         return mq_add_handler(w, rib_meta_queue_evpn_add);
    3473             : }
    3474             : 
    3475             : /* Enqueue EVPN remote ES for processing */
    3476           0 : int zebra_rib_queue_evpn_rem_es_add(const esi_t *esi,
    3477             :                                     const struct in_addr *vtep_ip,
    3478             :                                     bool esr_rxed, uint8_t df_alg,
    3479             :                                     uint16_t df_pref)
    3480             : {
    3481           0 :         struct wq_evpn_wrapper *w;
    3482           0 :         char buf[ESI_STR_LEN];
    3483             : 
    3484           0 :         w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_evpn_wrapper));
    3485             : 
    3486           0 :         w->type = WQ_EVPN_WRAPPER_TYPE_REM_ES;
    3487           0 :         w->add_p = true;
    3488           0 :         w->esi = *esi;
    3489           0 :         w->ip.ipa_type = IPADDR_V4;
    3490           0 :         w->ip.ipaddr_v4 = *vtep_ip;
    3491           0 :         w->esr_rxed = esr_rxed;
    3492           0 :         w->df_alg = df_alg;
    3493           0 :         w->df_pref = df_pref;
    3494             : 
    3495           0 :         if (IS_ZEBRA_DEBUG_RIB_DETAILED)
    3496           0 :                 zlog_debug("%s: vtep %pI4, esi %s enqueued", __func__, vtep_ip,
    3497             :                            esi_to_str(esi, buf, sizeof(buf)));
    3498             : 
    3499           0 :         return mq_add_handler(w, rib_meta_queue_evpn_add);
    3500             : }
    3501             : 
    3502           0 : int zebra_rib_queue_evpn_rem_es_del(const esi_t *esi,
    3503             :                                     const struct in_addr *vtep_ip)
    3504             : {
    3505           0 :         struct wq_evpn_wrapper *w;
    3506           0 :         char buf[ESI_STR_LEN];
    3507             : 
    3508           0 :         w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_evpn_wrapper));
    3509             : 
    3510           0 :         w->type = WQ_EVPN_WRAPPER_TYPE_REM_ES;
    3511           0 :         w->add_p = false;
    3512           0 :         w->esi = *esi;
    3513           0 :         w->ip.ipa_type = IPADDR_V4;
    3514           0 :         w->ip.ipaddr_v4 = *vtep_ip;
    3515             : 
    3516           0 :         if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
    3517           0 :                 if (memcmp(esi, zero_esi, sizeof(esi_t)) != 0)
    3518           0 :                         esi_to_str(esi, buf, sizeof(buf));
    3519             :                 else
    3520           0 :                         strlcpy(buf, "-", sizeof(buf));
    3521             : 
    3522           0 :                 zlog_debug("%s: vtep %pI4, esi %s enqueued", __func__, vtep_ip,
    3523             :                            buf);
    3524             :         }
    3525             : 
    3526           0 :         return mq_add_handler(w, rib_meta_queue_evpn_add);
    3527             : }
    3528             : 
    3529             : /*
    3530             :  * Enqueue EVPN remote macip update for processing
    3531             :  */
    3532           0 : int zebra_rib_queue_evpn_rem_macip_add(vni_t vni, const struct ethaddr *macaddr,
    3533             :                                        const struct ipaddr *ipaddr,
    3534             :                                        uint8_t flags, uint32_t seq,
    3535             :                                        struct in_addr vtep_ip, const esi_t *esi)
    3536             : {
    3537           0 :         struct wq_evpn_wrapper *w;
    3538           0 :         char buf[ESI_STR_LEN];
    3539             : 
    3540           0 :         w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_evpn_wrapper));
    3541             : 
    3542           0 :         w->type = WQ_EVPN_WRAPPER_TYPE_REM_MACIP;
    3543           0 :         w->add_p = true;
    3544           0 :         w->vni = vni;
    3545           0 :         w->macaddr = *macaddr;
    3546           0 :         w->ip = *ipaddr;
    3547           0 :         w->flags = flags;
    3548           0 :         w->seq = seq;
    3549           0 :         w->vtep_ip = vtep_ip;
    3550           0 :         w->esi = *esi;
    3551             : 
    3552           0 :         if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
    3553           0 :                 if (memcmp(esi, zero_esi, sizeof(esi_t)) != 0)
    3554           0 :                         esi_to_str(esi, buf, sizeof(buf));
    3555             :                 else
    3556           0 :                         strlcpy(buf, "-", sizeof(buf));
    3557             : 
    3558           0 :                 zlog_debug("%s: mac %pEA, vtep %pI4, esi %s enqueued", __func__,
    3559             :                            macaddr, &vtep_ip, buf);
    3560             :         }
    3561             : 
    3562           0 :         return mq_add_handler(w, rib_meta_queue_evpn_add);
    3563             : }
    3564             : 
    3565           0 : int zebra_rib_queue_evpn_rem_macip_del(vni_t vni, const struct ethaddr *macaddr,
    3566             :                                        const struct ipaddr *ip,
    3567             :                                        struct in_addr vtep_ip)
    3568             : {
    3569           0 :         struct wq_evpn_wrapper *w;
    3570             : 
    3571           0 :         w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_evpn_wrapper));
    3572             : 
    3573           0 :         w->type = WQ_EVPN_WRAPPER_TYPE_REM_MACIP;
    3574           0 :         w->add_p = false;
    3575           0 :         w->vni = vni;
    3576           0 :         w->macaddr = *macaddr;
    3577           0 :         w->ip = *ip;
    3578           0 :         w->vtep_ip = vtep_ip;
    3579             : 
    3580           0 :         if (IS_ZEBRA_DEBUG_RIB_DETAILED)
    3581           0 :                 zlog_debug("%s: mac %pEA, vtep %pI4 enqueued", __func__,
    3582             :                            macaddr, &vtep_ip);
    3583             : 
    3584           0 :         return mq_add_handler(w, rib_meta_queue_evpn_add);
    3585             : }
    3586             : 
    3587             : /*
    3588             :  * Enqueue remote VTEP address for processing
    3589             :  */
    3590           0 : int zebra_rib_queue_evpn_rem_vtep_add(vrf_id_t vrf_id, vni_t vni,
    3591             :                                       struct in_addr vtep_ip, int flood_control)
    3592             : {
    3593           0 :         struct wq_evpn_wrapper *w;
    3594             : 
    3595           0 :         w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_evpn_wrapper));
    3596             : 
    3597           0 :         w->type = WQ_EVPN_WRAPPER_TYPE_REM_VTEP;
    3598           0 :         w->add_p = true;
    3599           0 :         w->vrf_id = vrf_id;
    3600           0 :         w->vni = vni;
    3601           0 :         w->vtep_ip = vtep_ip;
    3602           0 :         w->flags = flood_control;
    3603             : 
    3604           0 :         if (IS_ZEBRA_DEBUG_RIB_DETAILED)
    3605           0 :                 zlog_debug("%s: vrf %u, vtep %pI4 enqueued", __func__, vrf_id,
    3606             :                            &vtep_ip);
    3607             : 
    3608           0 :         return mq_add_handler(w, rib_meta_queue_evpn_add);
    3609             : }
    3610             : 
    3611           0 : int zebra_rib_queue_evpn_rem_vtep_del(vrf_id_t vrf_id, vni_t vni,
    3612             :                                       struct in_addr vtep_ip)
    3613             : {
    3614           0 :         struct wq_evpn_wrapper *w;
    3615             : 
    3616           0 :         w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_evpn_wrapper));
    3617             : 
    3618           0 :         w->type = WQ_EVPN_WRAPPER_TYPE_REM_VTEP;
    3619           0 :         w->add_p = false;
    3620           0 :         w->vrf_id = vrf_id;
    3621           0 :         w->vni = vni;
    3622           0 :         w->vtep_ip = vtep_ip;
    3623             : 
    3624           0 :         if (IS_ZEBRA_DEBUG_RIB_DETAILED)
    3625           0 :                 zlog_debug("%s: vrf %u, vtep %pI4 enqueued", __func__, vrf_id,
    3626             :                            &vtep_ip);
    3627             : 
    3628           0 :         return mq_add_handler(w, rib_meta_queue_evpn_add);
    3629             : }
    3630             : 
    3631             : /* Create new meta queue.
    3632             :    A destructor function doesn't seem to be necessary here.
    3633             :  */
    3634           1 : static struct meta_queue *meta_queue_new(void)
    3635             : {
    3636           1 :         struct meta_queue *new;
    3637           1 :         unsigned i;
    3638             : 
    3639           1 :         new = XCALLOC(MTYPE_WORK_QUEUE, sizeof(struct meta_queue));
    3640             : 
    3641          12 :         for (i = 0; i < MQ_SIZE; i++) {
    3642          10 :                 new->subq[i] = list_new();
    3643          10 :                 assert(new->subq[i]);
    3644             :         }
    3645             : 
    3646           1 :         return new;
    3647             : }
    3648             : 
    3649             : /* Clean up the EVPN meta-queue list */
    3650           3 : static void evpn_meta_queue_free(struct meta_queue *mq, struct list *l,
    3651             :                                  struct zebra_vrf *zvrf)
    3652             : {
    3653           3 :         struct listnode *node, *nnode;
    3654           3 :         struct wq_evpn_wrapper *w;
    3655             : 
    3656             :         /* Free the node wrapper object, and the struct it wraps */
    3657           6 :         for (ALL_LIST_ELEMENTS(l, node, nnode, w)) {
    3658           0 :                 if (zvrf) {
    3659           0 :                         vrf_id_t vrf_id = zvrf->vrf->vrf_id;
    3660             : 
    3661           0 :                         if (w->vrf_id != vrf_id)
    3662           0 :                                 continue;
    3663             :                 }
    3664             : 
    3665           0 :                 node->data = NULL;
    3666             : 
    3667           0 :                 XFREE(MTYPE_WQ_WRAPPER, w);
    3668             : 
    3669           0 :                 list_delete_node(l, node);
    3670           0 :                 mq->size--;
    3671             :         }
    3672           3 : }
    3673             : 
    3674             : /* Clean up the nhg meta-queue list */
    3675           3 : static void nhg_meta_queue_free(struct meta_queue *mq, struct list *l,
    3676             :                                 struct zebra_vrf *zvrf)
    3677             : {
    3678           3 :         struct wq_nhg_wrapper *w;
    3679           3 :         struct listnode *node, *nnode;
    3680             : 
    3681             :         /* Free the node wrapper object, and the struct it wraps */
    3682           6 :         for (ALL_LIST_ELEMENTS(l, node, nnode, w)) {
    3683           0 :                 if (zvrf) {
    3684           0 :                         vrf_id_t vrf_id = zvrf->vrf->vrf_id;
    3685             : 
    3686           0 :                         if (w->type == WQ_NHG_WRAPPER_TYPE_CTX &&
    3687           0 :                             w->u.ctx->vrf_id != vrf_id)
    3688           0 :                                 continue;
    3689           0 :                         else if (w->type == WQ_NHG_WRAPPER_TYPE_NHG &&
    3690           0 :                                  w->u.nhe->vrf_id != vrf_id)
    3691           0 :                                 continue;
    3692             :                 }
    3693           0 :                 if (w->type == WQ_NHG_WRAPPER_TYPE_CTX)
    3694           0 :                         nhg_ctx_free(&w->u.ctx);
    3695           0 :                 else if (w->type == WQ_NHG_WRAPPER_TYPE_NHG)
    3696           0 :                         zebra_nhg_free(w->u.nhe);
    3697             : 
    3698           0 :                 node->data = NULL;
    3699           0 :                 XFREE(MTYPE_WQ_WRAPPER, w);
    3700             : 
    3701           0 :                 list_delete_node(l, node);
    3702           0 :                 mq->size--;
    3703             :         }
    3704           3 : }
    3705             : 
    3706           3 : static void early_label_meta_queue_free(struct meta_queue *mq, struct list *l,
    3707             :                                         struct zebra_vrf *zvrf)
    3708             : {
    3709           3 :         struct wq_label_wrapper *w;
    3710           3 :         struct listnode *node, *nnode;
    3711             : 
    3712           6 :         for (ALL_LIST_ELEMENTS(l, node, nnode, w)) {
    3713           0 :                 if (zvrf && zvrf->vrf->vrf_id != w->vrf_id)
    3714           0 :                         continue;
    3715             : 
    3716           0 :                 switch (w->type) {
    3717             :                 case WQ_LABEL_FTN_UNINSTALL:
    3718             :                 case WQ_LABEL_LABELS_PROCESS:
    3719             :                         break;
    3720             :                 }
    3721             : 
    3722           0 :                 node->data = NULL;
    3723           0 :                 XFREE(MTYPE_WQ_WRAPPER, w);
    3724           0 :                 list_delete_node(l, node);
    3725           0 :                 mq->size--;
    3726             :         }
    3727           3 : }
    3728             : 
    3729          18 : static void rib_meta_queue_free(struct meta_queue *mq, struct list *l,
    3730             :                                 struct zebra_vrf *zvrf)
    3731             : {
    3732          18 :         struct route_node *rnode;
    3733          18 :         struct listnode *node, *nnode;
    3734             : 
    3735          36 :         for (ALL_LIST_ELEMENTS(l, node, nnode, rnode)) {
    3736           0 :                 rib_dest_t *dest = rib_dest_from_rnode(rnode);
    3737             : 
    3738           0 :                 if (dest && rib_dest_vrf(dest) != zvrf)
    3739           0 :                         continue;
    3740             : 
    3741           0 :                 route_unlock_node(rnode);
    3742           0 :                 node->data = NULL;
    3743           0 :                 list_delete_node(l, node);
    3744           0 :                 mq->size--;
    3745             :         }
    3746          18 : }
    3747             : 
    3748           3 : static void early_route_meta_queue_free(struct meta_queue *mq, struct list *l,
    3749             :                                         struct zebra_vrf *zvrf)
    3750             : {
    3751           3 :         struct zebra_early_route *ere;
    3752           3 :         struct listnode *node, *nnode;
    3753             : 
    3754           6 :         for (ALL_LIST_ELEMENTS(l, node, nnode, ere)) {
    3755           0 :                 if (zvrf && ere->re->vrf_id != zvrf->vrf->vrf_id)
    3756           0 :                         continue;
    3757             : 
    3758           0 :                 early_route_memory_free(ere);
    3759           0 :                 node->data = NULL;
    3760           0 :                 list_delete_node(l, node);
    3761           0 :                 mq->size--;
    3762             :         }
    3763           3 : }
    3764             : 
    3765           3 : void meta_queue_free(struct meta_queue *mq, struct zebra_vrf *zvrf)
    3766             : {
    3767           3 :         enum meta_queue_indexes i;
    3768             : 
    3769          33 :         for (i = 0; i < MQ_SIZE; i++) {
    3770             :                 /* Some subqueues may need cleanup - nhgs for example */
    3771          30 :                 switch (i) {
    3772           3 :                 case META_QUEUE_NHG:
    3773           3 :                         nhg_meta_queue_free(mq, mq->subq[i], zvrf);
    3774           3 :                         break;
    3775           3 :                 case META_QUEUE_EVPN:
    3776           3 :                         evpn_meta_queue_free(mq, mq->subq[i], zvrf);
    3777           3 :                         break;
    3778           3 :                 case META_QUEUE_EARLY_ROUTE:
    3779           3 :                         early_route_meta_queue_free(mq, mq->subq[i], zvrf);
    3780           3 :                         break;
    3781           3 :                 case META_QUEUE_EARLY_LABEL:
    3782           3 :                         early_label_meta_queue_free(mq, mq->subq[i], zvrf);
    3783           3 :                         break;
    3784          18 :                 case META_QUEUE_CONNECTED:
    3785             :                 case META_QUEUE_KERNEL:
    3786             :                 case META_QUEUE_STATIC:
    3787             :                 case META_QUEUE_NOTBGP:
    3788             :                 case META_QUEUE_BGP:
    3789             :                 case META_QUEUE_OTHER:
    3790          18 :                         rib_meta_queue_free(mq, mq->subq[i], zvrf);
    3791          18 :                         break;
    3792             :                 }
    3793          30 :                 if (!zvrf)
    3794          10 :                         list_delete(&mq->subq[i]);
    3795             :         }
    3796             : 
    3797           3 :         if (!zvrf)
    3798           1 :                 XFREE(MTYPE_WORK_QUEUE, mq);
    3799           3 : }
    3800             : 
    3801             : /* initialise zebra rib work queue */
    3802           1 : static void rib_queue_init(void)
    3803             : {
    3804           1 :         if (!(zrouter.ribq = work_queue_new(zrouter.master,
    3805             :                                             "route_node processing"))) {
    3806           0 :                 flog_err(EC_ZEBRA_WQ_NONEXISTENT,
    3807             :                          "%s: could not initialise work queue!", __func__);
    3808           0 :                 return;
    3809             :         }
    3810             : 
    3811             :         /* fill in the work queue spec */
    3812           1 :         zrouter.ribq->spec.workfunc = &meta_queue_process;
    3813           1 :         zrouter.ribq->spec.completion_func = NULL;
    3814             :         /* XXX: TODO: These should be runtime configurable via vty */
    3815           1 :         zrouter.ribq->spec.max_retries = 3;
    3816           1 :         zrouter.ribq->spec.hold = ZEBRA_RIB_PROCESS_HOLD_TIME;
    3817           1 :         zrouter.ribq->spec.retry = ZEBRA_RIB_PROCESS_RETRY_TIME;
    3818             : 
    3819           1 :         if (!(zrouter.mq = meta_queue_new())) {
    3820           0 :                 flog_err(EC_ZEBRA_WQ_NONEXISTENT,
    3821             :                          "%s: could not initialise meta queue!", __func__);
    3822           0 :                 return;
    3823             :         }
    3824             :         return;
    3825             : }
    3826             : 
    3827          18 : rib_dest_t *zebra_rib_create_dest(struct route_node *rn)
    3828             : {
    3829          18 :         rib_dest_t *dest;
    3830             : 
    3831          18 :         dest = XCALLOC(MTYPE_RIB_DEST, sizeof(rib_dest_t));
    3832          18 :         rnh_list_init(&dest->nht);
    3833          18 :         re_list_init(&dest->routes);
    3834          18 :         route_lock_node(rn); /* rn route table reference */
    3835          18 :         rn->info = dest;
    3836          18 :         dest->rnode = rn;
    3837             : 
    3838          18 :         return dest;
    3839             : }
    3840             : 
    3841             : /* RIB updates are processed via a queue of pointers to route_nodes.
    3842             :  *
    3843             :  * The queue length is bounded by the maximal size of the routing table,
    3844             :  * as a route_node will not be requeued, if already queued.
    3845             :  *
    3846             :  * REs are submitted via rib_addnode or rib_delnode which set minimal
    3847             :  * state, or static_install_route (when an existing RE is updated)
    3848             :  * and then submit route_node to queue for best-path selection later.
    3849             :  * Order of add/delete state changes are preserved for any given RE.
    3850             :  *
    3851             :  * Deleted REs are reaped during best-path selection.
    3852             :  *
    3853             :  * rib_addnode
    3854             :  * |-> rib_link or unset ROUTE_ENTRY_REMOVE      |->Update kernel with
    3855             :  *       |-------->|                             |  best RE, if required
    3856             :  *                 |                             |
    3857             :  * static_install->|->rib_addqueue...... -> rib_process
    3858             :  *                 |                             |
    3859             :  *       |-------->|                             |-> rib_unlink
    3860             :  *       |-> set ROUTE_ENTRY_REMOVE              |
    3861             :  * rib_delnode                                  (RE freed)
    3862             :  *
    3863             :  * The 'info' pointer of a route_node points to a rib_dest_t
    3864             :  * ('dest'). Queueing state for a route_node is kept on the dest. The
    3865             :  * dest is created on-demand by rib_link() and is kept around at least
    3866             :  * as long as there are ribs hanging off it (@see rib_gc_dest()).
    3867             :  *
    3868             :  * Refcounting (aka "locking" throughout the Zebra and FRR code):
    3869             :  *
    3870             :  * - route_nodes: refcounted by:
    3871             :  *   - dest attached to route_node:
    3872             :  *     - managed by: rib_link/rib_gc_dest
    3873             :  *   - route_node processing queue
    3874             :  *     - managed by: rib_addqueue, rib_process.
    3875             :  *
    3876             :  */
    3877             : 
    3878             : /* Add RE to head of the route node. */
    3879          16 : static void rib_link(struct route_node *rn, struct route_entry *re, int process)
    3880             : {
    3881          16 :         rib_dest_t *dest;
    3882          16 :         afi_t afi;
    3883          16 :         const char *rmap_name;
    3884             : 
    3885          16 :         assert(re && rn);
    3886             : 
    3887          16 :         dest = rib_dest_from_rnode(rn);
    3888          16 :         if (!dest) {
    3889          14 :                 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
    3890          14 :                         rnode_debug(rn, re->vrf_id, "rn %p adding dest", rn);
    3891             : 
    3892          14 :                 dest = zebra_rib_create_dest(rn);
    3893             :         }
    3894             : 
    3895          16 :         re_list_add_head(&dest->routes, re);
    3896             : 
    3897          32 :         afi = (rn->p.family == AF_INET)
    3898             :                       ? AFI_IP
    3899          16 :                       : (rn->p.family == AF_INET6) ? AFI_IP6 : AFI_MAX;
    3900          16 :         if (is_zebra_import_table_enabled(afi, re->vrf_id, re->table)) {
    3901           0 :                 struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(re->vrf_id);
    3902             : 
    3903           0 :                 rmap_name = zebra_get_import_table_route_map(afi, re->table);
    3904           0 :                 zebra_add_import_table_entry(zvrf, rn, re, rmap_name);
    3905          16 :         } else if (process)
    3906          16 :                 rib_queue_add(rn);
    3907          16 : }
    3908             : 
    3909          16 : static void rib_addnode(struct route_node *rn,
    3910             :                         struct route_entry *re, int process)
    3911             : {
    3912             :         /* RE node has been un-removed before route-node is processed.
    3913             :          * route_node must hence already be on the queue for processing..
    3914             :          */
    3915          16 :         if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) {
    3916           0 :                 if (IS_ZEBRA_DEBUG_RIB)
    3917           0 :                         rnode_debug(rn, re->vrf_id, "rn %p, un-removed re %p",
    3918             :                                     (void *)rn, (void *)re);
    3919             : 
    3920           0 :                 UNSET_FLAG(re->status, ROUTE_ENTRY_REMOVED);
    3921           0 :                 return;
    3922             :         }
    3923          16 :         rib_link(rn, re, process);
    3924             : }
    3925             : 
    3926             : /*
    3927             :  * rib_unlink
    3928             :  *
    3929             :  * Detach a rib structure from a route_node.
    3930             :  *
    3931             :  * Note that a call to rib_unlink() should be followed by a call to
    3932             :  * rib_gc_dest() at some point. This allows a rib_dest_t that is no
    3933             :  * longer required to be deleted.
    3934             :  */
    3935          16 : void rib_unlink(struct route_node *rn, struct route_entry *re)
    3936             : {
    3937          16 :         rib_dest_t *dest;
    3938             : 
    3939          16 :         assert(rn && re);
    3940             : 
    3941          16 :         if (IS_ZEBRA_DEBUG_RIB)
    3942          16 :                 rnode_debug(rn, re->vrf_id, "rn %p, re %p", (void *)rn,
    3943             :                             (void *)re);
    3944             : 
    3945          16 :         dest = rib_dest_from_rnode(rn);
    3946             : 
    3947          16 :         re_list_del(&dest->routes, re);
    3948             : 
    3949          16 :         if (dest->selected_fib == re)
    3950           0 :                 dest->selected_fib = NULL;
    3951             : 
    3952          16 :         rib_re_nhg_free(re);
    3953             : 
    3954          16 :         zapi_re_opaque_free(re->opaque);
    3955             : 
    3956          16 :         XFREE(MTYPE_RE, re);
    3957          16 : }
    3958             : 
    3959           0 : void rib_delnode(struct route_node *rn, struct route_entry *re)
    3960             : {
    3961           0 :         afi_t afi;
    3962             : 
    3963           0 :         if (IS_ZEBRA_DEBUG_RIB)
    3964           0 :                 rnode_debug(rn, re->vrf_id, "rn %p, re %p, removing",
    3965             :                             (void *)rn, (void *)re);
    3966           0 :         SET_FLAG(re->status, ROUTE_ENTRY_REMOVED);
    3967             : 
    3968           0 :         afi = (rn->p.family == AF_INET)
    3969             :                       ? AFI_IP
    3970           0 :                       : (rn->p.family == AF_INET6) ? AFI_IP6 : AFI_MAX;
    3971           0 :         if (is_zebra_import_table_enabled(afi, re->vrf_id, re->table)) {
    3972           0 :                 struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(re->vrf_id);
    3973             : 
    3974           0 :                 zebra_del_import_table_entry(zvrf, rn, re);
    3975             :                 /* Just clean up if non main table */
    3976           0 :                 if (IS_ZEBRA_DEBUG_RIB)
    3977           0 :                         zlog_debug("%s(%u):%pRN: Freeing route rn %p, re %p (%s)",
    3978             :                                    vrf_id_to_name(re->vrf_id), re->vrf_id, rn,
    3979             :                                    rn, re, zebra_route_string(re->type));
    3980             : 
    3981           0 :                 rib_unlink(rn, re);
    3982             :         } else {
    3983           0 :                 rib_queue_add(rn);
    3984             :         }
    3985           0 : }
    3986             : 
    3987             : /*
    3988             :  * Helper that debugs a single nexthop within a route-entry
    3989             :  */
    3990          16 : static void _route_entry_dump_nh(const struct route_entry *re,
    3991             :                                  const char *straddr,
    3992             :                                  const struct nexthop *nexthop)
    3993             : {
    3994          16 :         char nhname[PREFIX_STRLEN];
    3995          16 :         char backup_str[50];
    3996          16 :         char wgt_str[50];
    3997          16 :         char temp_str[10];
    3998          16 :         char label_str[MPLS_LABEL_STRLEN];
    3999          16 :         int i;
    4000          16 :         struct interface *ifp;
    4001          16 :         struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id);
    4002             : 
    4003          16 :         switch (nexthop->type) {
    4004           0 :         case NEXTHOP_TYPE_BLACKHOLE:
    4005           0 :                 snprintf(nhname, sizeof(nhname), "Blackhole");
    4006           0 :                 break;
    4007          16 :         case NEXTHOP_TYPE_IFINDEX:
    4008          16 :                 ifp = if_lookup_by_index(nexthop->ifindex, nexthop->vrf_id);
    4009          16 :                 snprintf(nhname, sizeof(nhname), "%s",
    4010             :                          ifp ? ifp->name : "Unknown");
    4011          16 :                 break;
    4012           0 :         case NEXTHOP_TYPE_IPV4:
    4013             :                 /* fallthrough */
    4014             :         case NEXTHOP_TYPE_IPV4_IFINDEX:
    4015           0 :                 inet_ntop(AF_INET, &nexthop->gate, nhname, INET6_ADDRSTRLEN);
    4016           0 :                 break;
    4017           0 :         case NEXTHOP_TYPE_IPV6:
    4018             :         case NEXTHOP_TYPE_IPV6_IFINDEX:
    4019           0 :                 inet_ntop(AF_INET6, &nexthop->gate, nhname, INET6_ADDRSTRLEN);
    4020           0 :                 break;
    4021             :         }
    4022             : 
    4023             :         /* Label stack */
    4024          16 :         label_str[0] = '\0';
    4025          16 :         if (nexthop->nh_label && nexthop->nh_label->num_labels > 0) {
    4026           0 :                 mpls_label2str(nexthop->nh_label->num_labels,
    4027           0 :                                nexthop->nh_label->label, label_str,
    4028             :                                sizeof(label_str), 0 /*pretty*/);
    4029           0 :                 strlcat(label_str, ", ", sizeof(label_str));
    4030             :         }
    4031             : 
    4032          16 :         backup_str[0] = '\0';
    4033          16 :         if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
    4034           0 :                 snprintf(backup_str, sizeof(backup_str), "backup ");
    4035           0 :                 for (i = 0; i < nexthop->backup_num; i++) {
    4036           0 :                         snprintf(temp_str, sizeof(temp_str), "%d, ",
    4037           0 :                                  nexthop->backup_idx[i]);
    4038           0 :                         strlcat(backup_str, temp_str, sizeof(backup_str));
    4039             :                 }
    4040             :         }
    4041             : 
    4042          16 :         wgt_str[0] = '\0';
    4043          16 :         if (nexthop->weight)
    4044           0 :                 snprintf(wgt_str, sizeof(wgt_str), "wgt %d,", nexthop->weight);
    4045             : 
    4046         176 :         zlog_debug("%s: %s %s[%u] %svrf %s(%u) %s%s with flags %s%s%s%s%s%s%s%s%s",
    4047             :                    straddr, (nexthop->rparent ? "  NH" : "NH"), nhname,
    4048             :                    nexthop->ifindex, label_str, vrf ? vrf->name : "Unknown",
    4049             :                    nexthop->vrf_id,
    4050             :                    wgt_str, backup_str,
    4051             :                    (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)
    4052             :                     ? "ACTIVE "
    4053             :                     : ""),
    4054             :                    (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)
    4055             :                     ? "FIB "
    4056             :                     : ""),
    4057             :                    (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)
    4058             :                     ? "RECURSIVE "
    4059             :                     : ""),
    4060             :                    (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)
    4061             :                     ? "ONLINK "
    4062             :                     : ""),
    4063             :                    (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE)
    4064             :                     ? "DUPLICATE "
    4065             :                     : ""),
    4066             :                    (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RNH_FILTERED)
    4067             :                     ? "FILTERED " : ""),
    4068             :                    (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)
    4069             :                     ? "BACKUP " : ""),
    4070             :                    (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_SRTE)
    4071             :                     ? "SRTE " : ""),
    4072             :                    (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_EVPN)
    4073             :                     ? "EVPN " : ""));
    4074             : 
    4075          16 : }
    4076             : 
    4077             : /* This function dumps the contents of a given RE entry into
    4078             :  * standard debug log. Calling function name and IP prefix in
    4079             :  * question are passed as 1st and 2nd arguments.
    4080             :  */
    4081          16 : void _route_entry_dump(const char *func, union prefixconstptr pp,
    4082             :                        union prefixconstptr src_pp,
    4083             :                        const struct route_entry *re)
    4084             : {
    4085          16 :         const struct prefix *src_p = src_pp.p;
    4086          16 :         bool is_srcdst = src_p && src_p->prefixlen;
    4087          16 :         char straddr[PREFIX_STRLEN];
    4088          16 :         char srcaddr[PREFIX_STRLEN];
    4089          16 :         char flags_buf[128];
    4090          16 :         char status_buf[128];
    4091          16 :         struct nexthop *nexthop;
    4092          16 :         struct vrf *vrf = vrf_lookup_by_id(re->vrf_id);
    4093          16 :         struct nexthop_group *nhg;
    4094             : 
    4095          16 :         prefix2str(pp, straddr, sizeof(straddr));
    4096             : 
    4097          16 :         zlog_debug("%s: dumping RE entry %p for %s%s%s vrf %s(%u)", func,
    4098             :                    (const void *)re, straddr,
    4099             :                    is_srcdst ? " from " : "",
    4100             :                    is_srcdst ? prefix2str(src_pp, srcaddr, sizeof(srcaddr))
    4101             :                              : "",
    4102             :                    VRF_LOGNAME(vrf), re->vrf_id);
    4103          16 :         zlog_debug("%s: uptime == %lu, type == %u, instance == %d, table == %d",
    4104             :                    straddr, (unsigned long)re->uptime, re->type, re->instance,
    4105             :                    re->table);
    4106          16 :         zlog_debug(
    4107             :                 "%s: metric == %u, mtu == %u, distance == %u, flags == %sstatus == %s",
    4108             :                 straddr, re->metric, re->mtu, re->distance,
    4109             :                 zclient_dump_route_flags(re->flags, flags_buf,
    4110             :                                          sizeof(flags_buf)),
    4111             :                 _dump_re_status(re, status_buf, sizeof(status_buf)));
    4112          16 :         zlog_debug("%s: nexthop_num == %u, nexthop_active_num == %u", straddr,
    4113             :                    nexthop_group_nexthop_num(&(re->nhe->nhg)),
    4114             :                    nexthop_group_active_nexthop_num(&(re->nhe->nhg)));
    4115             : 
    4116             :         /* Dump nexthops */
    4117          32 :         for (ALL_NEXTHOPS(re->nhe->nhg, nexthop))
    4118          16 :                 _route_entry_dump_nh(re, straddr, nexthop);
    4119             : 
    4120          16 :         if (zebra_nhg_get_backup_nhg(re->nhe)) {
    4121           0 :                 zlog_debug("%s: backup nexthops:", straddr);
    4122             : 
    4123           0 :                 nhg = zebra_nhg_get_backup_nhg(re->nhe);
    4124           0 :                 for (ALL_NEXTHOPS_PTR(nhg, nexthop))
    4125           0 :                         _route_entry_dump_nh(re, straddr, nexthop);
    4126             :         }
    4127             : 
    4128          16 :         zlog_debug("%s: dump complete", straddr);
    4129          16 : }
    4130             : 
    4131          16 : static int rib_meta_queue_early_route_add(struct meta_queue *mq, void *data)
    4132             : {
    4133          16 :         struct zebra_early_route *ere = data;
    4134             : 
    4135          16 :         listnode_add(mq->subq[META_QUEUE_EARLY_ROUTE], data);
    4136          16 :         mq->size++;
    4137             : 
    4138          16 :         if (IS_ZEBRA_DEBUG_RIB_DETAILED)
    4139           8 :                 zlog_debug(
    4140             :                         "Route %pFX(%u) queued for processing into sub-queue %s",
    4141             :                         &ere->p, ere->re->vrf_id,
    4142             :                         subqueue2str(META_QUEUE_EARLY_ROUTE));
    4143             : 
    4144          16 :         return 0;
    4145             : }
    4146             : 
    4147          16 : struct route_entry *zebra_rib_route_entry_new(vrf_id_t vrf_id, int type,
    4148             :                                               uint8_t instance, uint32_t flags,
    4149             :                                               uint32_t nhe_id,
    4150             :                                               uint32_t table_id,
    4151             :                                               uint32_t metric, uint32_t mtu,
    4152             :                                               uint8_t distance, route_tag_t tag)
    4153             : {
    4154          16 :         struct route_entry *re;
    4155             : 
    4156          16 :         re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
    4157          16 :         re->type = type;
    4158          16 :         re->instance = instance;
    4159          16 :         re->distance = distance;
    4160          16 :         re->flags = flags;
    4161          16 :         re->metric = metric;
    4162          16 :         re->mtu = mtu;
    4163          16 :         re->table = table_id;
    4164          16 :         re->vrf_id = vrf_id;
    4165          16 :         re->uptime = monotime(NULL);
    4166          16 :         re->tag = tag;
    4167          16 :         re->nhe_id = nhe_id;
    4168             : 
    4169          16 :         return re;
    4170             : }
    4171             : /*
    4172             :  * Internal route-add implementation; there are a couple of different public
    4173             :  * signatures. Callers in this path are responsible for the memory they
    4174             :  * allocate: if they allocate a nexthop_group or backup nexthop info, they
    4175             :  * must free those objects. If this returns < 0, an error has occurred and the
    4176             :  * route_entry 're' has not been captured; the caller should free that also.
    4177             :  *
    4178             :  * -1 -> error
    4179             :  *  0 -> Add
    4180             :  *  1 -> update
    4181             :  */
    4182          16 : int rib_add_multipath_nhe(afi_t afi, safi_t safi, struct prefix *p,
    4183             :                           struct prefix_ipv6 *src_p, struct route_entry *re,
    4184             :                           struct nhg_hash_entry *re_nhe, bool startup)
    4185             : {
    4186          16 :         struct zebra_early_route *ere;
    4187             : 
    4188          16 :         if (!re)
    4189             :                 return -1;
    4190             : 
    4191          16 :         assert(!src_p || !src_p->prefixlen || afi == AFI_IP6);
    4192             : 
    4193          16 :         ere = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(*ere));
    4194          16 :         ere->afi = afi;
    4195          16 :         ere->safi = safi;
    4196          16 :         ere->p = *p;
    4197          16 :         if (src_p)
    4198           0 :                 ere->src_p = *src_p;
    4199          16 :         ere->src_p_provided = !!src_p;
    4200          16 :         ere->re = re;
    4201          16 :         ere->re_nhe = re_nhe;
    4202          16 :         ere->startup = startup;
    4203             : 
    4204          16 :         return mq_add_handler(ere, rib_meta_queue_early_route_add);
    4205             : }
    4206             : 
    4207             : /*
    4208             :  * Add a single route.
    4209             :  */
    4210          16 : int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
    4211             :                       struct prefix_ipv6 *src_p, struct route_entry *re,
    4212             :                       struct nexthop_group *ng, bool startup)
    4213             : {
    4214          16 :         int ret;
    4215          16 :         struct nhg_hash_entry nhe, *n;
    4216             : 
    4217          16 :         if (!re)
    4218             :                 return -1;
    4219             : 
    4220             :         /* We either need nexthop(s) or an existing nexthop id */
    4221          16 :         if (ng == NULL && re->nhe_id == 0)
    4222             :                 return -1;
    4223             : 
    4224             :         /*
    4225             :          * Use a temporary nhe to convey info to the common/main api.
    4226             :          */
    4227          16 :         zebra_nhe_init(&nhe, afi, (ng ? ng->nexthop : NULL));
    4228          16 :         if (ng)
    4229          16 :                 nhe.nhg.nexthop = ng->nexthop;
    4230           0 :         else if (re->nhe_id > 0)
    4231           0 :                 nhe.id = re->nhe_id;
    4232             : 
    4233          16 :         n = zebra_nhe_copy(&nhe, 0);
    4234          16 :         ret = rib_add_multipath_nhe(afi, safi, p, src_p, re, n, startup);
    4235             : 
    4236             :         /* In error cases, free the route also */
    4237          16 :         if (ret < 0)
    4238           0 :                 XFREE(MTYPE_RE, re);
    4239             : 
    4240             :         return ret;
    4241             : }
    4242             : 
    4243           0 : void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
    4244             :                 unsigned short instance, uint32_t flags, struct prefix *p,
    4245             :                 struct prefix_ipv6 *src_p, const struct nexthop *nh,
    4246             :                 uint32_t nhe_id, uint32_t table_id, uint32_t metric,
    4247             :                 uint8_t distance, bool fromkernel)
    4248             : {
    4249           0 :         struct zebra_early_route *ere;
    4250           0 :         struct route_entry *re = NULL;
    4251           0 :         struct nhg_hash_entry *nhe = NULL;
    4252             : 
    4253           0 :         re = zebra_rib_route_entry_new(vrf_id, type, instance, flags, nhe_id,
    4254             :                                        table_id, metric, 0, distance, 0);
    4255             : 
    4256           0 :         if (nh) {
    4257           0 :                 nhe = zebra_nhg_alloc();
    4258           0 :                 nhe->nhg.nexthop = nexthop_dup(nh, NULL);
    4259             :         }
    4260             : 
    4261           0 :         ere = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(*ere));
    4262           0 :         ere->afi = afi;
    4263           0 :         ere->safi = safi;
    4264           0 :         ere->p = *p;
    4265           0 :         if (src_p)
    4266           0 :                 ere->src_p = *src_p;
    4267           0 :         ere->src_p_provided = !!src_p;
    4268           0 :         ere->re = re;
    4269           0 :         ere->re_nhe = nhe;
    4270           0 :         ere->startup = false;
    4271           0 :         ere->deletion = true;
    4272           0 :         ere->fromkernel = fromkernel;
    4273             : 
    4274           0 :         mq_add_handler(ere, rib_meta_queue_early_route_add);
    4275           0 : }
    4276             : 
    4277             : 
    4278          16 : int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
    4279             :             unsigned short instance, uint32_t flags, struct prefix *p,
    4280             :             struct prefix_ipv6 *src_p, const struct nexthop *nh,
    4281             :             uint32_t nhe_id, uint32_t table_id, uint32_t metric, uint32_t mtu,
    4282             :             uint8_t distance, route_tag_t tag, bool startup)
    4283             : {
    4284          16 :         struct route_entry *re = NULL;
    4285          16 :         struct nexthop nexthop = {};
    4286          16 :         struct nexthop_group ng = {};
    4287             : 
    4288             :         /* Allocate new route_entry structure. */
    4289          16 :         re = zebra_rib_route_entry_new(vrf_id, type, instance, flags, nhe_id,
    4290             :                                        table_id, metric, mtu, distance, tag);
    4291             : 
    4292             :         /* If the owner of the route supplies a shared nexthop-group id,
    4293             :          * we'll use that. Otherwise, pass the nexthop along directly.
    4294             :          */
    4295          16 :         if (!nhe_id) {
    4296             :                 /* Add nexthop. */
    4297          16 :                 nexthop = *nh;
    4298          16 :                 nexthop_group_add_sorted(&ng, &nexthop);
    4299             :         }
    4300             : 
    4301          16 :         return rib_add_multipath(afi, safi, p, src_p, re, &ng, startup);
    4302             : }
    4303             : 
    4304           6 : static const char *rib_update_event2str(enum rib_update_event event)
    4305             : {
    4306           6 :         const char *ret = "UNKNOWN";
    4307             : 
    4308           6 :         switch (event) {
    4309           6 :         case RIB_UPDATE_KERNEL:
    4310           6 :                 ret = "RIB_UPDATE_KERNEL";
    4311           6 :                 break;
    4312           0 :         case RIB_UPDATE_RMAP_CHANGE:
    4313           0 :                 ret = "RIB_UPDATE_RMAP_CHANGE";
    4314           0 :                 break;
    4315           0 :         case RIB_UPDATE_OTHER:
    4316           0 :                 ret = "RIB_UPDATE_OTHER";
    4317           0 :                 break;
    4318             :         case RIB_UPDATE_MAX:
    4319             :                 break;
    4320             :         }
    4321             : 
    4322           6 :         return ret;
    4323             : }
    4324             : 
    4325             : 
    4326             : /* Schedule route nodes to be processed if they match the type */
    4327          28 : static void rib_update_route_node(struct route_node *rn, int type)
    4328             : {
    4329          28 :         struct route_entry *re, *next;
    4330          28 :         bool re_changed = false;
    4331             : 
    4332          72 :         RNODE_FOREACH_RE_SAFE (rn, re, next) {
    4333          16 :                 if (type == ZEBRA_ROUTE_ALL || type == re->type) {
    4334           0 :                         SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
    4335           0 :                         re_changed = true;
    4336             :                 }
    4337             :         }
    4338             : 
    4339          28 :         if (re_changed)
    4340           0 :                 rib_queue_add(rn);
    4341          28 : }
    4342             : 
    4343             : /* Schedule routes of a particular table (address-family) based on event. */
    4344           4 : void rib_update_table(struct route_table *table, enum rib_update_event event,
    4345             :                       int rtype)
    4346             : {
    4347           4 :         struct route_node *rn;
    4348             : 
    4349           4 :         if (IS_ZEBRA_DEBUG_EVENT) {
    4350           4 :                 struct zebra_vrf *zvrf;
    4351           4 :                 struct vrf *vrf;
    4352             : 
    4353          12 :                 zvrf = table->info
    4354             :                                ? ((struct rib_table_info *)table->info)->zvrf
    4355           4 :                                : NULL;
    4356           4 :                 vrf = zvrf ? zvrf->vrf : NULL;
    4357             : 
    4358           8 :                 zlog_debug("%s: %s VRF %s Table %u event %s Route type: %s", __func__,
    4359             :                            table->info ? afi2str(
    4360             :                                    ((struct rib_table_info *)table->info)->afi)
    4361             :                                        : "Unknown",
    4362             :                            VRF_LOGNAME(vrf), zvrf ? zvrf->table_id : 0,
    4363             :                            rib_update_event2str(event), zebra_route_string(rtype));
    4364             :         }
    4365             : 
    4366             :         /* Walk all routes and queue for processing, if appropriate for
    4367             :          * the trigger event.
    4368             :          */
    4369          32 :         for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
    4370             :                 /*
    4371             :                  * If we are looking at a route node and the node
    4372             :                  * has already been queued  we don't
    4373             :                  * need to queue it up again
    4374             :                  */
    4375          28 :                 if (rn->info
    4376          18 :                     && CHECK_FLAG(rib_dest_from_rnode(rn)->flags,
    4377             :                                   RIB_ROUTE_ANY_QUEUED))
    4378           0 :                         continue;
    4379             : 
    4380          28 :                 switch (event) {
    4381          28 :                 case RIB_UPDATE_KERNEL:
    4382          28 :                         rib_update_route_node(rn, ZEBRA_ROUTE_KERNEL);
    4383          28 :                         break;
    4384           0 :                 case RIB_UPDATE_RMAP_CHANGE:
    4385             :                 case RIB_UPDATE_OTHER:
    4386           0 :                         rib_update_route_node(rn, rtype);
    4387           0 :                         break;
    4388             :                 case RIB_UPDATE_MAX:
    4389             :                         break;
    4390             :                 }
    4391             :         }
    4392           4 : }
    4393             : 
    4394           1 : static void rib_update_handle_vrf_all(enum rib_update_event event, int rtype)
    4395             : {
    4396           1 :         struct zebra_router_table *zrt;
    4397             : 
    4398           1 :         if (IS_ZEBRA_DEBUG_EVENT)
    4399           2 :                 zlog_debug("%s: Handling VRF (ALL) event %s", __func__,
    4400             :                            rib_update_event2str(event));
    4401             : 
    4402             :         /* Just iterate over all the route tables, rather than vrf lookups */
    4403           6 :         RB_FOREACH (zrt, zebra_router_table_head, &zrouter.tables)
    4404           4 :                 rib_update_table(zrt->table, event, rtype);
    4405           1 : }
    4406             : 
    4407             : struct rib_update_ctx {
    4408             :         enum rib_update_event event;
    4409             :         vrf_id_t vrf_id;
    4410             : };
    4411             : 
    4412           1 : static struct rib_update_ctx *rib_update_ctx_init(vrf_id_t vrf_id,
    4413             :                                                   enum rib_update_event event)
    4414             : {
    4415           1 :         struct rib_update_ctx *ctx;
    4416             : 
    4417           2 :         ctx = XCALLOC(MTYPE_RIB_UPDATE_CTX, sizeof(struct rib_update_ctx));
    4418             : 
    4419           1 :         ctx->event = event;
    4420           1 :         ctx->vrf_id = vrf_id;
    4421             : 
    4422           1 :         return ctx;
    4423             : }
    4424             : 
    4425           1 : static void rib_update_ctx_fini(struct rib_update_ctx **ctx)
    4426             : {
    4427           2 :         XFREE(MTYPE_RIB_UPDATE_CTX, *ctx);
    4428             : }
    4429             : 
    4430           1 : static void rib_update_handler(struct thread *thread)
    4431             : {
    4432           1 :         struct rib_update_ctx *ctx;
    4433             : 
    4434           1 :         ctx = THREAD_ARG(thread);
    4435             : 
    4436           1 :         rib_update_handle_vrf_all(ctx->event, ZEBRA_ROUTE_ALL);
    4437             : 
    4438           1 :         rib_update_ctx_fini(&ctx);
    4439           1 : }
    4440             : 
    4441             : /*
    4442             :  * Thread list to ensure we don't schedule a ton of events
    4443             :  * if interfaces are flapping for instance.
    4444             :  */
    4445             : static struct thread *t_rib_update_threads[RIB_UPDATE_MAX];
    4446             : 
    4447             : /* Schedule a RIB update event for all vrfs */
    4448           1 : void rib_update(enum rib_update_event event)
    4449             : {
    4450           1 :         struct rib_update_ctx *ctx;
    4451             : 
    4452           1 :         if (thread_is_scheduled(t_rib_update_threads[event]))
    4453             :                 return;
    4454             : 
    4455           1 :         ctx = rib_update_ctx_init(0, event);
    4456             : 
    4457           1 :         thread_add_event(zrouter.master, rib_update_handler, ctx, 0,
    4458             :                          &t_rib_update_threads[event]);
    4459             : 
    4460           1 :         if (IS_ZEBRA_DEBUG_EVENT)
    4461           2 :                 zlog_debug("%s: Scheduled VRF (ALL), event %s", __func__,
    4462             :                            rib_update_event2str(event));
    4463             : }
    4464             : 
    4465             : /* Delete self installed routes after zebra is relaunched.  */
    4466           6 : void rib_sweep_table(struct route_table *table)
    4467             : {
    4468           6 :         struct route_node *rn;
    4469           6 :         struct route_entry *re;
    4470           6 :         struct route_entry *next;
    4471           6 :         struct nexthop *nexthop;
    4472             : 
    4473           6 :         if (!table)
    4474             :                 return;
    4475             : 
    4476           6 :         if (IS_ZEBRA_DEBUG_RIB)
    4477           6 :                 zlog_debug("%s: starting", __func__);
    4478             : 
    4479          12 :         for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
    4480          12 :                 RNODE_FOREACH_RE_SAFE (rn, re, next) {
    4481             : 
    4482           0 :                         if (IS_ZEBRA_DEBUG_RIB)
    4483           0 :                                 route_entry_dump(&rn->p, NULL, re);
    4484             : 
    4485           0 :                         if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
    4486           0 :                                 continue;
    4487             : 
    4488           0 :                         if (!CHECK_FLAG(re->flags, ZEBRA_FLAG_SELFROUTE))
    4489           0 :                                 continue;
    4490             : 
    4491             :                         /*
    4492             :                          * If routes are older than startup_time then
    4493             :                          * we know we read them in from the kernel.
    4494             :                          * As such we can safely remove them.
    4495             :                          */
    4496           0 :                         if (zrouter.startup_time < re->uptime)
    4497           0 :                                 continue;
    4498             : 
    4499             :                         /*
    4500             :                          * So we are starting up and have received
    4501             :                          * routes from the kernel that we have installed
    4502             :                          * from a previous run of zebra but not cleaned
    4503             :                          * up ( say a kill -9 )
    4504             :                          * But since we haven't actually installed
    4505             :                          * them yet( we received them from the kernel )
    4506             :                          * we don't think they are active.
    4507             :                          * So let's pretend they are active to actually
    4508             :                          * remove them.
    4509             :                          * In all honesty I'm not sure if we should
    4510             :                          * mark them as active when we receive them
    4511             :                          * This is startup only so probably ok.
    4512             :                          *
    4513             :                          * If we ever decide to move rib_sweep_table
    4514             :                          * to a different spot (ie startup )
    4515             :                          * this decision needs to be revisited
    4516             :                          */
    4517           0 :                         SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
    4518           0 :                         for (ALL_NEXTHOPS(re->nhe->nhg, nexthop))
    4519           0 :                                 SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
    4520             : 
    4521           0 :                         rib_uninstall_kernel(rn, re);
    4522           0 :                         rib_delnode(rn, re);
    4523             :                 }
    4524             :         }
    4525             : 
    4526           6 :         if (IS_ZEBRA_DEBUG_RIB)
    4527           6 :                 zlog_debug("%s: ends", __func__);
    4528             : }
    4529             : 
    4530             : /* Sweep all RIB tables.  */
    4531           1 : void rib_sweep_route(struct thread *t)
    4532             : {
    4533           1 :         struct vrf *vrf;
    4534           1 :         struct zebra_vrf *zvrf;
    4535             : 
    4536           3 :         RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
    4537           1 :                 if ((zvrf = vrf->info) == NULL)
    4538           0 :                         continue;
    4539             : 
    4540           1 :                 rib_sweep_table(zvrf->table[AFI_IP][SAFI_UNICAST]);
    4541           1 :                 rib_sweep_table(zvrf->table[AFI_IP6][SAFI_UNICAST]);
    4542             :         }
    4543             : 
    4544           1 :         zebra_router_sweep_route();
    4545           1 :         zebra_router_sweep_nhgs();
    4546           1 : }
    4547             : 
    4548             : /* Remove specific by protocol routes from 'table'. */
    4549           6 : unsigned long rib_score_proto_table(uint8_t proto, unsigned short instance,
    4550             :                                     struct route_table *table)
    4551             : {
    4552           6 :         struct route_node *rn;
    4553           6 :         struct route_entry *re;
    4554           6 :         struct route_entry *next;
    4555           6 :         unsigned long n = 0;
    4556             : 
    4557           6 :         if (table)
    4558          48 :                 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
    4559         108 :                         RNODE_FOREACH_RE_SAFE (rn, re, next) {
    4560          24 :                                 if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
    4561           0 :                                         continue;
    4562          24 :                                 if (re->type == proto
    4563           0 :                                     && re->instance == instance) {
    4564           0 :                                         rib_delnode(rn, re);
    4565           0 :                                         n++;
    4566             :                                 }
    4567             :                         }
    4568           6 :         return n;
    4569             : }
    4570             : 
    4571             : /* Remove specific by protocol routes. */
    4572           3 : unsigned long rib_score_proto(uint8_t proto, unsigned short instance)
    4573             : {
    4574           3 :         struct vrf *vrf;
    4575           3 :         struct zebra_vrf *zvrf;
    4576           3 :         struct other_route_table *ort;
    4577           3 :         unsigned long cnt = 0;
    4578             : 
    4579           9 :         RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
    4580           3 :                 zvrf = vrf->info;
    4581           3 :                 if (!zvrf)
    4582           0 :                         continue;
    4583             : 
    4584           3 :                 cnt += rib_score_proto_table(proto, instance,
    4585             :                                              zvrf->table[AFI_IP][SAFI_UNICAST])
    4586           3 :                        + rib_score_proto_table(
    4587             :                                proto, instance,
    4588             :                                zvrf->table[AFI_IP6][SAFI_UNICAST]);
    4589             : 
    4590           6 :                 frr_each(otable, &zvrf->other_tables, ort) cnt +=
    4591           0 :                         rib_score_proto_table(proto, instance, ort->table);
    4592             :         }
    4593             : 
    4594           3 :         return cnt;
    4595             : }
    4596             : 
    4597             : /* Close RIB and clean up kernel routes. */
    4598           4 : void rib_close_table(struct route_table *table)
    4599             : {
    4600           4 :         struct route_node *rn;
    4601           4 :         rib_dest_t *dest;
    4602             : 
    4603           4 :         if (!table)
    4604             :                 return;
    4605             : 
    4606          32 :         for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
    4607          28 :                 dest = rib_dest_from_rnode(rn);
    4608             : 
    4609          28 :                 if (dest && dest->selected_fib) {
    4610           7 :                         rib_uninstall_kernel(rn, dest->selected_fib);
    4611           7 :                         dest->selected_fib = NULL;
    4612             :                 }
    4613             :         }
    4614             : }
    4615             : 
    4616             : /*
    4617             :  * Handler for async dataplane results after a pseudowire installation
    4618             :  */
    4619           0 : static void handle_pw_result(struct zebra_dplane_ctx *ctx)
    4620             : {
    4621           0 :         struct zebra_pw *pw;
    4622           0 :         struct zebra_vrf *vrf;
    4623             : 
    4624             :         /* The pseudowire code assumes success - we act on an error
    4625             :          * result for installation attempts here.
    4626             :          */
    4627           0 :         if (dplane_ctx_get_op(ctx) != DPLANE_OP_PW_INSTALL)
    4628             :                 return;
    4629             : 
    4630           0 :         if (dplane_ctx_get_status(ctx) != ZEBRA_DPLANE_REQUEST_SUCCESS) {
    4631           0 :                 vrf = zebra_vrf_lookup_by_id(dplane_ctx_get_vrf(ctx));
    4632           0 :                 pw = zebra_pw_find(vrf, dplane_ctx_get_ifname(ctx));
    4633           0 :                 if (pw)
    4634           0 :                         zebra_pw_install_failure(pw,
    4635             :                                                  dplane_ctx_get_pw_status(ctx));
    4636             :         }
    4637             : }
    4638             : 
    4639             : /*
    4640             :  * Handle results from the dataplane system. Dequeue update context
    4641             :  * structs, dispatch to appropriate internal handlers.
    4642             :  */
    4643          16 : static void rib_process_dplane_results(struct thread *thread)
    4644             : {
    4645          16 :         struct zebra_dplane_ctx *ctx;
    4646          16 :         struct dplane_ctx_list_head ctxlist;
    4647          16 :         bool shut_p = false;
    4648             : 
    4649             :         /* Dequeue a list of completed updates with one lock/unlock cycle */
    4650             : 
    4651          32 :         do {
    4652          32 :                 dplane_ctx_q_init(&ctxlist);
    4653             : 
    4654             :                 /* Take lock controlling queue of results */
    4655          64 :                 frr_with_mutex (&dplane_mutex) {
    4656             :                         /* Dequeue list of context structs */
    4657          32 :                         dplane_ctx_list_append(&ctxlist, &rib_dplane_q);
    4658             :                 }
    4659             : 
    4660             :                 /* Dequeue context block */
    4661          32 :                 ctx = dplane_ctx_dequeue(&ctxlist);
    4662             : 
    4663             :                 /* If we've emptied the results queue, we're done */
    4664          32 :                 if (ctx == NULL)
    4665             :                         break;
    4666             : 
    4667             :                 /* If zebra is shutting down, avoid processing results,
    4668             :                  * just drain the results queue.
    4669             :                  */
    4670          16 :                 shut_p = atomic_load_explicit(&zrouter.in_shutdown,
    4671             :                                               memory_order_relaxed);
    4672          16 :                 if (shut_p) {
    4673          12 :                         while (ctx) {
    4674          11 :                                 dplane_ctx_fini(&ctx);
    4675             : 
    4676          11 :                                 ctx = dplane_ctx_dequeue(&ctxlist);
    4677             :                         }
    4678             : 
    4679           1 :                         continue;
    4680             :                 }
    4681             : 
    4682             : #ifdef HAVE_SCRIPTING
    4683             :                 char *script_name = frrscript_names_get_script_name(
    4684             :                         ZEBRA_ON_RIB_PROCESS_HOOK_CALL);
    4685             : 
    4686             :                 int ret = 1;
    4687             :                 struct frrscript *fs;
    4688             : 
    4689             :                 if (script_name) {
    4690             :                         fs = frrscript_new(script_name);
    4691             :                         if (fs)
    4692             :                                 ret = frrscript_load(
    4693             :                                         fs, ZEBRA_ON_RIB_PROCESS_HOOK_CALL,
    4694             :                                         NULL);
    4695             :                 }
    4696             : #endif /* HAVE_SCRIPTING */
    4697             : 
    4698          55 :                 while (ctx) {
    4699             : 
    4700             : #ifdef HAVE_SCRIPTING
    4701             :                         if (ret == 0)
    4702             :                                 frrscript_call(fs,
    4703             :                                                ZEBRA_ON_RIB_PROCESS_HOOK_CALL,
    4704             :                                                ("ctx", ctx));
    4705             : #endif /* HAVE_SCRIPTING */
    4706             : 
    4707          40 :                         switch (dplane_ctx_get_op(ctx)) {
    4708           8 :                         case DPLANE_OP_ROUTE_INSTALL:
    4709             :                         case DPLANE_OP_ROUTE_UPDATE:
    4710             :                         case DPLANE_OP_ROUTE_DELETE:
    4711             :                                 /* Bit of special case for route updates
    4712             :                                  * that were generated by async notifications:
    4713             :                                  * we don't want to continue processing these
    4714             :                                  * in the rib.
    4715             :                                  */
    4716           8 :                                 if (dplane_ctx_get_notif_provider(ctx) == 0)
    4717           8 :                                         rib_process_result(ctx);
    4718             :                                 break;
    4719             : 
    4720           0 :                         case DPLANE_OP_ROUTE_NOTIFY:
    4721           0 :                                 rib_process_dplane_notify(ctx);
    4722           0 :                                 break;
    4723             : 
    4724           6 :                         case DPLANE_OP_NH_INSTALL:
    4725             :                         case DPLANE_OP_NH_UPDATE:
    4726             :                         case DPLANE_OP_NH_DELETE:
    4727           6 :                                 zebra_nhg_dplane_result(ctx);
    4728           6 :                                 break;
    4729             : 
    4730           0 :                         case DPLANE_OP_LSP_INSTALL:
    4731             :                         case DPLANE_OP_LSP_UPDATE:
    4732             :                         case DPLANE_OP_LSP_DELETE:
    4733             :                                 /* Bit of special case for LSP updates
    4734             :                                  * that were generated by async notifications:
    4735             :                                  * we don't want to continue processing these.
    4736             :                                  */
    4737           0 :                                 if (dplane_ctx_get_notif_provider(ctx) == 0)
    4738           0 :                                         zebra_mpls_lsp_dplane_result(ctx);
    4739             :                                 break;
    4740             : 
    4741           0 :                         case DPLANE_OP_LSP_NOTIFY:
    4742           0 :                                 zebra_mpls_process_dplane_notify(ctx);
    4743           0 :                                 break;
    4744             : 
    4745           0 :                         case DPLANE_OP_PW_INSTALL:
    4746             :                         case DPLANE_OP_PW_UNINSTALL:
    4747           0 :                                 handle_pw_result(ctx);
    4748           0 :                                 break;
    4749             : 
    4750             :                         case DPLANE_OP_SYS_ROUTE_ADD:
    4751             :                         case DPLANE_OP_SYS_ROUTE_DELETE:
    4752             :                                 break;
    4753             : 
    4754           0 :                         case DPLANE_OP_MAC_INSTALL:
    4755             :                         case DPLANE_OP_MAC_DELETE:
    4756           0 :                                 zebra_vxlan_handle_result(ctx);
    4757           0 :                                 break;
    4758             : 
    4759           0 :                         case DPLANE_OP_RULE_ADD:
    4760             :                         case DPLANE_OP_RULE_DELETE:
    4761             :                         case DPLANE_OP_RULE_UPDATE:
    4762             :                         case DPLANE_OP_IPTABLE_ADD:
    4763             :                         case DPLANE_OP_IPTABLE_DELETE:
    4764             :                         case DPLANE_OP_IPSET_ADD:
    4765             :                         case DPLANE_OP_IPSET_DELETE:
    4766             :                         case DPLANE_OP_IPSET_ENTRY_ADD:
    4767             :                         case DPLANE_OP_IPSET_ENTRY_DELETE:
    4768           0 :                                 zebra_pbr_dplane_result(ctx);
    4769           0 :                                 break;
    4770             : 
    4771          26 :                         case DPLANE_OP_INTF_ADDR_ADD:
    4772             :                         case DPLANE_OP_INTF_ADDR_DEL:
    4773             :                         case DPLANE_OP_INTF_INSTALL:
    4774             :                         case DPLANE_OP_INTF_UPDATE:
    4775             :                         case DPLANE_OP_INTF_DELETE:
    4776             :                         case DPLANE_OP_INTF_NETCONFIG:
    4777          26 :                                 zebra_if_dplane_result(ctx);
    4778          26 :                                 break;
    4779             : 
    4780             :                         case DPLANE_OP_TC_QDISC_INSTALL:
    4781             :                         case DPLANE_OP_TC_QDISC_UNINSTALL:
    4782             :                         case DPLANE_OP_TC_CLASS_ADD:
    4783             :                         case DPLANE_OP_TC_CLASS_DELETE:
    4784             :                         case DPLANE_OP_TC_CLASS_UPDATE:
    4785             :                         case DPLANE_OP_TC_FILTER_ADD:
    4786             :                         case DPLANE_OP_TC_FILTER_DELETE:
    4787             :                         case DPLANE_OP_TC_FILTER_UPDATE:
    4788             :                                 break;
    4789             : 
    4790             :                         /* Some op codes not handled here */
    4791             :                         case DPLANE_OP_ADDR_INSTALL:
    4792             :                         case DPLANE_OP_ADDR_UNINSTALL:
    4793             :                         case DPLANE_OP_NEIGH_INSTALL:
    4794             :                         case DPLANE_OP_NEIGH_UPDATE:
    4795             :                         case DPLANE_OP_NEIGH_DELETE:
    4796             :                         case DPLANE_OP_NEIGH_IP_INSTALL:
    4797             :                         case DPLANE_OP_NEIGH_IP_DELETE:
    4798             :                         case DPLANE_OP_VTEP_ADD:
    4799             :                         case DPLANE_OP_VTEP_DELETE:
    4800             :                         case DPLANE_OP_NEIGH_DISCOVER:
    4801             :                         case DPLANE_OP_BR_PORT_UPDATE:
    4802             :                         case DPLANE_OP_NEIGH_TABLE_UPDATE:
    4803             :                         case DPLANE_OP_GRE_SET:
    4804             :                         case DPLANE_OP_NONE:
    4805             :                                 break;
    4806             : 
    4807             :                         } /* Dispatch by op code */
    4808             : 
    4809          40 :                         dplane_ctx_fini(&ctx);
    4810          40 :                         ctx = dplane_ctx_dequeue(&ctxlist);
    4811             :                 }
    4812             : 
    4813             :         } while (1);
    4814          16 : }
    4815             : 
    4816             : /*
    4817             :  * Results are returned from the dataplane subsystem, in the context of
    4818             :  * the dataplane pthread. We enqueue the results here for processing by
    4819             :  * the main thread later.
    4820             :  */
    4821          42 : static int rib_dplane_results(struct dplane_ctx_list_head *ctxlist)
    4822             : {
    4823             :         /* Take lock controlling queue of results */
    4824          84 :         frr_with_mutex (&dplane_mutex) {
    4825             :                 /* Enqueue context blocks */
    4826          42 :                 dplane_ctx_list_append(&rib_dplane_q, ctxlist);
    4827             :         }
    4828             : 
    4829             :         /* Ensure event is signalled to zebra main pthread */
    4830          42 :         thread_add_event(zrouter.master, rib_process_dplane_results, NULL, 0,
    4831             :                          &t_dplane);
    4832             : 
    4833          42 :         return 0;
    4834             : }
    4835             : 
    4836             : /*
    4837             :  * Ensure there are no empty slots in the route_info array.
    4838             :  * Every route type in zebra should be present there.
    4839             :  */
    4840           1 : static void check_route_info(void)
    4841             : {
    4842           1 :         int len = array_size(route_info);
    4843             : 
    4844             :         /*
    4845             :          * ZEBRA_ROUTE_SYSTEM is special cased since
    4846             :          * its key is 0 anyway.
    4847             :          *
    4848             :          * ZEBRA_ROUTE_ALL is also ignored.
    4849             :          */
    4850          32 :         for (int i = 0; i < len; i++) {
    4851          31 :                 assert(route_info[i].key >= ZEBRA_ROUTE_SYSTEM &&
    4852             :                        route_info[i].key < ZEBRA_ROUTE_MAX);
    4853          31 :                 assert(route_info[i].meta_q_map < MQ_SIZE);
    4854             :         }
    4855           1 : }
    4856             : 
    4857             : /* Routing information base initialize. */
    4858           1 : void rib_init(void)
    4859             : {
    4860           1 :         check_route_info();
    4861             : 
    4862           1 :         rib_queue_init();
    4863             : 
    4864             :         /* Init dataplane, and register for results */
    4865           1 :         pthread_mutex_init(&dplane_mutex, NULL);
    4866           1 :         dplane_ctx_q_init(&rib_dplane_q);
    4867           1 :         zebra_dplane_init(rib_dplane_results);
    4868           1 : }
    4869             : 
    4870             : /*
    4871             :  * vrf_id_get_next
    4872             :  *
    4873             :  * Get the first vrf id that is greater than the given vrf id if any.
    4874             :  *
    4875             :  * Returns true if a vrf id was found, false otherwise.
    4876             :  */
    4877           0 : static inline int vrf_id_get_next(vrf_id_t vrf_id, vrf_id_t *next_id_p)
    4878             : {
    4879           0 :         struct vrf *vrf;
    4880             : 
    4881           0 :         vrf = vrf_lookup_by_id(vrf_id);
    4882           0 :         if (vrf) {
    4883           0 :                 vrf = RB_NEXT(vrf_id_head, vrf);
    4884           0 :                 if (vrf) {
    4885           0 :                         *next_id_p = vrf->vrf_id;
    4886           0 :                         return 1;
    4887             :                 }
    4888             :         }
    4889             : 
    4890             :         return 0;
    4891             : }
    4892             : 
    4893             : /*
    4894             :  * rib_tables_iter_next
    4895             :  *
    4896             :  * Returns the next table in the iteration.
    4897             :  */
    4898           0 : struct route_table *rib_tables_iter_next(rib_tables_iter_t *iter)
    4899             : {
    4900           0 :         struct route_table *table;
    4901             : 
    4902             :         /*
    4903             :          * Array that helps us go over all AFI/SAFI combinations via one
    4904             :          * index.
    4905             :          */
    4906           0 :         static const struct {
    4907             :                 afi_t afi;
    4908             :                 safi_t safi;
    4909             :         } afi_safis[] = {
    4910             :                 {AFI_IP, SAFI_UNICAST},         {AFI_IP, SAFI_MULTICAST},
    4911             :                 {AFI_IP, SAFI_LABELED_UNICAST}, {AFI_IP6, SAFI_UNICAST},
    4912             :                 {AFI_IP6, SAFI_MULTICAST},      {AFI_IP6, SAFI_LABELED_UNICAST},
    4913             :         };
    4914             : 
    4915           0 :         table = NULL;
    4916             : 
    4917           0 :         switch (iter->state) {
    4918             : 
    4919           0 :         case RIB_TABLES_ITER_S_INIT:
    4920           0 :                 iter->vrf_id = VRF_DEFAULT;
    4921           0 :                 iter->afi_safi_ix = -1;
    4922             : 
    4923             :         /* Fall through */
    4924             : 
    4925           0 :         case RIB_TABLES_ITER_S_ITERATING:
    4926           0 :                 iter->afi_safi_ix++;
    4927           0 :                 while (1) {
    4928             : 
    4929           0 :                         while (iter->afi_safi_ix
    4930           0 :                                < (int)array_size(afi_safis)) {
    4931           0 :                                 table = zebra_vrf_table(
    4932           0 :                                         afi_safis[iter->afi_safi_ix].afi,
    4933           0 :                                         afi_safis[iter->afi_safi_ix].safi,
    4934             :                                         iter->vrf_id);
    4935           0 :                                 if (table)
    4936             :                                         break;
    4937             : 
    4938           0 :                                 iter->afi_safi_ix++;
    4939             :                         }
    4940             : 
    4941             :                         /*
    4942             :                          * Found another table in this vrf.
    4943             :                          */
    4944           0 :                         if (table)
    4945             :                                 break;
    4946             : 
    4947             :                         /*
    4948             :                          * Done with all tables in the current vrf, go to the
    4949             :                          * next
    4950             :                          * one.
    4951             :                          */
    4952           0 :                         if (!vrf_id_get_next(iter->vrf_id, &iter->vrf_id))
    4953             :                                 break;
    4954             : 
    4955           0 :                         iter->afi_safi_ix = 0;
    4956             :                 }
    4957             : 
    4958             :                 break;
    4959             : 
    4960             :         case RIB_TABLES_ITER_S_DONE:
    4961             :                 return NULL;
    4962             :         }
    4963             : 
    4964           0 :         if (table)
    4965           0 :                 iter->state = RIB_TABLES_ITER_S_ITERATING;
    4966             :         else
    4967           0 :                 iter->state = RIB_TABLES_ITER_S_DONE;
    4968             : 
    4969             :         return table;
    4970             : }

Generated by: LCOV version v1.16-topotato