back to topotato report
topotato coverage report
Current view: top level - bgpd/rfapi - rfapi_rib.c (source / functions) Hit Total Coverage
Test: test_bgp_distance_change.py::BGPDistanceChange Lines: 0 1008 0.0 %
Date: 2023-02-24 18:37:13 Functions: 0 28 0.0 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  * Copyright 2009-2016, LabN Consulting, L.L.C.
       4             :  *
       5             :  *
       6             :  * This program is free software; you can redistribute it and/or
       7             :  * modify it under the terms of the GNU General Public License
       8             :  * as published by the Free Software Foundation; either version 2
       9             :  * of the License, or (at your option) any later version.
      10             :  *
      11             :  * This program is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU 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             : /*
      22             :  * File:        rfapi_rib.c
      23             :  * Purpose:     maintain per-nve ribs and generate change lists
      24             :  */
      25             : 
      26             : #include "lib/zebra.h"
      27             : #include "lib/prefix.h"
      28             : #include "lib/agg_table.h"
      29             : #include "lib/vty.h"
      30             : #include "lib/memory.h"
      31             : #include "lib/log.h"
      32             : #include "lib/skiplist.h"
      33             : #include "lib/workqueue.h"
      34             : 
      35             : #include "bgpd/bgpd.h"
      36             : #include "bgpd/bgp_route.h"
      37             : #include "bgpd/bgp_ecommunity.h"
      38             : #include "bgpd/bgp_mplsvpn.h"
      39             : #include "bgpd/bgp_vnc_types.h"
      40             : 
      41             : #include "bgpd/rfapi/rfapi.h"
      42             : #include "bgpd/rfapi/bgp_rfapi_cfg.h"
      43             : #include "bgpd/rfapi/rfapi_import.h"
      44             : #include "bgpd/rfapi/rfapi_private.h"
      45             : #include "bgpd/rfapi/rfapi_vty.h"
      46             : #include "bgpd/rfapi/vnc_import_bgp.h"
      47             : #include "bgpd/rfapi/rfapi_rib.h"
      48             : #include "bgpd/rfapi/rfapi_monitor.h"
      49             : #include "bgpd/rfapi/rfapi_encap_tlv.h"
      50             : #include "bgpd/rfapi/vnc_debug.h"
      51             : 
      52             : #define DEBUG_PROCESS_PENDING_NODE      0
      53             : #define DEBUG_PENDING_DELETE_ROUTE      0
      54             : #define DEBUG_NHL                       0
      55             : #define DEBUG_RIB_SL_RD                 0
      56             : 
      57             : /* forward decl */
      58             : #if DEBUG_NHL
      59             : static void rfapiRibShowRibSl(void *stream, struct prefix *pfx,
      60             :                               struct skiplist *sl);
      61             : #endif
      62             : 
      63             : /*
      64             :  * RIB
      65             :  * ---
      66             :  * Model of the set of routes currently in the NVE's RIB.
      67             :  *
      68             :  * node->info                ptr to "struct skiplist".
      69             :  *                      MUST be NULL if there are no routes.
      70             :  *                      key = ptr to struct prefix {vn}
      71             :  *                      val = ptr to struct rfapi_info
      72             :  *                      skiplist.del = NULL
      73             :  *                      skiplist.cmp = vnc_prefix_cmp
      74             :  *
      75             :  * node->aggregate   ptr to "struct skiplist".
      76             :  *                      key = ptr to struct prefix {vn}
      77             :  *                      val = ptr to struct rfapi_info
      78             :  *                      skiplist.del = rfapi_info_free
      79             :  *                      skiplist.cmp = vnc_prefix_cmp
      80             :  *
      81             :  *                      This skiplist at "aggregate"
      82             :  *                      contains the routes recently
      83             :  *                      deleted
      84             :  *
      85             :  *
      86             :  * Pending RIB
      87             :  * -----------
      88             :  * Sparse list of prefixes that need to be updated. Each node
      89             :  * will have the complete set of routes for the prefix.
      90             :  *
      91             :  * node->info                ptr to "struct list" (lib/linklist.h)
      92             :  *                      "Cost List"
      93             :  *                      List of routes sorted lowest cost first.
      94             :  *                      This list is how the new complete set
      95             :  *                      of routes should look.
      96             :  *                      Set if there are updates to the prefix;
      97             :  *                      MUST be NULL if there are no updates.
      98             :  *
      99             :  *                      .data = ptr to struct rfapi_info
     100             :  *                      list.cmp = NULL (sorted manually)
     101             :  *                      list.del = rfapi_info_free
     102             :  *
     103             :  *                      Special case: if node->info is 1, it means
     104             :  *                      "delete all routes at this prefix".
     105             :  *
     106             :  * node->aggregate   ptr to struct skiplist
     107             :  *                      key = ptr to struct prefix {vn} (part of ri)
     108             :  *                      val =  struct rfapi_info
     109             :  *                      skiplist.cmp = vnc_prefix_cmp
     110             :  *                      skiplist.del = NULL
     111             :  *
     112             :  *                      ptlist is rewritten anew each time
     113             :  *                      rfapiRibUpdatePendingNode() is called
     114             :  *
     115             :  *                      THE ptlist VALUES ARE REFERENCES TO THE
     116             :  *                      rfapi_info STRUCTS IN THE node->info LIST.
     117             :  */
     118             : 
     119             : /*
     120             :  * iterate over RIB to count responses, compare with running counters
     121             :  */
     122           0 : void rfapiRibCheckCounts(
     123             :         int checkstats,      /* validate rfd & global counts */
     124             :         unsigned int offset) /* number of ri's held separately */
     125             : {
     126           0 :         struct rfapi_descriptor *rfd;
     127           0 :         struct listnode *node;
     128             : 
     129           0 :         struct bgp *bgp = bgp_get_default();
     130             : 
     131           0 :         uint32_t t_pfx_active = 0;
     132           0 :         uint32_t t_pfx_deleted = 0;
     133             : 
     134           0 :         uint32_t t_ri_active = 0;
     135           0 :         uint32_t t_ri_deleted = 0;
     136           0 :         uint32_t t_ri_pend = 0;
     137             : 
     138           0 :         unsigned int alloc_count;
     139             : 
     140             :         /*
     141             :          * loop over NVEs
     142             :          */
     143           0 :         for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, node, rfd)) {
     144             : 
     145             :                 afi_t afi;
     146             :                 uint32_t pfx_active = 0;
     147             :                 uint32_t pfx_deleted = 0;
     148             : 
     149           0 :                 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
     150             : 
     151           0 :                         struct agg_node *rn;
     152             : 
     153           0 :                         for (rn = agg_route_top(rfd->rib[afi]); rn;
     154           0 :                              rn = agg_route_next(rn)) {
     155             : 
     156           0 :                                 struct skiplist *sl = rn->info;
     157           0 :                                 struct skiplist *dsl = rn->aggregate;
     158           0 :                                 uint32_t ri_active = 0;
     159           0 :                                 uint32_t ri_deleted = 0;
     160             : 
     161           0 :                                 if (sl) {
     162           0 :                                         ri_active = skiplist_count(sl);
     163           0 :                                         assert(ri_active);
     164           0 :                                         t_ri_active += ri_active;
     165           0 :                                         ++pfx_active;
     166           0 :                                         ++t_pfx_active;
     167             :                                 }
     168             : 
     169           0 :                                 if (dsl) {
     170           0 :                                         ri_deleted = skiplist_count(dsl);
     171           0 :                                         t_ri_deleted += ri_deleted;
     172           0 :                                         ++pfx_deleted;
     173           0 :                                         ++t_pfx_deleted;
     174             :                                 }
     175             :                         }
     176           0 :                         for (rn = agg_route_top(rfd->rib_pending[afi]); rn;
     177           0 :                              rn = agg_route_next(rn)) {
     178             : 
     179           0 :                                 struct list *l = rn->info; /* sorted by cost */
     180           0 :                                 struct skiplist *sl = rn->aggregate;
     181           0 :                                 uint32_t ri_pend_cost = 0;
     182           0 :                                 uint32_t ri_pend_uniq = 0;
     183             : 
     184           0 :                                 if (sl) {
     185           0 :                                         ri_pend_uniq = skiplist_count(sl);
     186             :                                 }
     187             : 
     188           0 :                                 if (l && (l != (void *)1)) {
     189           0 :                                         ri_pend_cost = l->count;
     190           0 :                                         t_ri_pend += l->count;
     191             :                                 }
     192             : 
     193           0 :                                 assert(ri_pend_uniq == ri_pend_cost);
     194             :                         }
     195             :                 }
     196             : 
     197           0 :                 if (checkstats) {
     198           0 :                         if (pfx_active != rfd->rib_prefix_count) {
     199           0 :                                 vnc_zlog_debug_verbose(
     200             :                                         "%s: rfd %p actual pfx count %u != running %u",
     201             :                                         __func__, rfd, pfx_active,
     202             :                                         rfd->rib_prefix_count);
     203           0 :                                 assert(0);
     204             :                         }
     205             :                 }
     206             :         }
     207             : 
     208           0 :         if (checkstats && bgp->rfapi) {
     209           0 :                 if (t_pfx_active != bgp->rfapi->rib_prefix_count_total) {
     210           0 :                         vnc_zlog_debug_verbose(
     211             :                                 "%s: actual total pfx count %u != running %u",
     212             :                                 __func__, t_pfx_active,
     213             :                                 bgp->rfapi->rib_prefix_count_total);
     214           0 :                         assert(0);
     215             :                 }
     216             :         }
     217             : 
     218             :         /*
     219             :          * Check against memory allocation count
     220             :          */
     221           0 :         alloc_count = mtype_stats_alloc(MTYPE_RFAPI_INFO);
     222           0 :         assert(t_ri_active + t_ri_deleted + t_ri_pend + offset == alloc_count);
     223           0 : }
     224             : 
     225           0 : static struct rfapi_info *rfapi_info_new(void)
     226             : {
     227           0 :         return XCALLOC(MTYPE_RFAPI_INFO, sizeof(struct rfapi_info));
     228             : }
     229             : 
     230           0 : void rfapiFreeRfapiUnOptionChain(struct rfapi_un_option *p)
     231             : {
     232           0 :         while (p) {
     233           0 :                 struct rfapi_un_option *next;
     234             : 
     235           0 :                 next = p->next;
     236           0 :                 XFREE(MTYPE_RFAPI_UN_OPTION, p);
     237           0 :                 p = next;
     238             :         }
     239           0 : }
     240             : 
     241           0 : void rfapiFreeRfapiVnOptionChain(struct rfapi_vn_option *p)
     242             : {
     243           0 :         while (p) {
     244           0 :                 struct rfapi_vn_option *next;
     245             : 
     246           0 :                 next = p->next;
     247           0 :                 XFREE(MTYPE_RFAPI_VN_OPTION, p);
     248           0 :                 p = next;
     249             :         }
     250           0 : }
     251             : 
     252             : 
     253           0 : static void rfapi_info_free(struct rfapi_info *goner)
     254             : {
     255           0 :         if (goner) {
     256           0 :                 if (goner->tea_options) {
     257           0 :                         rfapiFreeBgpTeaOptionChain(goner->tea_options);
     258           0 :                         goner->tea_options = NULL;
     259             :                 }
     260           0 :                 if (goner->un_options) {
     261           0 :                         rfapiFreeRfapiUnOptionChain(goner->un_options);
     262           0 :                         goner->un_options = NULL;
     263             :                 }
     264           0 :                 if (goner->vn_options) {
     265           0 :                         rfapiFreeRfapiVnOptionChain(goner->vn_options);
     266           0 :                         goner->vn_options = NULL;
     267             :                 }
     268           0 :                 if (goner->timer) {
     269           0 :                         struct rfapi_rib_tcb *tcb;
     270             : 
     271           0 :                         tcb = THREAD_ARG(goner->timer);
     272           0 :                         THREAD_OFF(goner->timer);
     273           0 :                         XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
     274             :                 }
     275           0 :                 XFREE(MTYPE_RFAPI_INFO, goner);
     276             :         }
     277           0 : }
     278             : 
     279             : /*
     280             :  * Timer control block for recently-deleted and expired routes
     281             :  */
     282             : struct rfapi_rib_tcb {
     283             :         struct rfapi_descriptor *rfd;
     284             :         struct skiplist *sl;
     285             :         struct rfapi_info *ri;
     286             :         struct agg_node *rn;
     287             :         int flags;
     288             : #define RFAPI_RIB_TCB_FLAG_DELETED      0x00000001
     289             : };
     290             : 
     291             : /*
     292             :  * remove route from rib
     293             :  */
     294           0 : static void rfapiRibExpireTimer(struct thread *t)
     295             : {
     296           0 :         struct rfapi_rib_tcb *tcb = THREAD_ARG(t);
     297             : 
     298           0 :         RFAPI_RIB_CHECK_COUNTS(1, 0);
     299             : 
     300             :         /*
     301             :          * Forget reference to thread. Otherwise rfapi_info_free() will
     302             :          * attempt to free thread pointer as an option chain
     303             :          */
     304           0 :         tcb->ri->timer = NULL;
     305             : 
     306             :         /* "deleted" skiplist frees ri, "active" doesn't */
     307           0 :         assert(!skiplist_delete(tcb->sl, &tcb->ri->rk, NULL));
     308           0 :         if (!tcb->sl->del) {
     309             :                 /*
     310             :                  * XXX in this case, skiplist has no delete function: we must
     311             :                  * therefore delete rfapi_info explicitly.
     312             :                  */
     313           0 :                 rfapi_info_free(tcb->ri);
     314             :         }
     315             : 
     316           0 :         if (skiplist_empty(tcb->sl)) {
     317           0 :                 if (CHECK_FLAG(tcb->flags, RFAPI_RIB_TCB_FLAG_DELETED))
     318           0 :                         tcb->rn->aggregate = NULL;
     319             :                 else {
     320           0 :                         struct bgp *bgp = bgp_get_default();
     321           0 :                         tcb->rn->info = NULL;
     322           0 :                         RFAPI_RIB_PREFIX_COUNT_DECR(tcb->rfd, bgp->rfapi);
     323             :                 }
     324           0 :                 skiplist_free(tcb->sl);
     325           0 :                 agg_unlock_node(tcb->rn);
     326             :         }
     327             : 
     328           0 :         XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
     329             : 
     330           0 :         RFAPI_RIB_CHECK_COUNTS(1, 0);
     331           0 : }
     332             : 
     333           0 : static void rfapiRibStartTimer(struct rfapi_descriptor *rfd,
     334             :                                struct rfapi_info *ri,
     335             :                                struct agg_node *rn, /* route node attached to */
     336             :                                int deleted)
     337             : {
     338           0 :         struct rfapi_rib_tcb *tcb = NULL;
     339             : 
     340           0 :         if (ri->timer) {
     341           0 :                 tcb = THREAD_ARG(ri->timer);
     342           0 :                 THREAD_OFF(ri->timer);
     343             :         } else {
     344           0 :                 tcb = XCALLOC(MTYPE_RFAPI_RECENT_DELETE,
     345             :                               sizeof(struct rfapi_rib_tcb));
     346             :         }
     347           0 :         tcb->rfd = rfd;
     348           0 :         tcb->ri = ri;
     349           0 :         tcb->rn = rn;
     350           0 :         if (deleted) {
     351           0 :                 tcb->sl = (struct skiplist *)rn->aggregate;
     352           0 :                 SET_FLAG(tcb->flags, RFAPI_RIB_TCB_FLAG_DELETED);
     353             :         } else {
     354           0 :                 tcb->sl = (struct skiplist *)rn->info;
     355           0 :                 UNSET_FLAG(tcb->flags, RFAPI_RIB_TCB_FLAG_DELETED);
     356             :         }
     357             : 
     358           0 :         vnc_zlog_debug_verbose("%s: rfd %p pfx %pRN life %u", __func__, rfd, rn,
     359             :                                ri->lifetime);
     360             : 
     361           0 :         thread_add_timer(bm->master, rfapiRibExpireTimer, tcb, ri->lifetime,
     362             :                          &ri->timer);
     363           0 : }
     364             : 
     365           0 : extern void rfapi_rib_key_init(struct prefix *prefix, /* may be NULL */
     366             :                                struct prefix_rd *rd,  /* may be NULL */
     367             :                                struct prefix *aux,    /* may be NULL */
     368             :                                struct rfapi_rib_key *rk)
     369             : 
     370             : {
     371           0 :         memset((void *)rk, 0, sizeof(struct rfapi_rib_key));
     372           0 :         if (prefix)
     373           0 :                 rk->vn = *prefix;
     374           0 :         if (rd)
     375           0 :                 rk->rd = *rd;
     376           0 :         if (aux)
     377           0 :                 rk->aux_prefix = *aux;
     378           0 : }
     379             : 
     380             : /*
     381             :  * Compares two <struct rfapi_rib_key>s
     382             :  */
     383           0 : int rfapi_rib_key_cmp(const void *k1, const void *k2)
     384             : {
     385           0 :         const struct rfapi_rib_key *a = (struct rfapi_rib_key *)k1;
     386           0 :         const struct rfapi_rib_key *b = (struct rfapi_rib_key *)k2;
     387           0 :         int ret;
     388             : 
     389           0 :         if (!a || !b)
     390           0 :                 return (a - b);
     391             : 
     392           0 :         ret = vnc_prefix_cmp(&a->vn, &b->vn);
     393           0 :         if (ret)
     394             :                 return ret;
     395             : 
     396           0 :         ret = vnc_prefix_cmp(&a->rd, &b->rd);
     397           0 :         if (ret)
     398             :                 return ret;
     399             : 
     400           0 :         ret = vnc_prefix_cmp(&a->aux_prefix, &b->aux_prefix);
     401             : 
     402           0 :         return ret;
     403             : }
     404             : 
     405             : 
     406             : /*
     407             :  * Note: this function will claim that two option chains are
     408             :  * different unless their option items are in identical order.
     409             :  * The consequence is that RFP updated responses can be sent
     410             :  * unnecessarily, or that they might contain nexthop items
     411             :  * that are not strictly needed.
     412             :  *
     413             :  * This function could be modified to compare option chains more
     414             :  * thoroughly, but it's not clear that the extra compuation would
     415             :  * be worth it.
     416             :  */
     417           0 : static int bgp_tea_options_cmp(struct bgp_tea_options *a,
     418             :                                struct bgp_tea_options *b)
     419             : {
     420           0 :         int rc;
     421             : 
     422           0 :         if (!a || !b) {
     423           0 :                 return (a - b);
     424             :         }
     425             : 
     426           0 :         if (a->type != b->type)
     427           0 :                 return (a->type - b->type);
     428           0 :         if (a->length != b->length)
     429           0 :                 return (a->length = b->length);
     430           0 :         if ((rc = memcmp(a->value, b->value, a->length)))
     431             :                 return rc;
     432           0 :         if (!a->next != !b->next) { /* logical xor */
     433           0 :                 return (a->next - b->next);
     434             :         }
     435           0 :         if (a->next)
     436             :                 return bgp_tea_options_cmp(a->next, b->next);
     437             :         return 0;
     438             : }
     439             : 
     440           0 : static int rfapi_info_cmp(struct rfapi_info *a, struct rfapi_info *b)
     441             : {
     442           0 :         int rc;
     443             : 
     444           0 :         if (!a || !b)
     445           0 :                 return (a - b);
     446             : 
     447           0 :         if ((rc = rfapi_rib_key_cmp(&a->rk, &b->rk)))
     448             :                 return rc;
     449             : 
     450           0 :         if ((rc = vnc_prefix_cmp(&a->un, &b->un)))
     451             :                 return rc;
     452             : 
     453           0 :         if (a->cost != b->cost)
     454           0 :                 return (a->cost - b->cost);
     455             : 
     456           0 :         if (a->lifetime != b->lifetime)
     457           0 :                 return (a->lifetime - b->lifetime);
     458             : 
     459           0 :         if ((rc = bgp_tea_options_cmp(a->tea_options, b->tea_options)))
     460             :                 return rc;
     461             : 
     462             :         return 0;
     463             : }
     464             : 
     465           0 : void rfapiRibClear(struct rfapi_descriptor *rfd)
     466             : {
     467           0 :         struct bgp *bgp;
     468           0 :         afi_t afi;
     469             : 
     470           0 :         if (rfd->bgp)
     471             :                 bgp = rfd->bgp;
     472             :         else
     473           0 :                 bgp = bgp_get_default();
     474             : #ifdef DEBUG_L2_EXTRA
     475             :         vnc_zlog_debug_verbose("%s: rfd=%p", __func__, rfd);
     476             : #endif
     477             : 
     478           0 :         for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
     479           0 :                 struct agg_node *pn;
     480           0 :                 struct agg_node *rn;
     481             : 
     482           0 :                 if (rfd->rib_pending[afi]) {
     483           0 :                         for (pn = agg_route_top(rfd->rib_pending[afi]); pn;
     484           0 :                              pn = agg_route_next(pn)) {
     485           0 :                                 if (pn->aggregate) {
     486             :                                         /*
     487             :                                          * free references into the rfapi_info
     488             :                                          * structures before
     489             :                                          * freeing the structures themselves
     490             :                                          */
     491           0 :                                         skiplist_free(
     492             :                                                 (struct skiplist
     493             :                                                          *)(pn->aggregate));
     494           0 :                                         pn->aggregate = NULL;
     495           0 :                                         agg_unlock_node(
     496             :                                                 pn); /* skiplist deleted */
     497             :                                 }
     498             :                                 /*
     499             :                                  * free the rfapi_info structures
     500             :                                  */
     501           0 :                                 if (pn->info) {
     502           0 :                                         if (pn->info != (void *)1) {
     503           0 :                                                 list_delete(
     504             :                                                         (struct list *
     505           0 :                                                                  *)(&pn->info));
     506             :                                         }
     507           0 :                                         pn->info = NULL;
     508             :                                         /* linklist or 1 deleted */
     509           0 :                                         agg_unlock_node(pn);
     510             :                                 }
     511             :                         }
     512             :                 }
     513           0 :                 if (rfd->rib[afi]) {
     514           0 :                         for (rn = agg_route_top(rfd->rib[afi]); rn;
     515           0 :                              rn = agg_route_next(rn)) {
     516           0 :                                 if (rn->info) {
     517             : 
     518             :                                         struct rfapi_info *ri;
     519             : 
     520           0 :                                         while (0 == skiplist_first(
     521             :                                                             (struct skiplist *)
     522           0 :                                                                     rn->info,
     523             :                                                             NULL,
     524             :                                                             (void **)&ri)) {
     525             : 
     526           0 :                                                 rfapi_info_free(ri);
     527           0 :                                                 skiplist_delete_first(
     528             :                                                         (struct skiplist *)
     529           0 :                                                                 rn->info);
     530             :                                         }
     531           0 :                                         skiplist_free(
     532           0 :                                                 (struct skiplist *)rn->info);
     533           0 :                                         rn->info = NULL;
     534           0 :                                         agg_unlock_node(rn);
     535           0 :                                         RFAPI_RIB_PREFIX_COUNT_DECR(rfd,
     536             :                                                                     bgp->rfapi);
     537             :                                 }
     538           0 :                                 if (rn->aggregate) {
     539             : 
     540             :                                         struct rfapi_info *ri_del;
     541             : 
     542             :                                         /* delete skiplist & contents */
     543           0 :                                         while (!skiplist_first(
     544             :                                                 (struct skiplist
     545           0 :                                                          *)(rn->aggregate),
     546             :                                                 NULL, (void **)&ri_del)) {
     547             : 
     548             :                                                 /* sl->del takes care of ri_del
     549             :                                                  */
     550           0 :                                                 skiplist_delete_first((
     551             :                                                         struct skiplist
     552           0 :                                                                 *)(rn->aggregate));
     553             :                                         }
     554           0 :                                         skiplist_free(
     555             :                                                 (struct skiplist
     556           0 :                                                          *)(rn->aggregate));
     557             : 
     558           0 :                                         rn->aggregate = NULL;
     559           0 :                                         agg_unlock_node(rn);
     560             :                                 }
     561             :                         }
     562             :                 }
     563             :         }
     564           0 :         if (rfd->updated_responses_queue)
     565           0 :                 work_queue_free_and_null(&rfd->updated_responses_queue);
     566           0 : }
     567             : 
     568             : /*
     569             :  * Release all dynamically-allocated memory that is part of an HD's RIB
     570             :  */
     571           0 : void rfapiRibFree(struct rfapi_descriptor *rfd)
     572             : {
     573           0 :         afi_t afi;
     574             : 
     575             : 
     576             :         /*
     577             :          * NB rfd is typically detached from master list, so is not included
     578             :          * in the count performed by RFAPI_RIB_CHECK_COUNTS
     579             :          */
     580             : 
     581             :         /*
     582             :          * Free routes attached to radix trees
     583             :          */
     584           0 :         rfapiRibClear(rfd);
     585             : 
     586             :         /* Now the uncounted rfapi_info's are freed, so the check should succeed
     587             :          */
     588           0 :         RFAPI_RIB_CHECK_COUNTS(1, 0);
     589             : 
     590             :         /*
     591             :          * Free radix trees
     592             :          */
     593           0 :         for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
     594           0 :                 if (rfd->rib_pending[afi])
     595           0 :                         agg_table_finish(rfd->rib_pending[afi]);
     596           0 :                 rfd->rib_pending[afi] = NULL;
     597             : 
     598           0 :                 if (rfd->rib[afi])
     599           0 :                         agg_table_finish(rfd->rib[afi]);
     600           0 :                 rfd->rib[afi] = NULL;
     601             : 
     602             :                 /* NB agg_table_finish frees only prefix nodes, not chained
     603             :                  * info */
     604           0 :                 if (rfd->rsp_times[afi])
     605           0 :                         agg_table_finish(rfd->rsp_times[afi]);
     606           0 :                 rfd->rib[afi] = NULL;
     607             :         }
     608           0 : }
     609             : 
     610             : /*
     611             :  * Copies struct bgp_path_info to struct rfapi_info, except for rk fields and un
     612             :  */
     613           0 : static void rfapiRibBi2Ri(struct bgp_path_info *bpi, struct rfapi_info *ri,
     614             :                           uint32_t lifetime)
     615             : {
     616           0 :         struct bgp_attr_encap_subtlv *pEncap;
     617             : 
     618           0 :         ri->cost = rfapiRfpCost(bpi->attr);
     619           0 :         ri->lifetime = lifetime;
     620             : 
     621             :         /* This loop based on rfapiRouteInfo2NextHopEntry() */
     622           0 :         for (pEncap = bgp_attr_get_vnc_subtlvs(bpi->attr); pEncap;
     623           0 :              pEncap = pEncap->next) {
     624           0 :                 struct bgp_tea_options *hop;
     625             : 
     626           0 :                 switch (pEncap->type) {
     627             :                 case BGP_VNC_SUBTLV_TYPE_LIFETIME:
     628             :                         /* use configured lifetime, not attr lifetime */
     629             :                         break;
     630             : 
     631           0 :                 case BGP_VNC_SUBTLV_TYPE_RFPOPTION:
     632           0 :                         hop = XCALLOC(MTYPE_BGP_TEA_OPTIONS,
     633             :                                       sizeof(struct bgp_tea_options));
     634           0 :                         assert(hop);
     635           0 :                         hop->type = pEncap->value[0];
     636           0 :                         hop->length = pEncap->value[1];
     637           0 :                         hop->value = XCALLOC(MTYPE_BGP_TEA_OPTIONS_VALUE,
     638             :                                              pEncap->length - 2);
     639           0 :                         assert(hop->value);
     640           0 :                         memcpy(hop->value, pEncap->value + 2,
     641           0 :                                pEncap->length - 2);
     642           0 :                         if (hop->length > pEncap->length - 2) {
     643           0 :                                 zlog_warn(
     644             :                                         "%s: VNC subtlv length mismatch: RFP option says %d, attr says %d (shrinking)",
     645             :                                         __func__, hop->length,
     646             :                                         pEncap->length - 2);
     647           0 :                                 hop->length = pEncap->length - 2;
     648             :                         }
     649           0 :                         hop->next = ri->tea_options;
     650           0 :                         ri->tea_options = hop;
     651           0 :                         break;
     652             : 
     653             :                 default:
     654             :                         break;
     655             :                 }
     656             :         }
     657             : 
     658           0 :         rfapi_un_options_free(ri->un_options); /* maybe free old version */
     659           0 :         ri->un_options = rfapi_encap_tlv_to_un_option(bpi->attr);
     660             : 
     661             :         /*
     662             :          * VN options
     663             :          */
     664           0 :         if (bpi->extra
     665           0 :             && decode_rd_type(bpi->extra->vnc.import.rd.val)
     666             :                        == RD_TYPE_VNC_ETH) {
     667             :                 /* ethernet route */
     668             : 
     669           0 :                 struct rfapi_vn_option *vo;
     670             : 
     671           0 :                 vo = XCALLOC(MTYPE_RFAPI_VN_OPTION,
     672             :                              sizeof(struct rfapi_vn_option));
     673           0 :                 assert(vo);
     674             : 
     675           0 :                 vo->type = RFAPI_VN_OPTION_TYPE_L2ADDR;
     676             : 
     677             :                 /* copy from RD already stored in bpi, so we don't need it_node
     678             :                  */
     679           0 :                 memcpy(&vo->v.l2addr.macaddr, bpi->extra->vnc.import.rd.val + 2,
     680             :                        ETH_ALEN);
     681             : 
     682           0 :                 (void)rfapiEcommunityGetLNI(bgp_attr_get_ecommunity(bpi->attr),
     683             :                                             &vo->v.l2addr.logical_net_id);
     684           0 :                 (void)rfapiEcommunityGetEthernetTag(
     685           0 :                         bgp_attr_get_ecommunity(bpi->attr),
     686             :                         &vo->v.l2addr.tag_id);
     687             : 
     688             :                 /* local_nve_id comes from RD */
     689           0 :                 vo->v.l2addr.local_nve_id = bpi->extra->vnc.import.rd.val[1];
     690             : 
     691             :                 /* label comes from MP_REACH_NLRI label */
     692           0 :                 vo->v.l2addr.label = decode_label(&bpi->extra->label[0]);
     693             : 
     694           0 :                 rfapi_vn_options_free(
     695             :                         ri->vn_options); /* maybe free old version */
     696           0 :                 ri->vn_options = vo;
     697             :         }
     698             : 
     699             :         /*
     700             :          * If there is an auxiliary IP address (L2 can have it), copy it
     701             :          */
     702           0 :         if (bpi->extra && bpi->extra->vnc.import.aux_prefix.family) {
     703           0 :                 ri->rk.aux_prefix = bpi->extra->vnc.import.aux_prefix;
     704             :         }
     705           0 : }
     706             : 
     707             : /*
     708             :  * rfapiRibPreloadBi
     709             :  *
     710             :  *      Install route into NVE RIB model so as to be consistent with
     711             :  *      caller's response to rfapi_query().
     712             :  *
     713             :  *      Also: return indication to caller whether this specific route
     714             :  *      should be included in the response to the NVE according to
     715             :  *      the following tests:
     716             :  *
     717             :  *      1. If there were prior duplicates of this route in this same
     718             :  *         query response, don't include the route.
     719             :  *
     720             :  * RETURN VALUE:
     721             :  *
     722             :  *      0       OK to include route in response
     723             :  *      !0      do not include route in response
     724             :  */
     725           0 : int rfapiRibPreloadBi(
     726             :         struct agg_node *rfd_rib_node, /* NULL = don't preload or filter */
     727             :         struct prefix *pfx_vn, struct prefix *pfx_un, uint32_t lifetime,
     728             :         struct bgp_path_info *bpi)
     729             : {
     730           0 :         struct rfapi_descriptor *rfd;
     731           0 :         struct skiplist *slRibPt = NULL;
     732           0 :         struct rfapi_info *ori = NULL;
     733           0 :         struct rfapi_rib_key rk;
     734           0 :         struct agg_node *trn;
     735           0 :         afi_t afi;
     736           0 :         const struct prefix *p = agg_node_get_prefix(rfd_rib_node);
     737             : 
     738           0 :         if (!rfd_rib_node)
     739             :                 return 0;
     740             : 
     741           0 :         afi = family2afi(p->family);
     742             : 
     743           0 :         rfd = agg_get_table_info(agg_get_table(rfd_rib_node));
     744             : 
     745           0 :         memset((void *)&rk, 0, sizeof(rk));
     746           0 :         rk.vn = *pfx_vn;
     747           0 :         rk.rd = bpi->extra->vnc.import.rd;
     748             : 
     749             :         /*
     750             :          * If there is an auxiliary IP address (L2 can have it), copy it
     751             :          */
     752           0 :         if (bpi->extra->vnc.import.aux_prefix.family) {
     753           0 :                 rk.aux_prefix = bpi->extra->vnc.import.aux_prefix;
     754             :         }
     755             : 
     756             :         /*
     757             :          * is this route already in NVE's RIB?
     758             :          */
     759           0 :         slRibPt = (struct skiplist *)rfd_rib_node->info;
     760             : 
     761           0 :         if (slRibPt && !skiplist_search(slRibPt, &rk, (void **)&ori)) {
     762             : 
     763           0 :                 if ((ori->rsp_counter == rfd->rsp_counter)
     764           0 :                     && (ori->last_sent_time == rfd->rsp_time)) {
     765             :                         return -1; /* duplicate in this response */
     766             :                 }
     767             : 
     768             :                 /* found: update contents of existing route in RIB */
     769           0 :                 ori->un = *pfx_un;
     770           0 :                 rfapiRibBi2Ri(bpi, ori, lifetime);
     771             :         } else {
     772             :                 /* not found: add new route to RIB */
     773           0 :                 ori = rfapi_info_new();
     774           0 :                 ori->rk = rk;
     775           0 :                 ori->un = *pfx_un;
     776           0 :                 rfapiRibBi2Ri(bpi, ori, lifetime);
     777             : 
     778           0 :                 if (!slRibPt) {
     779           0 :                         slRibPt = skiplist_new(0, rfapi_rib_key_cmp, NULL);
     780           0 :                         rfd_rib_node->info = slRibPt;
     781           0 :                         agg_lock_node(rfd_rib_node);
     782           0 :                         RFAPI_RIB_PREFIX_COUNT_INCR(rfd, rfd->bgp->rfapi);
     783             :                 }
     784           0 :                 skiplist_insert(slRibPt, &ori->rk, ori);
     785             :         }
     786             : 
     787           0 :         ori->last_sent_time = monotime(NULL);
     788             : 
     789             :         /*
     790             :          * poke timer
     791             :          */
     792           0 :         RFAPI_RIB_CHECK_COUNTS(0, 0);
     793           0 :         rfapiRibStartTimer(rfd, ori, rfd_rib_node, 0);
     794           0 :         RFAPI_RIB_CHECK_COUNTS(0, 0);
     795             : 
     796             :         /*
     797             :          * Update last sent time for prefix
     798             :          */
     799           0 :         trn = agg_node_get(rfd->rsp_times[afi], p); /* locks trn */
     800           0 :         trn->info = (void *)(uintptr_t)monotime(NULL);
     801           0 :         if (agg_node_get_lock_count(trn) > 1)
     802           0 :                 agg_unlock_node(trn);
     803             : 
     804             :         return 0;
     805             : }
     806             : 
     807             : /*
     808             :  * Frees rfapi_info items at node
     809             :  *
     810             :  * Adjust 'rib' and 'rib_pending' as follows:
     811             :  *
     812             :  * If rib_pending node->info is 1 (magic value):
     813             :  *      callback: NHL = RIB NHL with lifetime = withdraw_lifetime_value
     814             :  *      RIB = remove all routes at the node
     815             :  *      DONE
     816             :  *
     817             :  * For each item at rib node:
     818             :  *  if not present in pending node, move RIB item to "delete list"
     819             :  *
     820             :  * For each item at pending rib node:
     821             :  *  if present (same vn/un) in rib node with same lifetime & options, drop
     822             :  *      matching item from pending node
     823             :  *
     824             :  * For each remaining item at pending rib node, add or replace item
     825             :  * at rib node.
     826             :  *
     827             :  * Construct NHL as concatenation of pending list + delete list
     828             :  *
     829             :  * Clear pending node
     830             :  */
     831           0 : static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd,
     832             :                                  afi_t afi,
     833             :                                  struct agg_node *pn, /* pending node */
     834             :                                  struct rfapi_next_hop_entry **head,
     835             :                                  struct rfapi_next_hop_entry **tail)
     836             : {
     837           0 :         struct listnode *node = NULL;
     838           0 :         struct listnode *nnode = NULL;
     839           0 :         struct rfapi_info *ri = NULL;    /* happy valgrind */
     840           0 :         struct rfapi_ip_prefix hp = {0}; /* pfx to put in NHE */
     841           0 :         struct agg_node *rn = NULL;
     842           0 :         struct skiplist *slRibPt = NULL; /* rib list */
     843           0 :         struct skiplist *slPendPt = NULL;
     844           0 :         struct list *lPendCost = NULL;
     845           0 :         struct list *delete_list = NULL;
     846           0 :         int printedprefix = 0;
     847           0 :         int rib_node_started_nonempty = 0;
     848           0 :         int sendingsomeroutes = 0;
     849           0 :         const struct prefix *p;
     850             : #if DEBUG_PROCESS_PENDING_NODE
     851             :         unsigned int count_rib_initial = 0;
     852             :         unsigned int count_pend_vn_initial = 0;
     853             :         unsigned int count_pend_cost_initial = 0;
     854             : #endif
     855             : 
     856           0 :         assert(pn);
     857           0 :         p = agg_node_get_prefix(pn);
     858           0 :         vnc_zlog_debug_verbose("%s: afi=%d, %pRN pn->info=%p", __func__, afi,
     859             :                                pn, pn->info);
     860             : 
     861           0 :         if (AFI_L2VPN != afi) {
     862           0 :                 rfapiQprefix2Rprefix(p, &hp);
     863             :         }
     864             : 
     865           0 :         RFAPI_RIB_CHECK_COUNTS(1, 0);
     866             : 
     867             :         /*
     868             :          * Find corresponding RIB node
     869             :          */
     870           0 :         rn = agg_node_get(rfd->rib[afi], p); /* locks rn */
     871             : 
     872             :         /*
     873             :          * RIB skiplist has key=rfapi_addr={vn,un}, val = rfapi_info,
     874             :          * skiplist.del = NULL
     875             :          */
     876           0 :         slRibPt = (struct skiplist *)rn->info;
     877           0 :         if (slRibPt)
     878           0 :                 rib_node_started_nonempty = 1;
     879             : 
     880           0 :         slPendPt = (struct skiplist *)(pn->aggregate);
     881           0 :         lPendCost = (struct list *)(pn->info);
     882             : 
     883             : #if DEBUG_PROCESS_PENDING_NODE
     884             :         /* debugging */
     885             :         if (slRibPt)
     886             :                 count_rib_initial = skiplist_count(slRibPt);
     887             : 
     888             :         if (slPendPt)
     889             :                 count_pend_vn_initial = skiplist_count(slPendPt);
     890             : 
     891             :         if (lPendCost && lPendCost != (struct list *)1)
     892             :                 count_pend_cost_initial = lPendCost->count;
     893             : #endif
     894             : 
     895             : 
     896             :         /*
     897             :          * Handle special case: delete all routes at prefix
     898             :          */
     899           0 :         if (lPendCost == (struct list *)1) {
     900           0 :                 vnc_zlog_debug_verbose("%s: lPendCost=1 => delete all",
     901             :                                        __func__);
     902           0 :                 if (slRibPt && !skiplist_empty(slRibPt)) {
     903           0 :                         delete_list = list_new();
     904           0 :                         while (0
     905           0 :                                == skiplist_first(slRibPt, NULL, (void **)&ri)) {
     906           0 :                                 listnode_add(delete_list, ri);
     907           0 :                                 vnc_zlog_debug_verbose(
     908             :                                         "%s: after listnode_add, delete_list->count=%d",
     909             :                                         __func__, delete_list->count);
     910           0 :                                 rfapiFreeBgpTeaOptionChain(ri->tea_options);
     911           0 :                                 ri->tea_options = NULL;
     912             : 
     913           0 :                                 if (ri->timer) {
     914           0 :                                         struct rfapi_rib_tcb *tcb;
     915             : 
     916           0 :                                         tcb = THREAD_ARG(ri->timer);
     917           0 :                                         THREAD_OFF(ri->timer);
     918           0 :                                         XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
     919             :                                 }
     920             : 
     921           0 :                                 vnc_zlog_debug_verbose(
     922             :                                         "%s:   put dl pfx=%pRN vn=%pFX un=%pFX cost=%d life=%d vn_options=%p",
     923             :                                         __func__, pn, &ri->rk.vn, &ri->un,
     924             :                                         ri->cost, ri->lifetime, ri->vn_options);
     925             : 
     926           0 :                                 skiplist_delete_first(slRibPt);
     927             :                         }
     928             : 
     929           0 :                         assert(skiplist_empty(slRibPt));
     930             : 
     931           0 :                         skiplist_free(slRibPt);
     932           0 :                         rn->info = slRibPt = NULL;
     933           0 :                         agg_unlock_node(rn);
     934             : 
     935           0 :                         lPendCost = pn->info = NULL;
     936           0 :                         agg_unlock_node(pn);
     937             : 
     938           0 :                         goto callback;
     939             :                 }
     940           0 :                 if (slRibPt) {
     941           0 :                         skiplist_free(slRibPt);
     942           0 :                         rn->info = NULL;
     943           0 :                         agg_unlock_node(rn);
     944             :                 }
     945             : 
     946           0 :                 assert(!slPendPt);
     947           0 :                 if (slPendPt) { /* TBD I think we can toss this block */
     948           0 :                         skiplist_free(slPendPt);
     949           0 :                         pn->aggregate = NULL;
     950           0 :                         agg_unlock_node(pn);
     951             :                 }
     952             : 
     953           0 :                 pn->info = NULL;
     954           0 :                 agg_unlock_node(pn);
     955             : 
     956           0 :                 agg_unlock_node(rn); /* agg_node_get() */
     957             : 
     958           0 :                 if (rib_node_started_nonempty) {
     959           0 :                         RFAPI_RIB_PREFIX_COUNT_DECR(rfd, bgp->rfapi);
     960             :                 }
     961             : 
     962           0 :                 RFAPI_RIB_CHECK_COUNTS(1, 0);
     963             : 
     964           0 :                 return;
     965             :         }
     966             : 
     967           0 :         vnc_zlog_debug_verbose("%s:   lPendCost->count=%d, slRibPt->count=%d",
     968             :                                __func__,
     969             :                                (lPendCost ? (int)lPendCost->count : -1),
     970             :                                (slRibPt ? (int)slRibPt->count : -1));
     971             : 
     972             :         /*
     973             :          * Iterate over routes at RIB Node.
     974             :          * If not found at Pending Node, delete from RIB Node and add to
     975             :          * deletelist
     976             :          * If found at Pending Node
     977             :          *      If identical rfapi_info, delete from Pending Node
     978             :          */
     979           0 :         if (slRibPt) {
     980           0 :                 void *cursor = NULL;
     981           0 :                 struct rfapi_info *ori;
     982             : 
     983             :                 /*
     984             :                  * Iterate over RIB List
     985             :                  *
     986             :                  */
     987           0 :                 while (!skiplist_next(slRibPt, NULL, (void **)&ori, &cursor)) {
     988             : 
     989           0 :                         if (skiplist_search(slPendPt, &ori->rk, (void **)&ri)) {
     990             :                                 /*
     991             :                                  * Not in Pending list, so it should be deleted
     992             :                                  */
     993           0 :                                 if (!delete_list)
     994           0 :                                         delete_list = list_new();
     995           0 :                                 listnode_add(delete_list, ori);
     996           0 :                                 rfapiFreeBgpTeaOptionChain(ori->tea_options);
     997           0 :                                 ori->tea_options = NULL;
     998           0 :                                 if (ori->timer) {
     999           0 :                                         struct rfapi_rib_tcb *tcb;
    1000             : 
    1001           0 :                                         tcb = THREAD_ARG(ori->timer);
    1002           0 :                                         THREAD_OFF(ori->timer);
    1003           0 :                                         XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
    1004             :                                 }
    1005             : 
    1006             : #if DEBUG_PROCESS_PENDING_NODE
    1007             :                                 /* deleted from slRibPt below, after we're done
    1008             :                                  * iterating */
    1009             :                                 vnc_zlog_debug_verbose(
    1010             :                                         "%s:   slRibPt ri %p not matched in pending list, delete",
    1011             :                                         __func__, ori);
    1012             : #endif
    1013             : 
    1014             :                         } else {
    1015             :                                 /*
    1016             :                                  * Found in pending list. If same lifetime,
    1017             :                                  * cost, options,
    1018             :                                  * then remove from pending list because the
    1019             :                                  * route
    1020             :                                  * hasn't changed.
    1021             :                                  */
    1022           0 :                                 if (!rfapi_info_cmp(ori, ri)) {
    1023           0 :                                         skiplist_delete(slPendPt, &ri->rk,
    1024             :                                                         NULL);
    1025           0 :                                         assert(lPendCost);
    1026           0 :                                         if (lPendCost) {
    1027             :                                                 /* linear walk: might need
    1028             :                                                  * optimization */
    1029           0 :                                                 listnode_delete(lPendCost,
    1030             :                                                                 ri); /* XXX
    1031             :                                                                         doesn't
    1032             :                                                                         free
    1033             :                                                                         data!
    1034             :                                                                         bug? */
    1035           0 :                                                 rfapi_info_free(
    1036             :                                                         ri); /* grr... */
    1037             :                                         }
    1038             :                                 }
    1039             : #if DEBUG_PROCESS_PENDING_NODE
    1040             :                                 vnc_zlog_debug_verbose(
    1041             :                                         "%s:   slRibPt ri %p matched in pending list, %s",
    1042             :                                         __func__, ori,
    1043             :                                         (same ? "same info"
    1044             :                                               : "different info"));
    1045             : #endif
    1046             :                         }
    1047             :                 }
    1048             :                 /*
    1049             :                  * Go back and delete items from RIB
    1050             :                  */
    1051           0 :                 if (delete_list) {
    1052           0 :                         for (ALL_LIST_ELEMENTS_RO(delete_list, node, ri)) {
    1053           0 :                                 vnc_zlog_debug_verbose(
    1054             :                                         "%s:   deleting ri %p from slRibPt",
    1055             :                                         __func__, ri);
    1056           0 :                                 assert(!skiplist_delete(slRibPt, &ri->rk,
    1057             :                                                         NULL));
    1058             :                         }
    1059           0 :                         if (skiplist_empty(slRibPt)) {
    1060           0 :                                 skiplist_free(slRibPt);
    1061           0 :                                 slRibPt = rn->info = NULL;
    1062           0 :                                 agg_unlock_node(rn);
    1063             :                         }
    1064             :                 }
    1065             :         }
    1066             : 
    1067           0 :         RFAPI_RIB_CHECK_COUNTS(0, (delete_list ? delete_list->count : 0));
    1068             : 
    1069             :         /*
    1070             :          * Iterate over routes at Pending Node
    1071             :          *
    1072             :          * If {vn} found at RIB Node, update RIB Node route contents to match PN
    1073             :          * If {vn} NOT found at RIB Node, add copy to RIB Node
    1074             :          */
    1075           0 :         if (lPendCost) {
    1076           0 :                 for (ALL_LIST_ELEMENTS_RO(lPendCost, node, ri)) {
    1077             : 
    1078           0 :                         struct rfapi_info *ori;
    1079             : 
    1080           0 :                         if (slRibPt
    1081           0 :                             && !skiplist_search(slRibPt, &ri->rk,
    1082             :                                                 (void **)&ori)) {
    1083             : 
    1084             :                                 /* found: update contents of existing route in
    1085             :                                  * RIB */
    1086           0 :                                 ori->un = ri->un;
    1087           0 :                                 ori->cost = ri->cost;
    1088           0 :                                 ori->lifetime = ri->lifetime;
    1089           0 :                                 rfapiFreeBgpTeaOptionChain(ori->tea_options);
    1090           0 :                                 ori->tea_options =
    1091           0 :                                         rfapiOptionsDup(ri->tea_options);
    1092           0 :                                 ori->last_sent_time = monotime(NULL);
    1093             : 
    1094           0 :                                 rfapiFreeRfapiVnOptionChain(ori->vn_options);
    1095           0 :                                 ori->vn_options =
    1096           0 :                                         rfapiVnOptionsDup(ri->vn_options);
    1097             : 
    1098           0 :                                 rfapiFreeRfapiUnOptionChain(ori->un_options);
    1099           0 :                                 ori->un_options =
    1100           0 :                                         rfapiUnOptionsDup(ri->un_options);
    1101             : 
    1102           0 :                                 vnc_zlog_debug_verbose(
    1103             :                                         "%s:   matched lPendCost item %p in slRibPt, rewrote",
    1104             :                                         __func__, ri);
    1105             : 
    1106             :                         } else {
    1107             :                                 /* not found: add new route to RIB */
    1108           0 :                                 ori = rfapi_info_new();
    1109           0 :                                 ori->rk = ri->rk;
    1110           0 :                                 ori->un = ri->un;
    1111           0 :                                 ori->cost = ri->cost;
    1112           0 :                                 ori->lifetime = ri->lifetime;
    1113           0 :                                 ori->tea_options =
    1114           0 :                                         rfapiOptionsDup(ri->tea_options);
    1115           0 :                                 ori->last_sent_time = monotime(NULL);
    1116           0 :                                 ori->vn_options =
    1117           0 :                                         rfapiVnOptionsDup(ri->vn_options);
    1118           0 :                                 ori->un_options =
    1119           0 :                                         rfapiUnOptionsDup(ri->un_options);
    1120             : 
    1121           0 :                                 if (!slRibPt) {
    1122           0 :                                         slRibPt = skiplist_new(
    1123             :                                                 0, rfapi_rib_key_cmp, NULL);
    1124           0 :                                         rn->info = slRibPt;
    1125           0 :                                         agg_lock_node(rn);
    1126             :                                 }
    1127           0 :                                 skiplist_insert(slRibPt, &ori->rk, ori);
    1128             : 
    1129           0 :                                 vnc_zlog_debug_verbose(
    1130             :                                         "%s:   nomatch lPendCost item %p in slRibPt, added (rd=%pRD)",
    1131             :                                         __func__, ri, &ori->rk.rd);
    1132             :                         }
    1133             : 
    1134             :                         /*
    1135             :                          * poke timer
    1136             :                          */
    1137             :                         RFAPI_RIB_CHECK_COUNTS(
    1138           0 :                                 0, (delete_list ? delete_list->count : 0));
    1139           0 :                         rfapiRibStartTimer(rfd, ori, rn, 0);
    1140             :                         RFAPI_RIB_CHECK_COUNTS(
    1141           0 :                                 0, (delete_list ? delete_list->count : 0));
    1142             :                 }
    1143             :         }
    1144             : 
    1145             : 
    1146           0 : callback:
    1147             :         /*
    1148             :          * Construct NHL as concatenation of pending list + delete list
    1149             :          */
    1150             : 
    1151             : 
    1152           0 :         RFAPI_RIB_CHECK_COUNTS(0, (delete_list ? delete_list->count : 0));
    1153             : 
    1154           0 :         if (lPendCost) {
    1155             : 
    1156           0 :                 char buf[BUFSIZ];
    1157           0 :                 char buf2[BUFSIZ];
    1158             : 
    1159           0 :                 vnc_zlog_debug_verbose("%s: lPendCost->count now %d", __func__,
    1160             :                                        lPendCost->count);
    1161           0 :                 vnc_zlog_debug_verbose("%s: For prefix %pRN (a)", __func__, pn);
    1162           0 :                 printedprefix = 1;
    1163             : 
    1164           0 :                 for (ALL_LIST_ELEMENTS(lPendCost, node, nnode, ri)) {
    1165             : 
    1166           0 :                         struct rfapi_next_hop_entry *new;
    1167           0 :                         struct agg_node *trn;
    1168             : 
    1169           0 :                         new = XCALLOC(MTYPE_RFAPI_NEXTHOP,
    1170             :                                       sizeof(struct rfapi_next_hop_entry));
    1171             : 
    1172           0 :                         if (ri->rk.aux_prefix.family) {
    1173           0 :                                 rfapiQprefix2Rprefix(&ri->rk.aux_prefix,
    1174             :                                                      &new->prefix);
    1175             :                         } else {
    1176           0 :                                 new->prefix = hp;
    1177           0 :                                 if (AFI_L2VPN == afi) {
    1178             :                                         /* hp is 0; need to set length to match
    1179             :                                          * AF of vn */
    1180           0 :                                         new->prefix.length =
    1181           0 :                                                 (ri->rk.vn.family == AF_INET)
    1182             :                                                         ? 32
    1183             :                                                         : 128;
    1184             :                                 }
    1185             :                         }
    1186           0 :                         new->prefix.cost = ri->cost;
    1187           0 :                         new->lifetime = ri->lifetime;
    1188           0 :                         rfapiQprefix2Raddr(&ri->rk.vn, &new->vn_address);
    1189           0 :                         rfapiQprefix2Raddr(&ri->un, &new->un_address);
    1190             :                         /* free option chain from ri */
    1191           0 :                         rfapiFreeBgpTeaOptionChain(ri->tea_options);
    1192             : 
    1193           0 :                         ri->tea_options =
    1194             :                                 NULL; /* option chain was transferred to NHL */
    1195             : 
    1196           0 :                         new->vn_options = ri->vn_options;
    1197           0 :                         ri->vn_options =
    1198             :                                 NULL; /* option chain was transferred to NHL */
    1199             : 
    1200           0 :                         new->un_options = ri->un_options;
    1201           0 :                         ri->un_options =
    1202             :                                 NULL; /* option chain was transferred to NHL */
    1203             : 
    1204           0 :                         if (*tail)
    1205           0 :                                 (*tail)->next = new;
    1206           0 :                         *tail = new;
    1207           0 :                         if (!*head) {
    1208           0 :                                 *head = new;
    1209             :                         }
    1210           0 :                         sendingsomeroutes = 1;
    1211             : 
    1212           0 :                         ++rfd->stat_count_nh_reachable;
    1213           0 :                         ++bgp->rfapi->stat.count_updated_response_updates;
    1214             : 
    1215             :                         /*
    1216             :                          * update this NVE's timestamp for this prefix
    1217             :                          */
    1218           0 :                         trn = agg_node_get(rfd->rsp_times[afi],
    1219             :                                            p); /* locks trn */
    1220           0 :                         trn->info = (void *)(uintptr_t)monotime(NULL);
    1221           0 :                         if (agg_node_get_lock_count(trn) > 1)
    1222           0 :                                 agg_unlock_node(trn);
    1223             : 
    1224           0 :                         rfapiRfapiIpAddr2Str(&new->vn_address, buf, BUFSIZ);
    1225           0 :                         rfapiRfapiIpAddr2Str(&new->un_address, buf2, BUFSIZ);
    1226           0 :                         vnc_zlog_debug_verbose(
    1227             :                                 "%s:   add vn=%s un=%s cost=%d life=%d",
    1228             :                                 __func__, buf, buf2, new->prefix.cost,
    1229             :                                 new->lifetime);
    1230             :                 }
    1231             :         }
    1232             : 
    1233           0 :         RFAPI_RIB_CHECK_COUNTS(0, (delete_list ? delete_list->count : 0));
    1234             : 
    1235           0 :         if (delete_list) {
    1236             : 
    1237           0 :                 char buf[BUFSIZ];
    1238           0 :                 char buf2[BUFSIZ];
    1239             : 
    1240           0 :                 if (!printedprefix) {
    1241           0 :                         vnc_zlog_debug_verbose("%s: For prefix %pRN (d)",
    1242             :                                                __func__, pn);
    1243             :                 }
    1244           0 :                 vnc_zlog_debug_verbose("%s: delete_list has %d elements",
    1245             :                                        __func__, delete_list->count);
    1246             : 
    1247           0 :                 RFAPI_RIB_CHECK_COUNTS(0, delete_list->count);
    1248           0 :                 if (!CHECK_FLAG(bgp->rfapi_cfg->flags,
    1249             :                                 BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE)) {
    1250             : 
    1251           0 :                         for (ALL_LIST_ELEMENTS(delete_list, node, nnode, ri)) {
    1252             : 
    1253           0 :                                 struct rfapi_next_hop_entry *new;
    1254           0 :                                 struct rfapi_info *ri_del;
    1255             : 
    1256           0 :                                 RFAPI_RIB_CHECK_COUNTS(0, delete_list->count);
    1257           0 :                                 new = XCALLOC(
    1258             :                                         MTYPE_RFAPI_NEXTHOP,
    1259             :                                         sizeof(struct rfapi_next_hop_entry));
    1260             : 
    1261           0 :                                 if (ri->rk.aux_prefix.family) {
    1262           0 :                                         rfapiQprefix2Rprefix(&ri->rk.aux_prefix,
    1263             :                                                              &new->prefix);
    1264             :                                 } else {
    1265           0 :                                         new->prefix = hp;
    1266           0 :                                         if (AFI_L2VPN == afi) {
    1267             :                                                 /* hp is 0; need to set length
    1268             :                                                  * to match AF of vn */
    1269           0 :                                                 new->prefix.length =
    1270           0 :                                                         (ri->rk.vn.family
    1271             :                                                          == AF_INET)
    1272             :                                                                 ? 32
    1273             :                                                                 : 128;
    1274             :                                         }
    1275             :                                 }
    1276             : 
    1277           0 :                                 new->prefix.cost = ri->cost;
    1278           0 :                                 new->lifetime = RFAPI_REMOVE_RESPONSE_LIFETIME;
    1279           0 :                                 rfapiQprefix2Raddr(&ri->rk.vn,
    1280             :                                                    &new->vn_address);
    1281           0 :                                 rfapiQprefix2Raddr(&ri->un, &new->un_address);
    1282             : 
    1283           0 :                                 new->vn_options = ri->vn_options;
    1284           0 :                                 ri->vn_options = NULL; /* option chain was
    1285             :                                                           transferred to NHL */
    1286             : 
    1287           0 :                                 new->un_options = ri->un_options;
    1288           0 :                                 ri->un_options = NULL; /* option chain was
    1289             :                                                           transferred to NHL */
    1290             : 
    1291           0 :                                 if (*tail)
    1292           0 :                                         (*tail)->next = new;
    1293           0 :                                 *tail = new;
    1294           0 :                                 if (!*head) {
    1295           0 :                                         *head = new;
    1296             :                                 }
    1297           0 :                                 ++rfd->stat_count_nh_removal;
    1298           0 :                                 ++bgp->rfapi->stat
    1299           0 :                                           .count_updated_response_deletes;
    1300             : 
    1301           0 :                                 rfapiRfapiIpAddr2Str(&new->vn_address, buf,
    1302             :                                                      BUFSIZ);
    1303           0 :                                 rfapiRfapiIpAddr2Str(&new->un_address, buf2,
    1304             :                                                      BUFSIZ);
    1305           0 :                                 vnc_zlog_debug_verbose(
    1306             :                                         "%s:   DEL vn=%s un=%s cost=%d life=%d",
    1307             :                                         __func__, buf, buf2, new->prefix.cost,
    1308             :                                         new->lifetime);
    1309             : 
    1310           0 :                                 RFAPI_RIB_CHECK_COUNTS(0, delete_list->count);
    1311             :                                 /*
    1312             :                                  * Update/add to list of recent deletions at
    1313             :                                  * this prefix
    1314             :                                  */
    1315           0 :                                 if (!rn->aggregate) {
    1316           0 :                                         rn->aggregate = skiplist_new(
    1317             :                                                 0, rfapi_rib_key_cmp,
    1318             :                                                 (void (*)(void *))
    1319             :                                                         rfapi_info_free);
    1320           0 :                                         agg_lock_node(rn);
    1321             :                                 }
    1322           0 :                                 RFAPI_RIB_CHECK_COUNTS(0, delete_list->count);
    1323             : 
    1324             :                                 /* sanity check lifetime */
    1325           0 :                                 if (ri->lifetime
    1326             :                                     > RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY)
    1327           0 :                                         ri->lifetime =
    1328             :                                                 RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY;
    1329             : 
    1330           0 :                                 RFAPI_RIB_CHECK_COUNTS(0, delete_list->count);
    1331             :                                 /* cancel normal expire timer */
    1332           0 :                                 if (ri->timer) {
    1333           0 :                                         struct rfapi_rib_tcb *tcb;
    1334             : 
    1335           0 :                                         tcb = THREAD_ARG(ri->timer);
    1336           0 :                                         THREAD_OFF(ri->timer);
    1337           0 :                                         XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
    1338             :                                 }
    1339           0 :                                 RFAPI_RIB_CHECK_COUNTS(0, delete_list->count);
    1340             : 
    1341             :                                 /*
    1342             :                                  * Look in "recently-deleted" list
    1343             :                                  */
    1344           0 :                                 if (skiplist_search(
    1345           0 :                                             (struct skiplist *)(rn->aggregate),
    1346           0 :                                             &ri->rk, (void **)&ri_del)) {
    1347             : 
    1348           0 :                                         int rc;
    1349             : 
    1350             :                                         RFAPI_RIB_CHECK_COUNTS(
    1351           0 :                                                 0, delete_list->count);
    1352             :                                         /*
    1353             :                                          * NOT in "recently-deleted" list
    1354             :                                          */
    1355           0 :                                         list_delete_node(
    1356             :                                                 delete_list,
    1357             :                                                 node); /* does not free ri */
    1358           0 :                                         rc = skiplist_insert(
    1359             :                                                 (struct skiplist
    1360           0 :                                                          *)(rn->aggregate),
    1361           0 :                                                 &ri->rk, ri);
    1362           0 :                                         assert(!rc);
    1363             : 
    1364             :                                         RFAPI_RIB_CHECK_COUNTS(
    1365           0 :                                                 0, delete_list->count);
    1366           0 :                                         rfapiRibStartTimer(rfd, ri, rn, 1);
    1367             :                                         RFAPI_RIB_CHECK_COUNTS(
    1368           0 :                                                 0, delete_list->count);
    1369           0 :                                         ri->last_sent_time = monotime(NULL);
    1370             : #if DEBUG_RIB_SL_RD
    1371             :                                         vnc_zlog_debug_verbose(
    1372             :                                                 "%s: move route to recently deleted list, rd=%pRD",
    1373             :                                                 __func__, &ri->rk.rd);
    1374             : #endif
    1375             : 
    1376             :                                 } else {
    1377             :                                         /*
    1378             :                                          * IN "recently-deleted" list
    1379             :                                          */
    1380             :                                         RFAPI_RIB_CHECK_COUNTS(
    1381           0 :                                                 0, delete_list->count);
    1382           0 :                                         rfapiRibStartTimer(rfd, ri_del, rn, 1);
    1383             :                                         RFAPI_RIB_CHECK_COUNTS(
    1384           0 :                                                 0, delete_list->count);
    1385           0 :                                         ri->last_sent_time = monotime(NULL);
    1386             :                                 }
    1387             :                         }
    1388             :                 } else {
    1389           0 :                         vnc_zlog_debug_verbose(
    1390             :                                 "%s: response removal disabled, omitting removals",
    1391             :                                 __func__);
    1392             :                 }
    1393             : 
    1394           0 :                 delete_list->del = (void (*)(void *))rfapi_info_free;
    1395           0 :                 list_delete(&delete_list);
    1396             :         }
    1397             : 
    1398           0 :         RFAPI_RIB_CHECK_COUNTS(0, 0);
    1399             : 
    1400             :         /*
    1401             :          * Reset pending lists. The final agg_unlock_node() will probably
    1402             :          * cause the pending node to be released.
    1403             :          */
    1404           0 :         if (slPendPt) {
    1405           0 :                 skiplist_free(slPendPt);
    1406           0 :                 pn->aggregate = NULL;
    1407           0 :                 agg_unlock_node(pn);
    1408             :         }
    1409           0 :         if (lPendCost) {
    1410           0 :                 list_delete(&lPendCost);
    1411           0 :                 pn->info = NULL;
    1412           0 :                 agg_unlock_node(pn);
    1413             :         }
    1414           0 :         RFAPI_RIB_CHECK_COUNTS(0, 0);
    1415             : 
    1416           0 :         if (rib_node_started_nonempty) {
    1417           0 :                 if (!rn->info) {
    1418           0 :                         RFAPI_RIB_PREFIX_COUNT_DECR(rfd, bgp->rfapi);
    1419             :                 }
    1420             :         } else {
    1421           0 :                 if (rn->info) {
    1422           0 :                         RFAPI_RIB_PREFIX_COUNT_INCR(rfd, bgp->rfapi);
    1423             :                 }
    1424             :         }
    1425             : 
    1426           0 :         if (sendingsomeroutes)
    1427           0 :                 rfapiMonitorTimersRestart(rfd, p);
    1428             : 
    1429           0 :         agg_unlock_node(rn); /* agg_node_get() */
    1430             : 
    1431           0 :         RFAPI_RIB_CHECK_COUNTS(1, 0);
    1432             : }
    1433             : 
    1434             : /*
    1435             :  * regardless of targets, construct a single callback by doing
    1436             :  * only one traversal of the pending RIB
    1437             :  *
    1438             :  *
    1439             :  * Do callback
    1440             :  *
    1441             :  */
    1442           0 : static void rib_do_callback_onepass(struct rfapi_descriptor *rfd, afi_t afi)
    1443             : {
    1444           0 :         struct bgp *bgp = bgp_get_default();
    1445           0 :         struct rfapi_next_hop_entry *head = NULL;
    1446           0 :         struct rfapi_next_hop_entry *tail = NULL;
    1447           0 :         struct agg_node *rn;
    1448             : 
    1449             : #ifdef DEBUG_L2_EXTRA
    1450             :         vnc_zlog_debug_verbose("%s: rfd=%p, afi=%d", __func__, rfd, afi);
    1451             : #endif
    1452             : 
    1453           0 :         if (!rfd->rib_pending[afi])
    1454           0 :                 return;
    1455             : 
    1456           0 :         assert(bgp->rfapi);
    1457             : 
    1458           0 :         for (rn = agg_route_top(rfd->rib_pending[afi]); rn;
    1459           0 :              rn = agg_route_next(rn)) {
    1460           0 :                 process_pending_node(bgp, rfd, afi, rn, &head, &tail);
    1461             :         }
    1462             : 
    1463           0 :         if (head) {
    1464           0 :                 rfapi_response_cb_t *f;
    1465             : 
    1466             : #if DEBUG_NHL
    1467             :                 vnc_zlog_debug_verbose("%s: response callback NHL follows:",
    1468             :                                        __func__);
    1469             :                 rfapiPrintNhl(NULL, head);
    1470             : #endif
    1471             : 
    1472           0 :                 if (rfd->response_cb)
    1473             :                         f = rfd->response_cb;
    1474             :                 else
    1475           0 :                         f = bgp->rfapi->rfp_methods.response_cb;
    1476             : 
    1477           0 :                 bgp->rfapi->flags |= RFAPI_INCALLBACK;
    1478           0 :                 vnc_zlog_debug_verbose("%s: invoking updated response callback",
    1479             :                                        __func__);
    1480           0 :                 (*f)(head, rfd->cookie);
    1481           0 :                 bgp->rfapi->flags &= ~RFAPI_INCALLBACK;
    1482           0 :                 ++bgp->rfapi->response_updated_count;
    1483             :         }
    1484             : }
    1485             : 
    1486           0 : static wq_item_status rfapiRibDoQueuedCallback(struct work_queue *wq,
    1487             :                                                void *data)
    1488             : {
    1489           0 :         struct rfapi_descriptor *rfd;
    1490           0 :         afi_t afi;
    1491           0 :         uint32_t queued_flag;
    1492             : 
    1493           0 :         RFAPI_RIB_CHECK_COUNTS(1, 0);
    1494             : 
    1495           0 :         rfd = ((struct rfapi_updated_responses_queue *)data)->rfd;
    1496           0 :         afi = ((struct rfapi_updated_responses_queue *)data)->afi;
    1497             : 
    1498             :         /* Make sure the HD wasn't closed after the work item was scheduled */
    1499           0 :         if (rfapi_check(rfd))
    1500             :                 return WQ_SUCCESS;
    1501             : 
    1502           0 :         rib_do_callback_onepass(rfd, afi);
    1503             : 
    1504           0 :         queued_flag = RFAPI_QUEUED_FLAG(afi);
    1505             : 
    1506           0 :         UNSET_FLAG(rfd->flags, queued_flag);
    1507             : 
    1508           0 :         RFAPI_RIB_CHECK_COUNTS(1, 0);
    1509             : 
    1510           0 :         return WQ_SUCCESS;
    1511             : }
    1512             : 
    1513           0 : static void rfapiRibQueueItemDelete(struct work_queue *wq, void *data)
    1514             : {
    1515           0 :         XFREE(MTYPE_RFAPI_UPDATED_RESPONSE_QUEUE, data);
    1516           0 : }
    1517             : 
    1518           0 : static void updated_responses_queue_init(struct rfapi_descriptor *rfd)
    1519             : {
    1520           0 :         if (rfd->updated_responses_queue)
    1521             :                 return;
    1522             : 
    1523           0 :         rfd->updated_responses_queue =
    1524           0 :                 work_queue_new(bm->master, "rfapi updated responses");
    1525           0 :         assert(rfd->updated_responses_queue);
    1526             : 
    1527           0 :         rfd->updated_responses_queue->spec.workfunc = rfapiRibDoQueuedCallback;
    1528           0 :         rfd->updated_responses_queue->spec.del_item_data =
    1529             :                 rfapiRibQueueItemDelete;
    1530           0 :         rfd->updated_responses_queue->spec.max_retries = 0;
    1531           0 :         rfd->updated_responses_queue->spec.hold = 1;
    1532             : }
    1533             : 
    1534             : /*
    1535             :  * Called when an import table node is modified. Construct a
    1536             :  * new complete nexthop list, sorted by cost (lowest first),
    1537             :  * based on the import table node.
    1538             :  *
    1539             :  * Filter out duplicate nexthops (vn address). There should be
    1540             :  * only one UN address per VN address from the point of view of
    1541             :  * a given import table, so we can probably ignore UN addresses
    1542             :  * while filtering.
    1543             :  *
    1544             :  * Based on rfapiNhlAddNodeRoutes()
    1545             :  */
    1546           0 : void rfapiRibUpdatePendingNode(
    1547             :         struct bgp *bgp, struct rfapi_descriptor *rfd,
    1548             :         struct rfapi_import_table *it, /* needed for L2 */
    1549             :         struct agg_node *it_node, uint32_t lifetime)
    1550             : {
    1551           0 :         const struct prefix *prefix;
    1552           0 :         struct bgp_path_info *bpi;
    1553           0 :         struct agg_node *pn;
    1554           0 :         afi_t afi;
    1555           0 :         uint32_t queued_flag;
    1556           0 :         int count = 0;
    1557             : 
    1558           0 :         vnc_zlog_debug_verbose("%s: entry", __func__);
    1559             : 
    1560           0 :         if (CHECK_FLAG(bgp->rfapi_cfg->flags, BGP_VNC_CONFIG_CALLBACK_DISABLE))
    1561             :                 return;
    1562             : 
    1563           0 :         vnc_zlog_debug_verbose("%s: callbacks are not disabled", __func__);
    1564             : 
    1565           0 :         RFAPI_RIB_CHECK_COUNTS(1, 0);
    1566             : 
    1567           0 :         prefix = agg_node_get_prefix(it_node);
    1568           0 :         afi = family2afi(prefix->family);
    1569           0 :         vnc_zlog_debug_verbose("%s: prefix=%pFX", __func__, prefix);
    1570             : 
    1571           0 :         pn = agg_node_get(rfd->rib_pending[afi], prefix);
    1572           0 :         assert(pn);
    1573             : 
    1574           0 :         vnc_zlog_debug_verbose("%s: pn->info=%p, pn->aggregate=%p", __func__,
    1575             :                                pn->info, pn->aggregate);
    1576             : 
    1577           0 :         if (pn->aggregate) {
    1578             :                 /*
    1579             :                  * free references into the rfapi_info structures before
    1580             :                  * freeing the structures themselves
    1581             :                  */
    1582           0 :                 skiplist_free((struct skiplist *)(pn->aggregate));
    1583           0 :                 pn->aggregate = NULL;
    1584           0 :                 agg_unlock_node(pn); /* skiplist deleted */
    1585             :         }
    1586             : 
    1587             : 
    1588             :         /*
    1589             :          * free the rfapi_info structures
    1590             :          */
    1591           0 :         if (pn->info) {
    1592           0 :                 if (pn->info != (void *)1) {
    1593           0 :                         list_delete((struct list **)(&pn->info));
    1594             :                 }
    1595           0 :                 pn->info = NULL;
    1596           0 :                 agg_unlock_node(pn); /* linklist or 1 deleted */
    1597             :         }
    1598             : 
    1599             :         /*
    1600             :          * The BPIs in the import table are already sorted by cost
    1601             :          */
    1602           0 :         for (bpi = it_node->info; bpi; bpi = bpi->next) {
    1603             : 
    1604           0 :                 struct rfapi_info *ri;
    1605           0 :                 struct prefix pfx_nh;
    1606             : 
    1607           0 :                 if (!bpi->extra) {
    1608             :                         /* shouldn't happen */
    1609             :                         /* TBD increment error stats counter */
    1610           0 :                         continue;
    1611             :                 }
    1612             : 
    1613           0 :                 rfapiNexthop2Prefix(bpi->attr, &pfx_nh);
    1614             : 
    1615             :                 /*
    1616             :                  * Omit route if nexthop is self
    1617             :                  */
    1618           0 :                 if (CHECK_FLAG(bgp->rfapi_cfg->flags,
    1619             :                                BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP)) {
    1620             : 
    1621           0 :                         struct prefix pfx_vn;
    1622             : 
    1623           0 :                         assert(!rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx_vn));
    1624           0 :                         if (prefix_same(&pfx_vn, &pfx_nh))
    1625           0 :                                 continue;
    1626             :                 }
    1627             : 
    1628           0 :                 ri = rfapi_info_new();
    1629           0 :                 ri->rk.vn = pfx_nh;
    1630           0 :                 ri->rk.rd = bpi->extra->vnc.import.rd;
    1631             :                 /*
    1632             :                  * If there is an auxiliary IP address (L2 can have it), copy it
    1633             :                  */
    1634           0 :                 if (bpi->extra->vnc.import.aux_prefix.family) {
    1635           0 :                         ri->rk.aux_prefix = bpi->extra->vnc.import.aux_prefix;
    1636             :                 }
    1637             : 
    1638           0 :                 if (rfapiGetUnAddrOfVpnBi(bpi, &ri->un)) {
    1639           0 :                         rfapi_info_free(ri);
    1640           0 :                         continue;
    1641             :                 }
    1642             : 
    1643           0 :                 if (!pn->aggregate) {
    1644           0 :                         pn->aggregate =
    1645           0 :                                 skiplist_new(0, rfapi_rib_key_cmp, NULL);
    1646           0 :                         agg_lock_node(pn);
    1647             :                 }
    1648             : 
    1649             :                 /*
    1650             :                  * If we have already added this nexthop, the insert will fail.
    1651             :                  * Note that the skiplist key is a pointer INTO the rfapi_info
    1652             :                  * structure which will be added to the "info" list.
    1653             :                  * The skiplist entry VALUE is not used for anything but
    1654             :                  * might be useful during debugging.
    1655             :                  */
    1656           0 :                 if (skiplist_insert((struct skiplist *)pn->aggregate, &ri->rk,
    1657             :                                     ri)) {
    1658             : 
    1659             :                         /*
    1660             :                          * duplicate
    1661             :                          */
    1662           0 :                         rfapi_info_free(ri);
    1663           0 :                         continue;
    1664             :                 }
    1665             : 
    1666           0 :                 rfapiRibBi2Ri(bpi, ri, lifetime);
    1667             : 
    1668           0 :                 if (!pn->info) {
    1669           0 :                         pn->info = list_new();
    1670           0 :                         ((struct list *)(pn->info))->del =
    1671             :                                 (void (*)(void *))rfapi_info_free;
    1672           0 :                         agg_lock_node(pn);
    1673             :                 }
    1674             : 
    1675           0 :                 listnode_add((struct list *)(pn->info), ri);
    1676             :         }
    1677             : 
    1678           0 :         if (pn->info) {
    1679           0 :                 count = ((struct list *)(pn->info))->count;
    1680             :         }
    1681             : 
    1682           0 :         if (!count) {
    1683           0 :                 assert(!pn->info);
    1684           0 :                 assert(!pn->aggregate);
    1685           0 :                 pn->info = (void *)1; /* magic value means this node has no
    1686             :                                          routes */
    1687           0 :                 agg_lock_node(pn);
    1688             :         }
    1689             : 
    1690           0 :         agg_unlock_node(pn); /* agg_node_get */
    1691             : 
    1692           0 :         queued_flag = RFAPI_QUEUED_FLAG(afi);
    1693             : 
    1694           0 :         if (!CHECK_FLAG(rfd->flags, queued_flag)) {
    1695             : 
    1696           0 :                 struct rfapi_updated_responses_queue *urq;
    1697             : 
    1698           0 :                 urq = XCALLOC(MTYPE_RFAPI_UPDATED_RESPONSE_QUEUE,
    1699             :                               sizeof(struct rfapi_updated_responses_queue));
    1700           0 :                 if (!rfd->updated_responses_queue)
    1701           0 :                         updated_responses_queue_init(rfd);
    1702             : 
    1703           0 :                 SET_FLAG(rfd->flags, queued_flag);
    1704           0 :                 urq->rfd = rfd;
    1705           0 :                 urq->afi = afi;
    1706           0 :                 work_queue_add(rfd->updated_responses_queue, urq);
    1707             :         }
    1708           0 :         RFAPI_RIB_CHECK_COUNTS(1, 0);
    1709             : }
    1710             : 
    1711           0 : void rfapiRibUpdatePendingNodeSubtree(
    1712             :         struct bgp *bgp, struct rfapi_descriptor *rfd,
    1713             :         struct rfapi_import_table *it, struct agg_node *it_node,
    1714             :         struct agg_node *omit_subtree, /* may be NULL */
    1715             :         uint32_t lifetime)
    1716             : {
    1717             :         /* FIXME: need to find a better way here to work without sticking our
    1718             :          * hands in node->link */
    1719           0 :         if (agg_node_left(it_node)
    1720           0 :             && (agg_node_left(it_node) != omit_subtree)) {
    1721           0 :                 if (agg_node_left(it_node)->info)
    1722           0 :                         rfapiRibUpdatePendingNode(
    1723             :                                 bgp, rfd, it, agg_node_left(it_node), lifetime);
    1724           0 :                 rfapiRibUpdatePendingNodeSubtree(bgp, rfd, it,
    1725             :                                                  agg_node_left(it_node),
    1726             :                                                  omit_subtree, lifetime);
    1727             :         }
    1728             : 
    1729           0 :         if (agg_node_right(it_node)
    1730           0 :             && (agg_node_right(it_node) != omit_subtree)) {
    1731           0 :                 if (agg_node_right(it_node)->info)
    1732           0 :                         rfapiRibUpdatePendingNode(bgp, rfd, it,
    1733             :                                                   agg_node_right(it_node),
    1734             :                                                   lifetime);
    1735           0 :                 rfapiRibUpdatePendingNodeSubtree(bgp, rfd, it,
    1736             :                                                  agg_node_right(it_node),
    1737             :                                                  omit_subtree, lifetime);
    1738             :         }
    1739           0 : }
    1740             : 
    1741             : /*
    1742             :  * RETURN VALUE
    1743             :  *
    1744             :  *      0       allow prefix to be included in response
    1745             :  *      !0      don't allow prefix to be included in response
    1746             :  */
    1747           0 : int rfapiRibFTDFilterRecentPrefix(
    1748             :         struct rfapi_descriptor *rfd,
    1749             :         struct agg_node *it_rn,             /* import table node */
    1750             :         struct prefix *pfx_target_original) /* query target */
    1751             : {
    1752           0 :         struct bgp *bgp = rfd->bgp;
    1753           0 :         const struct prefix *p = agg_node_get_prefix(it_rn);
    1754           0 :         afi_t afi = family2afi(p->family);
    1755           0 :         time_t prefix_time;
    1756           0 :         struct agg_node *trn;
    1757             : 
    1758             :         /*
    1759             :          * Not in FTD mode, so allow prefix
    1760             :          */
    1761           0 :         if (bgp->rfapi_cfg->rfp_cfg.download_type != RFAPI_RFP_DOWNLOAD_FULL)
    1762             :                 return 0;
    1763             : 
    1764             :         /*
    1765             :          * TBD
    1766             :          * This matches behavior of now-obsolete rfapiRibFTDFilterRecent(),
    1767             :          * but we need to decide if that is correct.
    1768             :          */
    1769           0 :         if (p->family == AF_ETHERNET)
    1770             :                 return 0;
    1771             : 
    1772             : #ifdef DEBUG_FTD_FILTER_RECENT
    1773             :         {
    1774             :                 vnc_zlog_debug_verbose("%s: prefix %pFX", __func__,
    1775             :                                        agg_node_get_prefix(it_rn));
    1776             :         }
    1777             : #endif
    1778             : 
    1779             :         /*
    1780             :          * prefix covers target address, so allow prefix
    1781             :          */
    1782           0 :         if (prefix_match(p, pfx_target_original)) {
    1783             : #ifdef DEBUG_FTD_FILTER_RECENT
    1784             :                 vnc_zlog_debug_verbose("%s: prefix covers target, allowed",
    1785             :                                        __func__);
    1786             : #endif
    1787             :                 return 0;
    1788             :         }
    1789             : 
    1790             :         /*
    1791             :          * check this NVE's timestamp for this prefix
    1792             :          */
    1793           0 :         trn = agg_node_get(rfd->rsp_times[afi], p); /* locks trn */
    1794           0 :         prefix_time = (time_t)trn->info;
    1795           0 :         if (agg_node_get_lock_count(trn) > 1)
    1796           0 :                 agg_unlock_node(trn);
    1797             : 
    1798             : #ifdef DEBUG_FTD_FILTER_RECENT
    1799             :         vnc_zlog_debug_verbose("%s: last sent time %lu, last allowed time %lu",
    1800             :                                __func__, prefix_time,
    1801             :                                rfd->ftd_last_allowed_time);
    1802             : #endif
    1803             : 
    1804             :         /*
    1805             :          * haven't sent this prefix, which doesn't cover target address,
    1806             :          * to NVE since ftd_advertisement_interval, so OK to send now.
    1807             :          */
    1808           0 :         if (prefix_time <= rfd->ftd_last_allowed_time)
    1809             :                 return 0;
    1810             : 
    1811             :         return 1;
    1812             : }
    1813             : 
    1814             : /*
    1815             :  * Call when rfapi returns from rfapi_query() so the RIB reflects
    1816             :  * the routes sent to the NVE before the first updated response
    1817             :  *
    1818             :  * Also: remove duplicates from response. Caller should use returned
    1819             :  * value of nexthop chain.
    1820             :  */
    1821             : struct rfapi_next_hop_entry *
    1822           0 : rfapiRibPreload(struct bgp *bgp, struct rfapi_descriptor *rfd,
    1823             :                 struct rfapi_next_hop_entry *response, int use_eth_resolution)
    1824             : {
    1825           0 :         struct rfapi_next_hop_entry *nhp;
    1826           0 :         struct rfapi_next_hop_entry *nhp_next;
    1827           0 :         struct rfapi_next_hop_entry *head = NULL;
    1828           0 :         struct rfapi_next_hop_entry *tail = NULL;
    1829           0 :         time_t new_last_sent_time;
    1830             : 
    1831           0 :         vnc_zlog_debug_verbose("%s: loading response=%p, use_eth_resolution=%d",
    1832             :                                __func__, response, use_eth_resolution);
    1833             : 
    1834           0 :         new_last_sent_time = monotime(NULL);
    1835             : 
    1836           0 :         for (nhp = response; nhp; nhp = nhp_next) {
    1837             : 
    1838           0 :                 struct prefix pfx;
    1839           0 :                 struct rfapi_rib_key rk;
    1840           0 :                 afi_t afi;
    1841           0 :                 struct rfapi_info *ri;
    1842           0 :                 int need_insert;
    1843           0 :                 struct agg_node *rn;
    1844           0 :                 int rib_node_started_nonempty = 0;
    1845           0 :                 struct agg_node *trn;
    1846           0 :                 int allowed = 0;
    1847             : 
    1848             :                 /* save in case we delete nhp */
    1849           0 :                 nhp_next = nhp->next;
    1850             : 
    1851           0 :                 if (nhp->lifetime == RFAPI_REMOVE_RESPONSE_LIFETIME) {
    1852             :                         /*
    1853             :                          * weird, shouldn't happen
    1854             :                          */
    1855           0 :                         vnc_zlog_debug_verbose(
    1856             :                                 "%s: got nhp->lifetime == RFAPI_REMOVE_RESPONSE_LIFETIME",
    1857             :                                 __func__);
    1858           0 :                         continue;
    1859             :                 }
    1860             : 
    1861             : 
    1862           0 :                 if (use_eth_resolution) {
    1863             :                         /* get the prefix of the ethernet address in the L2
    1864             :                          * option */
    1865           0 :                         struct rfapi_l2address_option *pL2o;
    1866           0 :                         struct rfapi_vn_option *vo;
    1867             : 
    1868             :                         /*
    1869             :                          * Look for VN option of type
    1870             :                          * RFAPI_VN_OPTION_TYPE_L2ADDR
    1871             :                          */
    1872           0 :                         for (pL2o = NULL, vo = nhp->vn_options; vo;
    1873           0 :                              vo = vo->next) {
    1874           0 :                                 if (RFAPI_VN_OPTION_TYPE_L2ADDR == vo->type) {
    1875           0 :                                         pL2o = &vo->v.l2addr;
    1876           0 :                                         break;
    1877             :                                 }
    1878             :                         }
    1879             : 
    1880           0 :                         if (!pL2o) {
    1881             :                                 /*
    1882             :                                  * not supposed to happen
    1883             :                                  */
    1884           0 :                                 vnc_zlog_debug_verbose("%s: missing L2 info",
    1885             :                                                        __func__);
    1886           0 :                                 continue;
    1887             :                         }
    1888             : 
    1889           0 :                         afi = AFI_L2VPN;
    1890           0 :                         rfapiL2o2Qprefix(pL2o, &pfx);
    1891             :                 } else {
    1892           0 :                         rfapiRprefix2Qprefix(&nhp->prefix, &pfx);
    1893           0 :                         afi = family2afi(pfx.family);
    1894             :                 }
    1895             : 
    1896             :                 /*
    1897             :                  * TBD for ethernet, rib must know the right way to distinguish
    1898             :                  * duplicate routes
    1899             :                  *
    1900             :                  * Current approach: prefix is key to radix tree; then
    1901             :                  * each prefix has a set of routes with unique VN addrs
    1902             :                  */
    1903             : 
    1904             :                 /*
    1905             :                  * Look up prefix in RIB
    1906             :                  */
    1907           0 :                 rn = agg_node_get(rfd->rib[afi], &pfx); /* locks rn */
    1908             : 
    1909           0 :                 if (rn->info) {
    1910             :                         rib_node_started_nonempty = 1;
    1911             :                 } else {
    1912           0 :                         rn->info = skiplist_new(0, rfapi_rib_key_cmp, NULL);
    1913           0 :                         agg_lock_node(rn);
    1914             :                 }
    1915             : 
    1916             :                 /*
    1917             :                  * Look up route at prefix
    1918             :                  */
    1919           0 :                 need_insert = 0;
    1920           0 :                 memset((void *)&rk, 0, sizeof(rk));
    1921           0 :                 assert(!rfapiRaddr2Qprefix(&nhp->vn_address, &rk.vn));
    1922             : 
    1923           0 :                 if (use_eth_resolution) {
    1924             :                         /* copy what came from aux_prefix to rk.aux_prefix */
    1925           0 :                         rfapiRprefix2Qprefix(&nhp->prefix, &rk.aux_prefix);
    1926           0 :                         if (RFAPI_0_PREFIX(&rk.aux_prefix)
    1927           0 :                             && RFAPI_HOST_PREFIX(&rk.aux_prefix)) {
    1928             :                                 /* mark as "none" if nhp->prefix is 0/32 or
    1929             :                                  * 0/128 */
    1930           0 :                                 rk.aux_prefix.family = AF_UNSPEC;
    1931             :                         }
    1932             :                 }
    1933             : 
    1934             : #if DEBUG_NHL
    1935             :                 {
    1936             :                         char str_aux_prefix[PREFIX_STRLEN];
    1937             : 
    1938             :                         str_aux_prefix[0] = 0;
    1939             : 
    1940             :                         prefix2str(&rk.aux_prefix, str_aux_prefix,
    1941             :                                    sizeof(str_aux_prefix));
    1942             : 
    1943             :                         if (!rk.aux_prefix.family) {
    1944             :                         }
    1945             :                         vnc_zlog_debug_verbose(
    1946             :                                 "%s:   rk.vn=%pFX rk.aux_prefix=%s", __func__,
    1947             :                                 &rk.vn,
    1948             :                                 (rk.aux_prefix.family ? str_aux_prefix : "-"));
    1949             :                 }
    1950             :                 vnc_zlog_debug_verbose(
    1951             :                         "%s: RIB skiplist for this prefix follows", __func__);
    1952             :                 rfapiRibShowRibSl(NULL, agg_node_get_prefix(rn),
    1953             :                                   (struct skiplist *)rn->info);
    1954             : #endif
    1955             : 
    1956             : 
    1957           0 :                 if (!skiplist_search((struct skiplist *)rn->info, &rk,
    1958             :                                      (void **)&ri)) {
    1959             :                         /*
    1960             :                          * Already have this route; make values match
    1961             :                          */
    1962           0 :                         rfapiFreeRfapiUnOptionChain(ri->un_options);
    1963           0 :                         ri->un_options = NULL;
    1964           0 :                         rfapiFreeRfapiVnOptionChain(ri->vn_options);
    1965           0 :                         ri->vn_options = NULL;
    1966             : 
    1967             : #if DEBUG_NHL
    1968             :                         vnc_zlog_debug_verbose("%s: found in RIB", __func__);
    1969             : #endif
    1970             : 
    1971             :                         /*
    1972             :                          * Filter duplicate routes from initial response.
    1973             :                          * Check timestamps to avoid wraparound problems
    1974             :                          */
    1975           0 :                         if ((ri->rsp_counter != rfd->rsp_counter)
    1976           0 :                             || (ri->last_sent_time != new_last_sent_time)) {
    1977             : 
    1978             : #if DEBUG_NHL
    1979             :                                 vnc_zlog_debug_verbose(
    1980             :                                         "%s: allowed due to counter/timestamp diff",
    1981             :                                         __func__);
    1982             : #endif
    1983           0 :                                 allowed = 1;
    1984             :                         }
    1985             : 
    1986             :                 } else {
    1987             : 
    1988             : #if DEBUG_NHL
    1989             :                         vnc_zlog_debug_verbose(
    1990             :                                 "%s: allowed due to not yet in RIB", __func__);
    1991             : #endif
    1992             :                         /* not found: add new route to RIB */
    1993           0 :                         ri = rfapi_info_new();
    1994           0 :                         need_insert = 1;
    1995           0 :                         allowed = 1;
    1996             :                 }
    1997             : 
    1998           0 :                 ri->rk = rk;
    1999           0 :                 assert(!rfapiRaddr2Qprefix(&nhp->un_address, &ri->un));
    2000           0 :                 ri->cost = nhp->prefix.cost;
    2001           0 :                 ri->lifetime = nhp->lifetime;
    2002           0 :                 ri->vn_options = rfapiVnOptionsDup(nhp->vn_options);
    2003           0 :                 ri->rsp_counter = rfd->rsp_counter;
    2004           0 :                 ri->last_sent_time = monotime(NULL);
    2005             : 
    2006           0 :                 if (need_insert) {
    2007           0 :                         int rc;
    2008           0 :                         rc = skiplist_insert((struct skiplist *)rn->info,
    2009           0 :                                              &ri->rk, ri);
    2010           0 :                         assert(!rc);
    2011             :                 }
    2012             : 
    2013           0 :                 if (!rib_node_started_nonempty) {
    2014           0 :                         RFAPI_RIB_PREFIX_COUNT_INCR(rfd, bgp->rfapi);
    2015             :                 }
    2016             : 
    2017           0 :                 RFAPI_RIB_CHECK_COUNTS(0, 0);
    2018           0 :                 rfapiRibStartTimer(rfd, ri, rn, 0);
    2019           0 :                 RFAPI_RIB_CHECK_COUNTS(0, 0);
    2020             : 
    2021           0 :                 agg_unlock_node(rn);
    2022             : 
    2023             :                 /*
    2024             :                  * update this NVE's timestamp for this prefix
    2025             :                  */
    2026           0 :                 trn = agg_node_get(rfd->rsp_times[afi], &pfx); /* locks trn */
    2027           0 :                 trn->info = (void *)(uintptr_t)monotime(NULL);
    2028           0 :                 if (agg_node_get_lock_count(trn) > 1)
    2029           0 :                         agg_unlock_node(trn);
    2030             : 
    2031           0 :                 vnc_zlog_debug_verbose(
    2032             :                         "%s:   added pfx=%pFX nh[vn]=%pFX, cost=%u, lifetime=%u, allowed=%d",
    2033             :                         __func__, &pfx, &rk.vn, nhp->prefix.cost, nhp->lifetime,
    2034             :                         allowed);
    2035             : 
    2036           0 :                 if (allowed) {
    2037           0 :                         if (tail)
    2038           0 :                                 (tail)->next = nhp;
    2039           0 :                         tail = nhp;
    2040           0 :                         if (!head) {
    2041           0 :                                 head = nhp;
    2042             :                         }
    2043             :                 } else {
    2044           0 :                         rfapi_un_options_free(nhp->un_options);
    2045           0 :                         nhp->un_options = NULL;
    2046           0 :                         rfapi_vn_options_free(nhp->vn_options);
    2047           0 :                         nhp->vn_options = NULL;
    2048             : 
    2049           0 :                         XFREE(MTYPE_RFAPI_NEXTHOP, nhp);
    2050             :                 }
    2051             :         }
    2052             : 
    2053           0 :         if (tail)
    2054           0 :                 tail->next = NULL;
    2055           0 :         return head;
    2056             : }
    2057             : 
    2058           0 : void rfapiRibPendingDeleteRoute(struct bgp *bgp, struct rfapi_import_table *it,
    2059             :                                 afi_t afi, struct agg_node *it_node)
    2060             : {
    2061           0 :         struct rfapi_descriptor *rfd;
    2062           0 :         struct listnode *node;
    2063           0 :         const struct prefix *p = agg_node_get_prefix(it_node);
    2064             : 
    2065           0 :         vnc_zlog_debug_verbose("%s: entry, it=%p, afi=%d, it_node=%p, pfx=%pRN",
    2066             :                                __func__, it, afi, it_node, it_node);
    2067             : 
    2068           0 :         if (AFI_L2VPN == afi) {
    2069             :                 /*
    2070             :                  * ethernet import tables are per-LNI and each ethernet monitor
    2071             :                  * identifies the rfd that owns it.
    2072             :                  */
    2073           0 :                 struct rfapi_monitor_eth *m;
    2074           0 :                 struct agg_node *rn;
    2075           0 :                 struct skiplist *sl;
    2076           0 :                 void *cursor;
    2077           0 :                 int rc;
    2078             : 
    2079             :                 /*
    2080             :                  * route-specific monitors
    2081             :                  */
    2082           0 :                 if ((sl = RFAPI_MONITOR_ETH(it_node))) {
    2083             : 
    2084           0 :                         vnc_zlog_debug_verbose(
    2085             :                                 "%s: route-specific skiplist: %p", __func__,
    2086             :                                 sl);
    2087             : 
    2088           0 :                         for (cursor = NULL,
    2089           0 :                             rc = skiplist_next(sl, NULL, (void **)&m, &cursor);
    2090           0 :                              !rc; rc = skiplist_next(sl, NULL, (void **)&m,
    2091             :                                                      &cursor)) {
    2092             : 
    2093             : #if DEBUG_PENDING_DELETE_ROUTE
    2094             :                                 vnc_zlog_debug_verbose("%s: eth monitor rfd=%p",
    2095             :                                                        __func__, m->rfd);
    2096             : #endif
    2097             :                                 /*
    2098             :                                  * If we have already sent a route with this
    2099             :                                  * prefix to this
    2100             :                                  * NVE, it's OK to send an update with the
    2101             :                                  * delete
    2102             :                                  */
    2103           0 :                                 if ((rn = agg_node_lookup(m->rfd->rib[afi],
    2104             :                                                           p))) {
    2105           0 :                                         rfapiRibUpdatePendingNode(
    2106             :                                                 bgp, m->rfd, it, it_node,
    2107           0 :                                                 m->rfd->response_lifetime);
    2108           0 :                                         agg_unlock_node(rn);
    2109             :                                 }
    2110             :                         }
    2111             :                 }
    2112             : 
    2113             :                 /*
    2114             :                  * all-routes/FTD monitors
    2115             :                  */
    2116           0 :                 for (m = it->eth0_queries; m; m = m->next) {
    2117             : #if DEBUG_PENDING_DELETE_ROUTE
    2118             :                         vnc_zlog_debug_verbose("%s: eth0 monitor rfd=%p",
    2119             :                                                __func__, m->rfd);
    2120             : #endif
    2121             :                         /*
    2122             :                          * If we have already sent a route with this prefix to
    2123             :                          * this
    2124             :                          * NVE, it's OK to send an update with the delete
    2125             :                          */
    2126           0 :                         if ((rn = agg_node_lookup(m->rfd->rib[afi], p))) {
    2127           0 :                                 rfapiRibUpdatePendingNode(
    2128             :                                         bgp, m->rfd, it, it_node,
    2129           0 :                                         m->rfd->response_lifetime);
    2130           0 :                                 agg_unlock_node(rn);
    2131             :                         }
    2132             :                 }
    2133             : 
    2134             :         } else {
    2135             :                 /*
    2136             :                  * Find RFDs that reference this import table
    2137             :                  */
    2138           0 :                 for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, node,
    2139             :                                           rfd)) {
    2140             : 
    2141           0 :                         struct agg_node *rn;
    2142             : 
    2143           0 :                         vnc_zlog_debug_verbose(
    2144             :                                 "%s: comparing rfd(%p)->import_table=%p to it=%p",
    2145             :                                 __func__, rfd, rfd->import_table, it);
    2146             : 
    2147           0 :                         if (rfd->import_table != it)
    2148           0 :                                 continue;
    2149             : 
    2150           0 :                         vnc_zlog_debug_verbose("%s: matched rfd %p", __func__,
    2151             :                                                rfd);
    2152             : 
    2153             :                         /*
    2154             :                          * If we have sent a response to this NVE with this
    2155             :                          * prefix
    2156             :                          * previously, we should send an updated response.
    2157             :                          */
    2158           0 :                         if ((rn = agg_node_lookup(rfd->rib[afi], p))) {
    2159           0 :                                 rfapiRibUpdatePendingNode(
    2160             :                                         bgp, rfd, it, it_node,
    2161             :                                         rfd->response_lifetime);
    2162           0 :                                 agg_unlock_node(rn);
    2163             :                         }
    2164             :                 }
    2165             :         }
    2166           0 : }
    2167             : 
    2168           0 : void rfapiRibShowResponsesSummary(void *stream)
    2169             : {
    2170           0 :         int (*fp)(void *, const char *, ...);
    2171           0 :         struct vty *vty;
    2172           0 :         void *out;
    2173           0 :         const char *vty_newline;
    2174           0 :         struct bgp *bgp = bgp_get_default();
    2175             : 
    2176           0 :         int nves = 0;
    2177           0 :         int nves_with_nonempty_ribs = 0;
    2178           0 :         struct rfapi_descriptor *rfd;
    2179           0 :         struct listnode *node;
    2180             : 
    2181           0 :         if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
    2182           0 :                 return;
    2183           0 :         if (!bgp) {
    2184           0 :                 fp(out, "Unable to find default BGP instance\n");
    2185           0 :                 return;
    2186             :         }
    2187             : 
    2188           0 :         fp(out, "%-24s ", "Responses: (Prefixes)");
    2189           0 :         fp(out, "%-8s %-8u ", "Active:", bgp->rfapi->rib_prefix_count_total);
    2190           0 :         fp(out, "%-8s %-8u",
    2191           0 :            "Maximum:", bgp->rfapi->rib_prefix_count_total_max);
    2192           0 :         fp(out, "\n");
    2193             : 
    2194           0 :         fp(out, "%-24s ", "           (Updated)");
    2195           0 :         fp(out, "%-8s %-8u ",
    2196           0 :            "Update:", bgp->rfapi->stat.count_updated_response_updates);
    2197           0 :         fp(out, "%-8s %-8u",
    2198           0 :            "Remove:", bgp->rfapi->stat.count_updated_response_deletes);
    2199           0 :         fp(out, "%-8s %-8u", "Total:",
    2200           0 :            bgp->rfapi->stat.count_updated_response_updates
    2201           0 :                    + bgp->rfapi->stat.count_updated_response_deletes);
    2202           0 :         fp(out, "\n");
    2203             : 
    2204           0 :         fp(out, "%-24s ", "           (NVEs)");
    2205           0 :         for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, node, rfd)) {
    2206           0 :                 ++nves;
    2207           0 :                 if (rfd->rib_prefix_count)
    2208           0 :                         ++nves_with_nonempty_ribs;
    2209             :         }
    2210           0 :         fp(out, "%-8s %-8u ", "Active:", nves_with_nonempty_ribs);
    2211           0 :         fp(out, "%-8s %-8u", "Total:", nves);
    2212           0 :         fp(out, "\n");
    2213             : }
    2214             : 
    2215           0 : void rfapiRibShowResponsesSummaryClear(void)
    2216             : {
    2217           0 :         struct bgp *bgp = bgp_get_default();
    2218             : 
    2219           0 :         bgp->rfapi->rib_prefix_count_total_max =
    2220           0 :                 bgp->rfapi->rib_prefix_count_total;
    2221           0 : }
    2222             : 
    2223           0 : static int print_rib_sl(int (*fp)(void *, const char *, ...), struct vty *vty,
    2224             :                         void *out, struct skiplist *sl, int deleted,
    2225             :                         char *str_pfx, int *printedprefix)
    2226             : {
    2227           0 :         struct rfapi_info *ri;
    2228           0 :         int rc;
    2229           0 :         void *cursor;
    2230           0 :         int routes_displayed = 0;
    2231             : 
    2232           0 :         cursor = NULL;
    2233           0 :         for (rc = skiplist_next(sl, NULL, (void **)&ri, &cursor); !rc;
    2234           0 :              rc = skiplist_next(sl, NULL, (void **)&ri, &cursor)) {
    2235             : 
    2236           0 :                 char str_vn[PREFIX_STRLEN];
    2237           0 :                 char str_un[PREFIX_STRLEN];
    2238           0 :                 char str_lifetime[BUFSIZ];
    2239           0 :                 char str_age[BUFSIZ];
    2240           0 :                 char *p;
    2241             : 
    2242           0 :                 ++routes_displayed;
    2243             : 
    2244           0 :                 prefix2str(&ri->rk.vn, str_vn, sizeof(str_vn));
    2245           0 :                 p = index(str_vn, '/');
    2246           0 :                 if (p)
    2247           0 :                         *p = 0;
    2248             : 
    2249           0 :                 prefix2str(&ri->un, str_un, sizeof(str_un));
    2250           0 :                 p = index(str_un, '/');
    2251           0 :                 if (p)
    2252           0 :                         *p = 0;
    2253             : 
    2254           0 :                 rfapiFormatSeconds(ri->lifetime, str_lifetime, BUFSIZ);
    2255             : #ifdef RFAPI_REGISTRATIONS_REPORT_AGE
    2256             :                 rfapiFormatAge(ri->last_sent_time, str_age, BUFSIZ);
    2257             : #else
    2258             :                 {
    2259           0 :                         time_t now = monotime(NULL);
    2260           0 :                         time_t expire =
    2261           0 :                                 ri->last_sent_time + (time_t)ri->lifetime;
    2262             :                         /* allow for delayed/async removal */
    2263           0 :                         rfapiFormatSeconds((expire > now ? expire - now : 1),
    2264             :                                            str_age, BUFSIZ);
    2265             :                 }
    2266             : #endif
    2267             : 
    2268           0 :                 fp(out, " %c %-20s %-15s %-15s %-4u %-8s %-8s %pRD\n",
    2269           0 :                    deleted ? 'r' : ' ', *printedprefix ? "" : str_pfx, str_vn,
    2270           0 :                    str_un, ri->cost, str_lifetime, str_age, &ri->rk.rd);
    2271             : 
    2272           0 :                 if (!*printedprefix)
    2273           0 :                         *printedprefix = 1;
    2274             :         }
    2275           0 :         return routes_displayed;
    2276             : }
    2277             : 
    2278             : #if DEBUG_NHL
    2279             : /*
    2280             :  * This one is for debugging (set stream to NULL to send output to log)
    2281             :  */
    2282             : static void rfapiRibShowRibSl(void *stream, struct prefix *pfx,
    2283             :                               struct skiplist *sl)
    2284             : {
    2285             :         int (*fp)(void *, const char *, ...);
    2286             :         struct vty *vty;
    2287             :         void *out;
    2288             :         const char *vty_newline;
    2289             : 
    2290             :         int nhs_displayed = 0;
    2291             :         char str_pfx[PREFIX_STRLEN];
    2292             :         int printedprefix = 0;
    2293             : 
    2294             :         if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
    2295             :                 return;
    2296             : 
    2297             :         prefix2str(pfx, str_pfx, sizeof(str_pfx));
    2298             : 
    2299             :         nhs_displayed +=
    2300             :                 print_rib_sl(fp, vty, out, sl, 0, str_pfx, &printedprefix);
    2301             : }
    2302             : #endif
    2303             : 
    2304           0 : void rfapiRibShowResponses(void *stream, struct prefix *pfx_match,
    2305             :                            int show_removed)
    2306             : {
    2307           0 :         int (*fp)(void *, const char *, ...);
    2308           0 :         struct vty *vty;
    2309           0 :         void *out;
    2310           0 :         const char *vty_newline;
    2311             : 
    2312           0 :         struct rfapi_descriptor *rfd;
    2313           0 :         struct listnode *node;
    2314             : 
    2315           0 :         struct bgp *bgp = bgp_get_default();
    2316           0 :         int printedheader = 0;
    2317           0 :         int routes_total = 0;
    2318           0 :         int nhs_total = 0;
    2319           0 :         int prefixes_total = 0;
    2320           0 :         int prefixes_displayed = 0;
    2321           0 :         int nves_total = 0;
    2322           0 :         int nves_with_routes = 0;
    2323           0 :         int nves_displayed = 0;
    2324           0 :         int routes_displayed = 0;
    2325           0 :         int nhs_displayed = 0;
    2326             : 
    2327           0 :         if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
    2328           0 :                 return;
    2329           0 :         if (!bgp) {
    2330           0 :                 fp(out, "Unable to find default BGP instance\n");
    2331           0 :                 return;
    2332             :         }
    2333             : 
    2334             :         /*
    2335             :          * loop over NVEs
    2336             :          */
    2337           0 :         for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, node, rfd)) {
    2338             : 
    2339           0 :                 int printednve = 0;
    2340             :                 afi_t afi;
    2341             : 
    2342           0 :                 ++nves_total;
    2343             :                 if (rfd->rib_prefix_count)
    2344             :                         ++nves_with_routes;
    2345             : 
    2346           0 :                 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
    2347             : 
    2348           0 :                         struct agg_node *rn;
    2349             : 
    2350           0 :                         if (!rfd->rib[afi])
    2351           0 :                                 continue;
    2352             : 
    2353           0 :                         for (rn = agg_route_top(rfd->rib[afi]); rn;
    2354           0 :                              rn = agg_route_next(rn)) {
    2355           0 :                                 const struct prefix *p =
    2356           0 :                                         agg_node_get_prefix(rn);
    2357           0 :                                 struct skiplist *sl;
    2358           0 :                                 char str_pfx[PREFIX_STRLEN];
    2359           0 :                                 int printedprefix = 0;
    2360             : 
    2361           0 :                                 if (!show_removed)
    2362           0 :                                         sl = rn->info;
    2363             :                                 else
    2364           0 :                                         sl = rn->aggregate;
    2365             : 
    2366           0 :                                 if (!sl)
    2367           0 :                                         continue;
    2368             : 
    2369           0 :                                 routes_total++;
    2370           0 :                                 nhs_total += skiplist_count(sl);
    2371           0 :                                 ++prefixes_total;
    2372             : 
    2373           0 :                                 if (pfx_match && !prefix_match(pfx_match, p)
    2374           0 :                                     && !prefix_match(p, pfx_match))
    2375           0 :                                         continue;
    2376             : 
    2377           0 :                                 ++prefixes_displayed;
    2378             : 
    2379           0 :                                 if (!printedheader) {
    2380           0 :                                         ++printedheader;
    2381             : 
    2382           0 :                                         fp(out, "\n[%s]\n",
    2383             :                                            show_removed ? "Removed" : "Active");
    2384           0 :                                         fp(out, "%-15s %-15s\n", "Querying VN",
    2385             :                                            "Querying UN");
    2386           0 :                                         fp(out,
    2387             :                                            "   %-20s %-15s %-15s %4s %-8s %-8s\n",
    2388             :                                            "Prefix", "Registered VN",
    2389             :                                            "Registered UN", "Cost", "Lifetime",
    2390             : #ifdef RFAPI_REGISTRATIONS_REPORT_AGE
    2391             :                                            "Age"
    2392             : #else
    2393             :                                            "Remaining"
    2394             : #endif
    2395             :                                         );
    2396             :                                 }
    2397           0 :                                 if (!printednve) {
    2398           0 :                                         char str_vn[BUFSIZ];
    2399           0 :                                         char str_un[BUFSIZ];
    2400             : 
    2401           0 :                                         ++printednve;
    2402           0 :                                         ++nves_displayed;
    2403             : 
    2404           0 :                                         fp(out, "%-15s %-15s\n",
    2405             :                                            rfapiRfapiIpAddr2Str(&rfd->vn_addr,
    2406             :                                                                 str_vn, BUFSIZ),
    2407             :                                            rfapiRfapiIpAddr2Str(&rfd->un_addr,
    2408             :                                                                 str_un,
    2409             :                                                                 BUFSIZ));
    2410             :                                 }
    2411           0 :                                 prefix2str(p, str_pfx, sizeof(str_pfx));
    2412             :                                 // fp(out, "  %s\n", buf);  /* prefix */
    2413             : 
    2414           0 :                                 routes_displayed++;
    2415           0 :                                 nhs_displayed += print_rib_sl(
    2416             :                                         fp, vty, out, sl, show_removed, str_pfx,
    2417             :                                         &printedprefix);
    2418             :                         }
    2419             :                 }
    2420             :         }
    2421             : 
    2422           0 :         if (routes_total) {
    2423           0 :                 fp(out, "\n");
    2424           0 :                 fp(out, "Displayed %u NVEs, and %u out of %u %s prefixes",
    2425             :                    nves_displayed, routes_displayed, routes_total,
    2426             :                    show_removed ? "removed" : "active");
    2427           0 :                 if (nhs_displayed != routes_displayed
    2428           0 :                     || nhs_total != routes_total)
    2429           0 :                         fp(out, " with %u out of %u next hops", nhs_displayed,
    2430             :                            nhs_total);
    2431           0 :                 fp(out, "\n");
    2432             :         }
    2433             : }

Generated by: LCOV version v1.16-topotato