back to topotato report
topotato coverage report
Current view: top level - bgpd/rfapi - vnc_import_bgp.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 62 1176 5.3 %
Date: 2023-02-24 14:41:08 Functions: 6 31 19.4 %

          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:        vnc_import_bgp.c
      23             :  * Purpose:     Import routes from BGP unicast directly (not via zebra)
      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/log.h"
      31             : #include "lib/memory.h"
      32             : #include "lib/linklist.h"
      33             : #include "lib/plist.h"
      34             : #include "lib/routemap.h"
      35             : #include "lib/lib_errors.h"
      36             : 
      37             : #include "bgpd/bgpd.h"
      38             : #include "bgpd/bgp_ecommunity.h"
      39             : #include "bgpd/bgp_attr.h"
      40             : #include "bgpd/bgp_route.h"
      41             : #include "bgpd/bgp_mplsvpn.h" /* for RD_TYPE_IP */
      42             : 
      43             : #include "bgpd/rfapi/vnc_export_bgp.h"
      44             : #include "bgpd/rfapi/bgp_rfapi_cfg.h"
      45             : #include "bgpd/rfapi/rfapi.h"
      46             : #include "bgpd/rfapi/rfapi_import.h"
      47             : #include "bgpd/rfapi/rfapi_private.h"
      48             : #include "bgpd/rfapi/rfapi_monitor.h"
      49             : #include "bgpd/rfapi/rfapi_vty.h"
      50             : #include "bgpd/rfapi/vnc_import_bgp.h"
      51             : #include "bgpd/rfapi/vnc_import_bgp_p.h"
      52             : #include "bgpd/rfapi/vnc_debug.h"
      53             : 
      54             : #define ENABLE_VNC_RHNCK
      55             : 
      56             : #define DEBUG_RHN_LIST  0
      57             : 
      58             : static struct rfapi_descriptor vncHDBgpDirect;  /* dummy nve descriptor */
      59             : static struct rfapi_descriptor vncHDResolveNve; /* dummy nve descriptor */
      60             : 
      61             : /*
      62             :  * For routes from another AS:
      63             :  *
      64             :  * If MED is set,
      65             :  *      LOCAL_PREF = 255 - MIN(255, MED)
      66             :  * else
      67             :  *      LOCAL_PREF = default_local_pref
      68             :  *
      69             :  * For routes from the same AS:
      70             :  *
      71             :  *      LOCAL_PREF unchanged
      72             :  */
      73           0 : uint32_t calc_local_pref(struct attr *attr, struct peer *peer)
      74             : {
      75           0 :         uint32_t local_pref = 0;
      76             : 
      77           0 :         if (!attr) {
      78           0 :                 if (peer) {
      79           0 :                         return peer->bgp->default_local_pref;
      80             :                 }
      81           0 :                 return bgp_get_default()->default_local_pref;
      82             :         }
      83             : 
      84           0 :         if (peer && (peer->as != peer->bgp->as)) {
      85           0 :                 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
      86           0 :                         if (attr->med > 255) {
      87             :                                 local_pref = 0;
      88             :                         } else {
      89           0 :                                 local_pref = 255 - attr->med;
      90             :                         }
      91             :                 } else {
      92           0 :                         local_pref = peer->bgp->default_local_pref;
      93             :                 }
      94             :         } else {
      95           0 :                 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
      96           0 :                         local_pref = attr->local_pref;
      97             :                 } else {
      98           0 :                         if (peer && peer->bgp) {
      99           0 :                                 local_pref = peer->bgp->default_local_pref;
     100             :                         }
     101             :                 }
     102             :         }
     103             : 
     104             :         return local_pref;
     105             : }
     106             : 
     107           0 : static int is_host_prefix(const struct prefix *p)
     108             : {
     109           0 :         switch (p->family) {
     110           0 :         case AF_INET:
     111           0 :                 return (p->prefixlen == IPV4_MAX_BITLEN);
     112           0 :         case AF_INET6:
     113           0 :                 return (p->prefixlen == IPV6_MAX_BITLEN);
     114             :         }
     115             :         return 0;
     116             : }
     117             : 
     118             : /***********************************************************************
     119             :  *                              RHN list
     120             :  ***********************************************************************/
     121             : 
     122             : struct prefix_bag {
     123             :         struct prefix hpfx;   /* ce address = unicast nexthop */
     124             :         struct prefix upfx;   /* unicast prefix */
     125             :         struct bgp_path_info *ubpi; /* unicast route */
     126             : };
     127             : 
     128             : static const uint8_t maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
     129             :                                   0xf8, 0xfc, 0xfe, 0xff};
     130             : 
     131           0 : int vnc_prefix_cmp(const void *pfx1, const void *pfx2)
     132             : {
     133           0 :         int offset;
     134           0 :         int shift;
     135           0 :         uint8_t mask;
     136             : 
     137           0 :         const struct prefix *p1 = pfx1;
     138           0 :         const struct prefix *p2 = pfx2;
     139             : 
     140           0 :         if (p1->family < p2->family)
     141             :                 return -1;
     142           0 :         if (p1->family > p2->family)
     143             :                 return 1;
     144             : 
     145           0 :         if (p1->prefixlen < p2->prefixlen)
     146             :                 return -1;
     147           0 :         if (p1->prefixlen > p2->prefixlen)
     148             :                 return 1;
     149             : 
     150           0 :         offset = p1->prefixlen / 8;
     151           0 :         shift = p1->prefixlen % 8;
     152           0 :         if (shift == 0 && offset) { /* catch aligned case */
     153           0 :                 offset--;
     154           0 :                 shift = 8;
     155             :         }
     156             : 
     157             :         /* Set both prefix's head pointer. */
     158           0 :         const uint8_t *pp1 = (const uint8_t *)&p1->u.prefix;
     159           0 :         const uint8_t *pp2 = (const uint8_t *)&p2->u.prefix;
     160             : 
     161           0 :         while (offset--) {
     162           0 :                 if (*pp1 < *pp2)
     163             :                         return -1;
     164           0 :                 if (*pp1 > *pp2)
     165             :                         return 1;
     166           0 :                 ++pp1;
     167           0 :                 ++pp2;
     168             :         }
     169             : 
     170           0 :         mask = maskbit[shift];
     171           0 :         if ((*pp1 & mask) < (*pp2 & mask))
     172             :                 return -1;
     173           0 :         if ((*pp1 & mask) > (*pp2 & mask))
     174           0 :                 return 1;
     175             : 
     176             :         return 0;
     177             : }
     178             : 
     179           0 : static void prefix_bag_free(void *pb)
     180             : {
     181           0 :         XFREE(MTYPE_RFAPI_PREFIX_BAG, pb);
     182           0 : }
     183             : 
     184             : #if DEBUG_RHN_LIST
     185             : static void print_rhn_list(const char *tag1, const char *tag2)
     186             : {
     187             :         struct bgp *bgp;
     188             :         struct skiplist *sl;
     189             :         struct skiplistnode *p;
     190             :         struct prefix_bag *pb;
     191             :         int count = 0;
     192             : 
     193             :         bgp = bgp_get_default();
     194             :         if (!bgp)
     195             :                 return;
     196             : 
     197             :         sl = bgp->frapi->resolve_nve_nexthop;
     198             :         if (!sl) {
     199             :                 vnc_zlog_debug_verbose("%s: %s: RHN List is empty",
     200             :                                        (tag1 ? tag1 : ""), (tag2 ? tag2 : ""));
     201             :                 return;
     202             :         }
     203             : 
     204             :         vnc_zlog_debug_verbose("%s: %s: RHN list:", (tag1 ? tag1 : ""),
     205             :                                (tag2 ? tag2 : ""));
     206             : 
     207             :         /* XXX uses secret knowledge of skiplist structure */
     208             :         for (p = sl->header->forward[0]; p; p = p->forward[0]) {
     209             :                 pb = p->value;
     210             : 
     211             :                 vnc_zlog_debug_verbose(
     212             :                         "RHN Entry %d (q=%p): kpfx=%pFX, upfx=%pFX, hpfx=%pFX, ubpi=%p",
     213             :                         ++count, p, p->key, &pb->upfx, &pb->hpfx, pb->ubpi);
     214             :         }
     215             : }
     216             : #endif
     217             : 
     218             : #ifdef ENABLE_VNC_RHNCK
     219          83 : static void vnc_rhnck(char *tag)
     220             : {
     221          83 :         struct bgp *bgp;
     222          83 :         struct skiplist *sl;
     223          83 :         struct skiplistnode *p;
     224             : 
     225          83 :         bgp = bgp_get_default();
     226          83 :         if (!bgp)
     227             :                 return;
     228          83 :         sl = bgp->rfapi->resolve_nve_nexthop;
     229             : 
     230          83 :         if (!sl)
     231             :                 return;
     232             : 
     233             :         /* XXX uses secret knowledge of skiplist structure */
     234           0 :         for (p = sl->header->forward[0]; p; p = p->forward[0]) {
     235           0 :                 struct prefix_bag *pb;
     236           0 :                 struct prefix *pkey;
     237           0 :                 afi_t afi;
     238           0 :                 struct prefix pfx_orig_nexthop;
     239             : 
     240           0 :                 memset(&pfx_orig_nexthop, 0,
     241             :                        sizeof(pfx_orig_nexthop)); /* keep valgrind happy */
     242             : 
     243           0 :                 pkey = p->key;
     244           0 :                 pb = p->value;
     245             : 
     246           0 :                 afi = family2afi(pb->upfx.family);
     247             : 
     248           0 :                 rfapiUnicastNexthop2Prefix(afi, pb->ubpi->attr,
     249             :                                            &pfx_orig_nexthop);
     250             : 
     251             :                 /* pb->hpfx, pb->ubpi nexthop, pkey should all reflect the same
     252             :                  * pfx */
     253           0 :                 assert(!vnc_prefix_cmp(&pb->hpfx, pkey));
     254           0 :                 if (vnc_prefix_cmp(&pb->hpfx, &pfx_orig_nexthop)) {
     255           0 :                         vnc_zlog_debug_verbose(
     256             :                                 "%s: %s: FATAL: resolve_nve_nexthop list item bpi nexthop %pFX != nve pfx %pFX",
     257             :                                 __func__, tag, &pfx_orig_nexthop, &pb->hpfx);
     258           0 :                         assert(0);
     259             :                 }
     260             :         }
     261           0 :         vnc_zlog_debug_verbose("%s: vnc_rhnck OK", tag);
     262             : }
     263             : 
     264             : #define VNC_RHNCK(n)                                                           \
     265             :         do {                                                                   \
     266             :                 char buf[BUFSIZ];                                              \
     267             :                 snprintf(buf, sizeof(buf), "%s: %s", __func__, #n);            \
     268             :                 vnc_rhnck(buf);                                                \
     269             :         } while (0)
     270             : 
     271             : #else
     272             : 
     273             : #define VNC_RHNCK(n)
     274             : 
     275             : #endif
     276             : 
     277             : /***********************************************************************
     278             :  *                      Add/Delete Unicast Route
     279             :  ***********************************************************************/
     280             : 
     281             : /*
     282             :  * "Adding a Route" import process
     283             :  */
     284             : 
     285             : /*
     286             :  * extract and package information from the BGP unicast route.
     287             :  * Return code 0 means OK, non-0 means drop.
     288             :  *
     289             :  * If return code is 0, caller MUST release ecom
     290             :  */
     291           0 : static int process_unicast_route(struct bgp *bgp,                /* in */
     292             :                                  afi_t afi,                      /* in */
     293             :                                  const struct prefix *prefix,    /* in */
     294             :                                  struct bgp_path_info *info,     /* in */
     295             :                                  struct ecommunity **ecom,       /* OUT */
     296             :                                  struct prefix *unicast_nexthop) /* OUT */
     297             : {
     298           0 :         struct rfapi_cfg *hc = bgp->rfapi_cfg;
     299           0 :         struct peer *peer = info->peer;
     300           0 :         struct attr *attr = info->attr;
     301           0 :         struct attr hattr;
     302           0 :         struct route_map *rmap = NULL;
     303           0 :         struct prefix pfx_orig_nexthop;
     304             : 
     305           0 :         memset(&pfx_orig_nexthop, 0,
     306             :                sizeof(pfx_orig_nexthop)); /* keep valgrind happy */
     307             : 
     308             :         /*
     309             :          * prefix list check
     310             :          */
     311           0 :         if (hc->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi]) {
     312           0 :                 vnc_zlog_debug_verbose("%s: HC prefix list is set, checking",
     313             :                                        __func__);
     314           0 :                 if (prefix_list_apply(
     315             :                             hc->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi],
     316             :                             prefix)
     317             :                     == PREFIX_DENY) {
     318           0 :                         vnc_zlog_debug_verbose(
     319             :                                 "%s: prefix list returns DENY, blocking route",
     320             :                                 __func__);
     321           0 :                         return -1;
     322             :                 }
     323           0 :                 vnc_zlog_debug_verbose(
     324             :                         "%s: prefix list returns PASS, allowing route",
     325             :                         __func__);
     326             :         }
     327             : 
     328             :         /* apply routemap, if any, later */
     329           0 :         rmap = hc->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT];
     330             : 
     331             :         /*
     332             :          * Extract original nexthop, which we expect to be a NVE connected
     333             :          * router
     334             :          * Note that this is the nexthop before any possible application of
     335             :          * policy
     336             :          */
     337             :         /*
     338             :          * Incoming prefix is unicast. If v6, it is in multiprotocol area,
     339             :          * but if v4 it is in attr->nexthop
     340             :          */
     341           0 :         rfapiUnicastNexthop2Prefix(afi, attr, &pfx_orig_nexthop);
     342             : 
     343             :         /*
     344             :          * route map handling
     345             :          * This code is here because it allocates an interned attr which
     346             :          * must be freed before we return. It's easier to put it after
     347             :          * all of the possible returns above.
     348             :          */
     349           0 :         memset(&hattr, 0, sizeof(hattr));
     350             :         /* hattr becomes a ghost attr */
     351           0 :         hattr = *attr;
     352             : 
     353           0 :         if (rmap) {
     354           0 :                 struct bgp_path_info info;
     355           0 :                 route_map_result_t ret;
     356             : 
     357           0 :                 memset(&info, 0, sizeof(info));
     358           0 :                 info.peer = peer;
     359           0 :                 info.attr = &hattr;
     360           0 :                 ret = route_map_apply(rmap, prefix, &info);
     361           0 :                 if (ret == RMAP_DENYMATCH) {
     362           0 :                         bgp_attr_flush(&hattr);
     363           0 :                         vnc_zlog_debug_verbose(
     364             :                                 "%s: route map \"%s\" says DENY, returning",
     365             :                                 __func__, rmap->name);
     366           0 :                         return -1;
     367             :                 }
     368             :         }
     369             : 
     370             :         /*
     371             :          * Get the (possibly altered by policy) unicast nexthop
     372             :          * for later lookup in the Import Table by caller
     373             :          */
     374           0 :         rfapiUnicastNexthop2Prefix(afi, &hattr, unicast_nexthop);
     375             : 
     376           0 :         if (bgp_attr_get_ecommunity(&hattr))
     377           0 :                 *ecom = ecommunity_dup(bgp_attr_get_ecommunity(&hattr));
     378             :         else
     379           0 :                 *ecom = ecommunity_new();
     380             : 
     381             :         /*
     382             :          * Done with hattr, clean up
     383             :          */
     384           0 :         bgp_attr_flush(&hattr);
     385             : 
     386             :         /*
     387             :          * Add EC that carries original NH of iBGP route (2 bytes = magic
     388             :          * value indicating it came from an VNC gateway; default 5226, but
     389             :          * must be user configurable). Note that this is the nexthop before
     390             :          * any application of policy.
     391             :          */
     392             :         {
     393           0 :                 struct ecommunity_val vnc_gateway_magic;
     394           0 :                 uint16_t localadmin;
     395             : 
     396             :                 /* Using route origin extended community type */
     397           0 :                 memset(&vnc_gateway_magic, 0, sizeof(vnc_gateway_magic));
     398           0 :                 vnc_gateway_magic.val[0] = 0x01;
     399           0 :                 vnc_gateway_magic.val[1] = 0x03;
     400             : 
     401             :                 /* Only works for IPv4 nexthops */
     402           0 :                 if (prefix->family == AF_INET) {
     403           0 :                         memcpy(vnc_gateway_magic.val + 2,
     404             :                                &unicast_nexthop->u.prefix4, 4);
     405             :                 }
     406           0 :                 localadmin = htons(hc->resolve_nve_roo_local_admin);
     407           0 :                 memcpy(vnc_gateway_magic.val + 6, (char *)&localadmin, 2);
     408             : 
     409           0 :                 ecommunity_add_val(*ecom, &vnc_gateway_magic, false, false);
     410             :         }
     411             : 
     412           0 :         return 0;
     413             : }
     414             : 
     415             : 
     416           0 : static void vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
     417             :         struct bgp *bgp, afi_t afi, struct bgp_path_info *bpi, /* VPN bpi */
     418             :         struct prefix_rd *prd,                                 /* RD */
     419             :         const struct prefix *prefix, /* unicast route prefix */
     420             :         uint32_t *local_pref,        /* NULL = no local_pref */
     421             :         uint32_t *med,               /* NULL = no med */
     422             :         struct ecommunity *ecom)     /* generated ecoms */
     423             : {
     424           0 :         struct prefix un;
     425           0 :         struct prefix nexthop;
     426           0 :         struct rfapi_ip_addr nexthop_h;
     427           0 :         uint32_t lifetime;
     428           0 :         uint32_t *plifetime;
     429           0 :         struct bgp_attr_encap_subtlv *encaptlvs;
     430           0 :         uint32_t label = 0;
     431             : 
     432           0 :         struct rfapi_un_option optary[3];
     433           0 :         struct rfapi_un_option *opt = NULL;
     434           0 :         int cur_opt = 0;
     435             : 
     436           0 :         vnc_zlog_debug_verbose("%s: entry", __func__);
     437             : 
     438           0 :         if (bpi->type != ZEBRA_ROUTE_BGP
     439           0 :             && bpi->type != ZEBRA_ROUTE_BGP_DIRECT) {
     440             : 
     441           0 :                 return;
     442             :         }
     443           0 :         if (bpi->sub_type != BGP_ROUTE_NORMAL
     444             :             && bpi->sub_type != BGP_ROUTE_STATIC
     445           0 :             && bpi->sub_type != BGP_ROUTE_RFP) {
     446             : 
     447             :                 return;
     448             :         }
     449           0 :         if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
     450             :                 return;
     451             : 
     452           0 :         vncHDResolveNve.peer = bpi->peer;
     453           0 :         if (!rfapiGetVncTunnelUnAddr(bpi->attr, &un)) {
     454           0 :                 if (rfapiQprefix2Raddr(&un, &vncHDResolveNve.un_addr))
     455             :                         return;
     456             :         } else {
     457           0 :                 memset(&vncHDResolveNve.un_addr, 0,
     458             :                        sizeof(vncHDResolveNve.un_addr));
     459             :         }
     460             : 
     461             :         /* Use nexthop of VPN route as nexthop of constructed route */
     462           0 :         rfapiNexthop2Prefix(bpi->attr, &nexthop);
     463           0 :         rfapiQprefix2Raddr(&nexthop, &nexthop_h);
     464             : 
     465           0 :         if (rfapiGetVncLifetime(bpi->attr, &lifetime)) {
     466             :                 plifetime = NULL;
     467             :         } else {
     468           0 :                 plifetime = &lifetime;
     469             :         }
     470             : 
     471           0 :         encaptlvs = bgp_attr_get_vnc_subtlvs(bpi->attr);
     472           0 :         if (bpi->attr->encap_tunneltype != BGP_ENCAP_TYPE_RESERVED
     473           0 :             && bpi->attr->encap_tunneltype != BGP_ENCAP_TYPE_MPLS) {
     474           0 :                 opt = &optary[cur_opt++];
     475           0 :                 memset(opt, 0, sizeof(struct rfapi_un_option));
     476           0 :                 opt->type = RFAPI_UN_OPTION_TYPE_TUNNELTYPE;
     477           0 :                 opt->v.tunnel.type = bpi->attr->encap_tunneltype;
     478             :                 /* TBD parse bpi->attr->extra->encap_subtlvs */
     479             :         }
     480             : 
     481           0 :         struct ecommunity *new_ecom = ecommunity_dup(ecom);
     482             : 
     483           0 :         if (bgp_attr_get_ecommunity(bpi->attr))
     484           0 :                 ecommunity_merge(new_ecom, bgp_attr_get_ecommunity(bpi->attr));
     485             : 
     486           0 :         if (bpi->extra)
     487           0 :                 label = decode_label(&bpi->extra->label[0]);
     488             : 
     489           0 :         add_vnc_route(&vncHDResolveNve, bgp, SAFI_MPLS_VPN,
     490             :                       prefix,     /* unicast route prefix */
     491             :                       prd, &nexthop_h, /* new nexthop */
     492             :                       local_pref, plifetime,
     493             :                       (struct bgp_tea_options *)encaptlvs, /* RFP options */
     494             :                       opt, NULL, new_ecom, med, /* NULL => don't set med */
     495           0 :                       (label ? &label : NULL),  /* NULL= default */
     496             :                       ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE,
     497             :                       RFAPI_AHR_RFPOPT_IS_VNCTLV); /* flags */
     498             : 
     499           0 :         ecommunity_free(&new_ecom);
     500             : }
     501             : 
     502           0 : static void vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
     503             :         struct prefix_rd *prd,      /* RD */
     504             :         struct bgp_table *table_rd, /* per-rd VPN route table */
     505             :         afi_t afi, struct bgp *bgp,
     506             :         const struct prefix *prefix, /* unicast prefix */
     507             :         struct ecommunity *ecom,     /* generated ecoms */
     508             :         uint32_t *local_pref,        /* NULL = no local_pref */
     509             :         uint32_t *med,               /* NULL = no med */
     510             :         struct prefix *ubpi_nexthop) /* unicast nexthop */
     511             : {
     512           0 :         struct bgp_dest *bd;
     513           0 :         struct bgp_path_info *bpi;
     514             : 
     515           0 :         if (!table_rd)
     516             :                 return;
     517             : 
     518           0 :         vnc_zlog_debug_verbose("%s: ubpi_nexthop=%pFX", __func__, ubpi_nexthop);
     519             : 
     520             :         /* exact match */
     521           0 :         bd = bgp_node_lookup(table_rd, ubpi_nexthop);
     522           0 :         if (!bd) {
     523           0 :                 vnc_zlog_debug_verbose(
     524             :                         "%s: no match in RD's table for ubpi_nexthop",
     525             :                         __func__);
     526           0 :                 return;
     527             :         }
     528             : 
     529             :         /* Iterate over bgp_info items at this node */
     530           0 :         for (bpi = bgp_dest_get_bgp_path_info(bd); bpi; bpi = bpi->next) {
     531             : 
     532           0 :                 vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
     533             :                         bgp, afi, bpi, /* VPN bpi */
     534             :                         prd, prefix, local_pref, med, ecom);
     535             :         }
     536             : 
     537           0 :         bgp_dest_unlock_node(bd);
     538             : }
     539             : 
     540           0 : static void vnc_import_bgp_add_route_mode_resolve_nve(
     541             :         struct bgp *bgp, const struct prefix *prefix, /* unicast prefix */
     542             :         struct bgp_path_info *info)                   /* unicast info */
     543             : {
     544           0 :         afi_t afi = family2afi(prefix->family);
     545             : 
     546           0 :         struct prefix pfx_unicast_nexthop = {0}; /* happy valgrind */
     547             : 
     548           0 :         struct ecommunity *ecom = NULL;
     549           0 :         uint32_t local_pref;
     550           0 :         uint32_t *med = NULL;
     551             : 
     552           0 :         struct prefix_bag *pb;
     553           0 :         struct bgp_dest *bdp; /* prd table node */
     554             : 
     555             :         /*debugging */
     556           0 :         if (VNC_DEBUG(VERBOSE)) {
     557           0 :                 char str_nh[PREFIX_STRLEN];
     558           0 :                 struct prefix nh;
     559             : 
     560           0 :                 nh.prefixlen = 0;
     561           0 :                 rfapiUnicastNexthop2Prefix(afi, info->attr, &nh);
     562           0 :                 if (nh.prefixlen) {
     563           0 :                         prefix2str(&nh, str_nh, sizeof(str_nh));
     564             :                 } else {
     565           0 :                         str_nh[0] = '?';
     566           0 :                         str_nh[1] = 0;
     567             :                 }
     568             : 
     569           0 :                 vnc_zlog_debug_verbose(
     570             :                         "%s(bgp=%p, unicast prefix=%pFX, unicast nh=%s)",
     571             :                         __func__, bgp, prefix, str_nh);
     572             :         }
     573             : 
     574           0 :         if (info->type != ZEBRA_ROUTE_BGP) {
     575           0 :                 vnc_zlog_debug_verbose(
     576             :                         "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
     577             :                         __func__, info->type, zebra_route_string(info->type),
     578             :                         ZEBRA_ROUTE_BGP, "ZEBRA_ROUTE_BGP");
     579           0 :                 return;
     580             :         }
     581             : 
     582             :         /*
     583             :          * Preliminary checks
     584             :          */
     585             : 
     586           0 :         if (!afi) {
     587           0 :                 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of prefix",
     588             :                          __func__);
     589           0 :                 return;
     590             :         }
     591             : 
     592           0 :         if (!(bgp->rfapi_cfg)) {
     593           0 :                 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
     594             :                                        __func__);
     595           0 :                 return;
     596             :         }
     597             : 
     598             :         /* check vnc redist flag for bgp direct routes */
     599           0 :         if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
     600           0 :                 vnc_zlog_debug_verbose(
     601             :                         "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
     602             :                         __func__, afi);
     603           0 :                 return;
     604             :         }
     605             : 
     606             : 
     607           0 :         if (process_unicast_route(bgp, afi, prefix, info, &ecom,
     608             :                                   &pfx_unicast_nexthop)) {
     609             : 
     610           0 :                 vnc_zlog_debug_verbose(
     611             :                         "%s: process_unicast_route error, skipping", __func__);
     612           0 :                 return;
     613             :         }
     614             : 
     615           0 :         local_pref = calc_local_pref(info->attr, info->peer);
     616           0 :         if (info->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
     617           0 :                 med = &info->attr->med;
     618             : 
     619             :         /*
     620             :          * At this point, we have allocated:
     621             :          *
     622             :          *  ecom    ecommunity ptr, union of unicast and ROO parts (no NVE part)
     623             :          *
     624             :          * And we have set:
     625             :          *
     626             :          *  pfx_unicast_nexthop     nexthop of uncast route
     627             :          */
     628             : 
     629           0 :         if (!bgp->rfapi->resolve_nve_nexthop) {
     630           0 :                 bgp->rfapi->resolve_nve_nexthop =
     631           0 :                         skiplist_new(SKIPLIST_FLAG_ALLOW_DUPLICATES,
     632             :                                      vnc_prefix_cmp, prefix_bag_free);
     633             :         }
     634             : 
     635           0 :         pb = XCALLOC(MTYPE_RFAPI_PREFIX_BAG, sizeof(struct prefix_bag));
     636           0 :         pb->hpfx = pfx_unicast_nexthop;
     637           0 :         pb->ubpi = info;
     638           0 :         pb->upfx = *prefix;
     639             : 
     640           0 :         bgp_path_info_lock(info); /* skiplist refers to it */
     641           0 :         skiplist_insert(bgp->rfapi->resolve_nve_nexthop, &pb->hpfx, pb);
     642             : 
     643             :         /*
     644             :          * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
     645             :          * (exact match, /32). If an exact match is found, call add_vnc_route.
     646             :          */
     647             : 
     648           0 :         for (bdp = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); bdp;
     649           0 :              bdp = bgp_route_next(bdp)) {
     650             : 
     651           0 :                 struct bgp_table *table;
     652             : 
     653           0 :                 table = bgp_dest_get_bgp_table_info(bdp);
     654             : 
     655           0 :                 if (!table)
     656           0 :                         continue;
     657             : 
     658           0 :                 vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
     659           0 :                         (struct prefix_rd *)bgp_dest_get_prefix(bdp), table,
     660             :                         afi, bgp, prefix, ecom, &local_pref, med,
     661             :                         &pfx_unicast_nexthop);
     662             :         }
     663             : 
     664             : 
     665           0 :         if (ecom)
     666           0 :                 ecommunity_free(&ecom);
     667             : 
     668           0 :         vnc_zlog_debug_verbose("%s: done", __func__);
     669             : }
     670             : 
     671             : 
     672           0 : static void vnc_import_bgp_add_route_mode_plain(struct bgp *bgp,
     673             :                                                 const struct prefix *prefix,
     674             :                                                 struct bgp_path_info *info)
     675             : {
     676           0 :         afi_t afi = family2afi(prefix->family);
     677           0 :         struct peer *peer = info->peer;
     678           0 :         struct attr *attr = info->attr;
     679           0 :         struct attr hattr;
     680           0 :         struct rfapi_cfg *hc = bgp->rfapi_cfg;
     681           0 :         struct attr *iattr = NULL;
     682             : 
     683           0 :         struct rfapi_ip_addr vnaddr;
     684           0 :         struct prefix vn_pfx_space;
     685           0 :         struct prefix *vn_pfx = NULL;
     686           0 :         int ahr_flags = 0;
     687           0 :         struct ecommunity *ecom = NULL;
     688           0 :         struct prefix_rd prd;
     689           0 :         struct route_map *rmap = NULL;
     690           0 :         uint32_t local_pref;
     691           0 :         uint32_t *med = NULL;
     692             : 
     693           0 :         vnc_zlog_debug_verbose("%s(prefix=%pFX) entry", __func__, prefix);
     694             : 
     695           0 :         if (!afi) {
     696           0 :                 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of prefix",
     697             :                          __func__);
     698           0 :                 return;
     699             :         }
     700             : 
     701           0 :         if (!hc) {
     702           0 :                 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
     703             :                                        __func__);
     704           0 :                 return;
     705             :         }
     706             : 
     707             :         /* check vnc redist flag for bgp direct routes */
     708           0 :         if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
     709           0 :                 vnc_zlog_debug_verbose(
     710             :                         "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
     711             :                         __func__, afi);
     712           0 :                 return;
     713             :         }
     714             : 
     715             :         /*
     716             :          * mode "plain" specific code
     717             :          */
     718             :         {
     719           0 :                 vnc_zlog_debug_verbose("%s: NOT using redist RFG", __func__);
     720             : 
     721             :                 /*
     722             :                  * prefix list check
     723             :                  */
     724           0 :                 if (hc->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi]) {
     725           0 :                         vnc_zlog_debug_verbose(
     726             :                                 "%s: HC prefix list is set, checking",
     727             :                                 __func__);
     728           0 :                         if (prefix_list_apply(
     729             :                                     hc->plist_redist[ZEBRA_ROUTE_BGP_DIRECT]
     730             :                                                     [afi],
     731             :                                     prefix)
     732             :                             == PREFIX_DENY) {
     733           0 :                                 vnc_zlog_debug_verbose(
     734             :                                         "%s: prefix list returns DENY, blocking route",
     735             :                                         __func__);
     736           0 :                                 return;
     737             :                         }
     738           0 :                         vnc_zlog_debug_verbose(
     739             :                                 "%s: prefix list returns PASS, allowing route",
     740             :                                 __func__);
     741             :                 }
     742             : 
     743             :                 /* apply routemap, if any, later */
     744           0 :                 rmap = hc->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT];
     745             : 
     746             :                 /*
     747             :                  * Incoming prefix is unicast. If v6, it is in multiprotocol
     748             :                  * area,
     749             :                  * but if v4 it is in attr->nexthop
     750             :                  */
     751           0 :                 rfapiUnicastNexthop2Prefix(afi, attr, &vn_pfx_space);
     752           0 :                 vn_pfx = &vn_pfx_space;
     753             : 
     754             :                 /* UN address */
     755           0 :                 ahr_flags |= RFAPI_AHR_NO_TUNNEL_SUBTLV;
     756             :         }
     757             : 
     758           0 :         if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE))
     759           0 :                 vnc_zlog_debug_any("%s vn_pfx=%pFX", __func__, vn_pfx);
     760             : 
     761             :         /*
     762             :          * Compute VN address
     763             :          */
     764           0 :         if (rfapiQprefix2Raddr(vn_pfx, &vnaddr)) {
     765           0 :                 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
     766             :                                        __func__);
     767           0 :                 return;
     768             :         }
     769             : 
     770             :         /*
     771             :          * route map handling
     772             :          * This code is here because it allocates an interned attr which
     773             :          * must be freed before we return. It's easier to put it after
     774             :          * all of the possible returns above.
     775             :          */
     776           0 :         memset(&hattr, 0, sizeof(hattr));
     777             :         /* hattr becomes a ghost attr */
     778           0 :         hattr = *attr;
     779             : 
     780           0 :         if (rmap) {
     781           0 :                 struct bgp_path_info info;
     782           0 :                 route_map_result_t ret;
     783             : 
     784           0 :                 memset(&info, 0, sizeof(info));
     785           0 :                 info.peer = peer;
     786           0 :                 info.attr = &hattr;
     787           0 :                 ret = route_map_apply(rmap, prefix, &info);
     788           0 :                 if (ret == RMAP_DENYMATCH) {
     789           0 :                         bgp_attr_flush(&hattr);
     790           0 :                         vnc_zlog_debug_verbose(
     791             :                                 "%s: route map \"%s\" says DENY, returning",
     792             :                                 __func__, rmap->name);
     793           0 :                         return;
     794             :                 }
     795             :         }
     796             : 
     797           0 :         iattr = bgp_attr_intern(&hattr);
     798           0 :         bgp_attr_flush(&hattr);
     799             : 
     800             :         /* Now iattr is an allocated interned attr */
     801             : 
     802             :         /*
     803             :          * Mode "plain" specific code
     804             :          *
     805             :          * Sets RD in dummy HD
     806             :          * Allocates ecom
     807             :          */
     808             :         {
     809           0 :                 if (vnaddr.addr_family != AF_INET) {
     810           0 :                         vnc_zlog_debug_verbose(
     811             :                                 "%s: can't auto-assign RD, VN AF (%d) is not IPv4, skipping",
     812             :                                 __func__, vnaddr.addr_family);
     813           0 :                         if (iattr) {
     814           0 :                                 bgp_attr_unintern(&iattr);
     815             :                         }
     816           0 :                         return;
     817             :                 }
     818           0 :                 memset(&prd, 0, sizeof(prd));
     819           0 :                 rfapi_set_autord_from_vn(&prd, &vnaddr);
     820             : 
     821           0 :                 if (iattr && bgp_attr_get_ecommunity(iattr))
     822           0 :                         ecom = ecommunity_dup(bgp_attr_get_ecommunity(iattr));
     823             :         }
     824             : 
     825           0 :         local_pref = calc_local_pref(iattr, peer);
     826             : 
     827           0 :         if (iattr && (iattr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))) {
     828           0 :                 med = &iattr->med;
     829             :         }
     830             : 
     831           0 :         if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE)) {
     832           0 :                 char buf[PREFIX_STRLEN];
     833             : 
     834           0 :                 rfapiRfapiIpAddr2Str(&vnaddr, buf, sizeof(buf));
     835           0 :                 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__, buf);
     836             :         }
     837             : 
     838           0 :         vncHDBgpDirect.peer = peer;
     839           0 :         add_vnc_route(&vncHDBgpDirect, bgp, SAFI_MPLS_VPN, prefix, &prd,
     840           0 :                       &vnaddr, &local_pref, &(bgp->rfapi_cfg->redist_lifetime),
     841             :                       NULL,                  /* RFP options */
     842             :                       NULL, NULL, ecom, med, /* med */
     843             :                       NULL,                  /* label: default */
     844             :                       ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE,
     845             :                       ahr_flags);
     846           0 :         vncHDBgpDirect.peer = NULL;
     847             : 
     848           0 :         if (ecom)
     849           0 :                 ecommunity_free(&ecom);
     850             : }
     851             : 
     852           0 : static void vnc_import_bgp_add_route_mode_nvegroup(
     853             :         struct bgp *bgp, const struct prefix *prefix,
     854             :         struct bgp_path_info *info, struct rfapi_nve_group_cfg *rfg)
     855             : {
     856           0 :         afi_t afi = family2afi(prefix->family);
     857           0 :         struct peer *peer = info->peer;
     858           0 :         struct attr *attr = info->attr;
     859           0 :         struct attr hattr;
     860           0 :         struct attr *iattr = NULL;
     861             : 
     862           0 :         struct rfapi_ip_addr vnaddr;
     863           0 :         struct prefix *vn_pfx = NULL;
     864           0 :         int ahr_flags = 0;
     865           0 :         struct ecommunity *ecom = NULL;
     866           0 :         struct prefix_rd prd;
     867           0 :         struct route_map *rmap = NULL;
     868           0 :         uint32_t local_pref;
     869             : 
     870           0 :         vnc_zlog_debug_verbose("%s(prefix=%pFX) entry", __func__, prefix);
     871             : 
     872           0 :         assert(rfg);
     873             : 
     874           0 :         if (!afi) {
     875           0 :                 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of prefix",
     876             :                          __func__);
     877           0 :                 return;
     878             :         }
     879             : 
     880           0 :         if (!(bgp->rfapi_cfg)) {
     881           0 :                 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
     882             :                                        __func__);
     883           0 :                 return;
     884             :         }
     885             : 
     886             :         /* check vnc redist flag for bgp direct routes */
     887           0 :         if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
     888           0 :                 vnc_zlog_debug_verbose(
     889             :                         "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
     890             :                         __func__, afi);
     891           0 :                 return;
     892             :         }
     893             : 
     894             : 
     895             :         /*
     896             :          * RFG-specific code
     897             :          */
     898             :         {
     899             : 
     900           0 :                 struct rfapi_ip_prefix pfx_un;
     901             : 
     902           0 :                 vnc_zlog_debug_verbose("%s: using redist RFG", __func__);
     903             : 
     904             :                 /*
     905             :                  * RFG prefix list check
     906             :                  */
     907           0 :                 if (rfg->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi]) {
     908           0 :                         vnc_zlog_debug_verbose(
     909             :                                 "%s: RFG prefix list is set, checking",
     910             :                                 __func__);
     911           0 :                         if (prefix_list_apply(
     912             :                                     rfg->plist_redist[ZEBRA_ROUTE_BGP_DIRECT]
     913             :                                                      [afi],
     914             :                                     prefix)
     915             :                             == PREFIX_DENY) {
     916           0 :                                 vnc_zlog_debug_verbose(
     917             :                                         "%s: prefix list returns DENY, blocking route",
     918             :                                         __func__);
     919           0 :                                 return;
     920             :                         }
     921           0 :                         vnc_zlog_debug_verbose(
     922             :                                 "%s: prefix list returns PASS, allowing route",
     923             :                                 __func__);
     924             :                 }
     925             : 
     926             :                 /* apply routemap, if any, later */
     927           0 :                 rmap = rfg->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT];
     928             : 
     929             :                 /*
     930             :                  * export nve group's VN addr prefix must be a /32 which
     931             :                  * will yield the VN addr to use
     932             :                  */
     933           0 :                 vn_pfx = &rfg->vn_prefix;
     934             : 
     935             :                 /*
     936             :                  * UN Address
     937             :                  */
     938           0 :                 if (!is_host_prefix(&rfg->un_prefix)) {
     939             :                         /* NB prefixlen==0 means it has not been configured */
     940           0 :                         vnc_zlog_debug_verbose(
     941             :                                 "%s: redist RFG UN pfx not host pfx (plen=%d), skipping",
     942             :                                 __func__, rfg->un_prefix.prefixlen);
     943           0 :                         return;
     944             :                 }
     945             : 
     946           0 :                 rfapiQprefix2Rprefix(&rfg->un_prefix, &pfx_un);
     947             : 
     948           0 :                 vncHDBgpDirect.un_addr = pfx_un.prefix;
     949             :         }
     950             : 
     951           0 :         if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE))
     952           0 :                 vnc_zlog_debug_any("%s vn_pfx=%pFX", __func__, vn_pfx);
     953             : 
     954             :         /*
     955             :          * Compute VN address
     956             :          */
     957           0 :         if (rfapiQprefix2Raddr(vn_pfx, &vnaddr)) {
     958           0 :                 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
     959             :                                        __func__);
     960           0 :                 return;
     961             :         }
     962             : 
     963             :         /*
     964             :          * route map handling
     965             :          * This code is here because it allocates an interned attr which
     966             :          * must be freed before we return. It's easier to put it after
     967             :          * all of the possible returns above.
     968             :          */
     969           0 :         memset(&hattr, 0, sizeof(hattr));
     970             :         /* hattr becomes a ghost attr */
     971           0 :         hattr = *attr;
     972             : 
     973           0 :         if (rmap) {
     974           0 :                 struct bgp_path_info path;
     975           0 :                 route_map_result_t ret;
     976             : 
     977           0 :                 memset(&path, 0, sizeof(path));
     978           0 :                 path.peer = peer;
     979           0 :                 path.attr = &hattr;
     980           0 :                 ret = route_map_apply(rmap, prefix, &path);
     981           0 :                 if (ret == RMAP_DENYMATCH) {
     982           0 :                         bgp_attr_flush(&hattr);
     983           0 :                         vnc_zlog_debug_verbose(
     984             :                                 "%s: route map \"%s\" says DENY, returning",
     985             :                                 __func__, rmap->name);
     986           0 :                         return;
     987             :                 }
     988             :         }
     989             : 
     990           0 :         iattr = bgp_attr_intern(&hattr);
     991           0 :         bgp_attr_flush(&hattr);
     992             : 
     993             :         /* Now iattr is an allocated interned attr */
     994             : 
     995             :         /*
     996             :          * RFG-specific code
     997             :          *
     998             :          * Sets RD in dummy HD
     999             :          * Allocates ecom
    1000             :          */
    1001             :         {
    1002             : 
    1003           0 :                 memset(&prd, 0, sizeof(prd));
    1004           0 :                 prd = rfg->rd;
    1005           0 :                 prd.family = AF_UNSPEC;
    1006           0 :                 prd.prefixlen = 64;
    1007             : 
    1008           0 :                 if (rfg->rd.family == AF_UNIX) {
    1009           0 :                         rfapi_set_autord_from_vn(&prd, &vnaddr);
    1010             :                 }
    1011             : 
    1012           0 :                 if (rfg->rt_export_list)
    1013           0 :                         ecom = ecommunity_dup(
    1014           0 :                                 bgp->rfapi_cfg->rfg_redist->rt_export_list);
    1015             :                 else
    1016           0 :                         ecom = ecommunity_new();
    1017             : 
    1018           0 :                 if (iattr && bgp_attr_get_ecommunity(iattr))
    1019           0 :                         ecom = ecommunity_merge(ecom,
    1020             :                                                 bgp_attr_get_ecommunity(iattr));
    1021             :         }
    1022             : 
    1023           0 :         local_pref = calc_local_pref(iattr, peer);
    1024             : 
    1025           0 :         if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE)) {
    1026           0 :                 char buf[BUFSIZ];
    1027             : 
    1028           0 :                 buf[0] = 0;
    1029           0 :                 rfapiRfapiIpAddr2Str(&vnaddr, buf, BUFSIZ);
    1030           0 :                 buf[BUFSIZ - 1] = 0;
    1031           0 :                 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__, buf);
    1032             :         }
    1033             : 
    1034           0 :         vncHDBgpDirect.peer = peer;
    1035           0 :         add_vnc_route(&vncHDBgpDirect, bgp, SAFI_MPLS_VPN, prefix, &prd,
    1036           0 :                       &vnaddr, &local_pref, &(bgp->rfapi_cfg->redist_lifetime),
    1037             :                       NULL,                   /* RFP options */
    1038             :                       NULL, NULL, ecom, NULL, /* med */
    1039             :                       NULL,                   /* label: default */
    1040             :                       ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE,
    1041             :                       ahr_flags);
    1042           0 :         vncHDBgpDirect.peer = NULL;
    1043             : 
    1044           0 :         if (ecom)
    1045           0 :                 ecommunity_free(&ecom);
    1046             : }
    1047             : 
    1048           0 : static void vnc_import_bgp_del_route_mode_plain(struct bgp *bgp,
    1049             :                                                 const struct prefix *prefix,
    1050             :                                                 struct bgp_path_info *info)
    1051             : {
    1052           0 :         struct prefix_rd prd;
    1053           0 :         afi_t afi = family2afi(prefix->family);
    1054           0 :         struct prefix *vn_pfx = NULL;
    1055           0 :         struct rfapi_ip_addr vnaddr;
    1056           0 :         struct prefix vn_pfx_space;
    1057             : 
    1058             : 
    1059           0 :         assert(afi);
    1060             : 
    1061             :         /*
    1062             :          * Compute VN address
    1063             :          */
    1064             : 
    1065           0 :         if (info) {
    1066           0 :                 rfapiUnicastNexthop2Prefix(afi, info->attr, &vn_pfx_space);
    1067             :         } else {
    1068           0 :                 vnc_zlog_debug_verbose("%s: no attr, can't delete route",
    1069             :                                        __func__);
    1070           0 :                 return;
    1071             :         }
    1072           0 :         vn_pfx = &vn_pfx_space;
    1073             : 
    1074           0 :         vnaddr.addr_family = vn_pfx->family;
    1075           0 :         switch (vn_pfx->family) {
    1076           0 :         case AF_INET:
    1077           0 :                 if (vn_pfx->prefixlen != IPV4_MAX_BITLEN) {
    1078           0 :                         vnc_zlog_debug_verbose(
    1079             :                                 "%s: redist VN plen (%d) != 32, skipping",
    1080             :                                 __func__, vn_pfx->prefixlen);
    1081           0 :                         return;
    1082             :                 }
    1083           0 :                 vnaddr.addr.v4 = vn_pfx->u.prefix4;
    1084           0 :                 break;
    1085             : 
    1086           0 :         case AF_INET6:
    1087           0 :                 if (vn_pfx->prefixlen != IPV6_MAX_BITLEN) {
    1088           0 :                         vnc_zlog_debug_verbose(
    1089             :                                 "%s: redist VN plen (%d) != 128, skipping",
    1090             :                                 __func__, vn_pfx->prefixlen);
    1091           0 :                         return;
    1092             :                 }
    1093           0 :                 vnaddr.addr.v6 = vn_pfx->u.prefix6;
    1094           0 :                 break;
    1095             : 
    1096           0 :         default:
    1097           0 :                 vnc_zlog_debug_verbose(
    1098             :                         "%s: no redist RFG VN host pfx configured, skipping",
    1099             :                         __func__);
    1100             :                 return;
    1101             :         }
    1102             : 
    1103             : 
    1104           0 :         memset(&prd, 0, sizeof(prd));
    1105           0 :         if (rfapi_set_autord_from_vn(&prd, &vnaddr)) {
    1106           0 :                 vnc_zlog_debug_verbose("%s: can't auto-assign RD, skipping",
    1107             :                                        __func__);
    1108           0 :                 return;
    1109             :         }
    1110             : 
    1111           0 :         vncHDBgpDirect.peer = info->peer;
    1112           0 :         vnc_zlog_debug_verbose("%s: setting peer to %p", __func__,
    1113             :                                vncHDBgpDirect.peer);
    1114           0 :         del_vnc_route(&vncHDBgpDirect, info->peer, bgp, SAFI_MPLS_VPN, prefix,
    1115             :                       &prd, ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE,
    1116             :                       NULL, 1);
    1117             : 
    1118           0 :         vncHDBgpDirect.peer = NULL;
    1119             : }
    1120             : 
    1121           0 : static void vnc_import_bgp_del_route_mode_nvegroup(struct bgp *bgp,
    1122             :                                                    const struct prefix *prefix,
    1123             :                                                    struct bgp_path_info *info)
    1124             : {
    1125           0 :         struct prefix_rd prd;
    1126           0 :         afi_t afi = family2afi(prefix->family);
    1127           0 :         struct rfapi_nve_group_cfg *rfg = NULL;
    1128           0 :         struct prefix *vn_pfx = NULL;
    1129           0 :         struct rfapi_ip_addr vnaddr;
    1130             : 
    1131             : 
    1132           0 :         assert(afi);
    1133             : 
    1134           0 :         rfg = bgp->rfapi_cfg->rfg_redist;
    1135           0 :         assert(rfg);
    1136             : 
    1137             :         /*
    1138             :          * Compute VN address
    1139             :          */
    1140             : 
    1141             :         /*
    1142             :          * export nve group's VN addr prefix must be a /32 which
    1143             :          * will yield the VN addr to use
    1144             :          */
    1145           0 :         vn_pfx = &rfg->vn_prefix;
    1146             : 
    1147             : 
    1148           0 :         vnaddr.addr_family = vn_pfx->family;
    1149           0 :         switch (vn_pfx->family) {
    1150           0 :         case AF_INET:
    1151           0 :                 if (vn_pfx->prefixlen != IPV4_MAX_BITLEN) {
    1152           0 :                         vnc_zlog_debug_verbose(
    1153             :                                 "%s: redist VN plen (%d) != 32, skipping",
    1154             :                                 __func__, vn_pfx->prefixlen);
    1155           0 :                         return;
    1156             :                 }
    1157           0 :                 vnaddr.addr.v4 = vn_pfx->u.prefix4;
    1158           0 :                 break;
    1159             : 
    1160           0 :         case AF_INET6:
    1161           0 :                 if (vn_pfx->prefixlen != IPV6_MAX_BITLEN) {
    1162           0 :                         vnc_zlog_debug_verbose(
    1163             :                                 "%s: redist VN plen (%d) != 128, skipping",
    1164             :                                 __func__, vn_pfx->prefixlen);
    1165           0 :                         return;
    1166             :                 }
    1167           0 :                 vnaddr.addr.v6 = vn_pfx->u.prefix6;
    1168           0 :                 break;
    1169             : 
    1170           0 :         default:
    1171           0 :                 vnc_zlog_debug_verbose(
    1172             :                         "%s: no redist RFG VN host pfx configured, skipping",
    1173             :                         __func__);
    1174             :                 return;
    1175             :         }
    1176             : 
    1177           0 :         memset(&prd, 0, sizeof(prd));
    1178           0 :         prd = rfg->rd;
    1179           0 :         prd.family = AF_UNSPEC;
    1180           0 :         prd.prefixlen = 64;
    1181             : 
    1182           0 :         if (rfg->rd.family == AF_UNIX) {
    1183             :                 /* means "auto" with VN addr */
    1184           0 :                 if (rfapi_set_autord_from_vn(&prd, &vnaddr)) {
    1185           0 :                         vnc_zlog_debug_verbose(
    1186             :                                 "%s: can't auto-assign RD, skipping", __func__);
    1187           0 :                         return;
    1188             :                 }
    1189             :         }
    1190             : 
    1191             : 
    1192           0 :         vncHDBgpDirect.peer = info->peer;
    1193           0 :         vnc_zlog_debug_verbose("%s: setting peer to %p", __func__,
    1194             :                                vncHDBgpDirect.peer);
    1195           0 :         del_vnc_route(&vncHDBgpDirect, info->peer, bgp, SAFI_MPLS_VPN, prefix,
    1196             :                       &prd, ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE,
    1197             :                       NULL, 1);
    1198             : 
    1199           0 :         vncHDBgpDirect.peer = NULL;
    1200             : }
    1201             : 
    1202           0 : static void vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
    1203             :         struct bgp *bgp, afi_t afi, struct bgp_path_info *bpi, /* VPN bpi */
    1204             :         struct prefix_rd *prd,                                 /* RD */
    1205             :         const struct prefix *prefix) /* unicast route prefix */
    1206             : {
    1207           0 :         struct prefix un;
    1208             : 
    1209           0 :         if (bpi->type != ZEBRA_ROUTE_BGP
    1210           0 :             && bpi->type != ZEBRA_ROUTE_BGP_DIRECT) {
    1211             : 
    1212           0 :                 return;
    1213             :         }
    1214           0 :         if (bpi->sub_type != BGP_ROUTE_NORMAL
    1215             :             && bpi->sub_type != BGP_ROUTE_STATIC
    1216           0 :             && bpi->sub_type != BGP_ROUTE_RFP) {
    1217             : 
    1218             :                 return;
    1219             :         }
    1220           0 :         if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
    1221             :                 return;
    1222             : 
    1223           0 :         vncHDResolveNve.peer = bpi->peer;
    1224           0 :         if (!rfapiGetVncTunnelUnAddr(bpi->attr, &un)) {
    1225           0 :                 if (rfapiQprefix2Raddr(&un, &vncHDResolveNve.un_addr))
    1226             :                         return;
    1227             :         } else {
    1228           0 :                 memset(&vncHDResolveNve.un_addr, 0,
    1229             :                        sizeof(vncHDResolveNve.un_addr));
    1230             :         }
    1231             : 
    1232           0 :         del_vnc_route(&vncHDResolveNve, vncHDResolveNve.peer, bgp,
    1233             :                       SAFI_MPLS_VPN, prefix, /* unicast route prefix */
    1234             :                       prd, ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL,
    1235             :                       0); /* flags */
    1236             : }
    1237             : 
    1238           0 : static void vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
    1239             :         struct prefix_rd *prd,
    1240             :         struct bgp_table *table_rd, /* per-rd VPN route table */
    1241             :         afi_t afi, struct bgp *bgp,
    1242             :         const struct prefix *prefix,       /* unicast prefix */
    1243             :         const struct prefix *ubpi_nexthop) /* unicast bpi's nexthop */
    1244             : {
    1245           0 :         struct bgp_dest *bd;
    1246           0 :         struct bgp_path_info *bpi;
    1247             : 
    1248           0 :         if (!table_rd)
    1249             :                 return;
    1250             : 
    1251           0 :         vnc_zlog_debug_verbose("%s: ubpi_nexthop=%pFX", __func__, ubpi_nexthop);
    1252             : 
    1253             : 
    1254             :         /* exact match */
    1255           0 :         bd = bgp_node_lookup(table_rd, ubpi_nexthop);
    1256           0 :         if (!bd) {
    1257           0 :                 vnc_zlog_debug_verbose(
    1258             :                         "%s: no match in RD's table for ubpi_nexthop",
    1259             :                         __func__);
    1260           0 :                 return;
    1261             :         }
    1262             : 
    1263             :         /* Iterate over bgp_info items at this node */
    1264           0 :         for (bpi = bgp_dest_get_bgp_path_info(bd); bpi; bpi = bpi->next) {
    1265             : 
    1266           0 :                 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
    1267             :                         bgp, afi, bpi, /* VPN bpi */
    1268             :                         prd,       /* VPN RD */
    1269             :                         prefix);       /* unicast route prefix */
    1270             :         }
    1271             : 
    1272           0 :         bgp_dest_unlock_node(bd);
    1273             : }
    1274             : 
    1275             : static void
    1276           0 : vnc_import_bgp_del_route_mode_resolve_nve(struct bgp *bgp, afi_t afi,
    1277             :                                           const struct prefix *prefix,
    1278             :                                           struct bgp_path_info *info)
    1279             : {
    1280           0 :         struct ecommunity *ecom = NULL;
    1281           0 :         struct prefix pfx_unicast_nexthop = {0}; /* happy valgrind */
    1282             : 
    1283             :         // struct listnode           *hnode;
    1284             :         // struct rfapi_descriptor   *rfd;
    1285           0 :         struct prefix_bag *pb;
    1286           0 :         void *cursor;
    1287           0 :         struct skiplist *sl = bgp->rfapi->resolve_nve_nexthop;
    1288           0 :         int rc;
    1289           0 :         struct bgp_dest *bdp; /* prd table node */
    1290             : 
    1291           0 :         if (!sl) {
    1292           0 :                 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
    1293             :                                        __func__);
    1294           0 :                 return;
    1295             :         }
    1296             : 
    1297           0 :         if (info->type != ZEBRA_ROUTE_BGP) {
    1298           0 :                 vnc_zlog_debug_verbose(
    1299             :                         "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
    1300             :                         __func__, info->type, zebra_route_string(info->type),
    1301             :                         ZEBRA_ROUTE_BGP, "ZEBRA_ROUTE_BGP");
    1302           0 :                 return;
    1303             :         }
    1304             : 
    1305           0 :         if (process_unicast_route(bgp, afi, prefix, info, &ecom,
    1306             :                                   &pfx_unicast_nexthop)) {
    1307             : 
    1308           0 :                 vnc_zlog_debug_verbose(
    1309             :                         "%s: process_unicast_route error, skipping", __func__);
    1310           0 :                 return;
    1311             :         }
    1312             : 
    1313           0 :         rc = skiplist_first_value(sl, &pfx_unicast_nexthop, (void *)&pb,
    1314             :                                   &cursor);
    1315           0 :         while (!rc) {
    1316           0 :                 if (pb->ubpi == info) {
    1317           0 :                         skiplist_delete(sl, &pfx_unicast_nexthop, pb);
    1318           0 :                         bgp_path_info_unlock(info);
    1319           0 :                         break;
    1320             :                 }
    1321           0 :                 rc = skiplist_next_value(sl, &pfx_unicast_nexthop, (void *)&pb,
    1322             :                                          &cursor);
    1323             :         }
    1324             : 
    1325             :         /*
    1326             :          * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
    1327             :          * (exact match, /32). If an exact match is found, call add_vnc_route.
    1328             :          */
    1329             : 
    1330           0 :         for (bdp = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); bdp;
    1331           0 :              bdp = bgp_route_next(bdp)) {
    1332             : 
    1333           0 :                 struct bgp_table *table;
    1334             : 
    1335           0 :                 table = bgp_dest_get_bgp_table_info(bdp);
    1336             : 
    1337           0 :                 if (!table)
    1338           0 :                         continue;
    1339             : 
    1340           0 :                 vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
    1341           0 :                         (struct prefix_rd *)bgp_dest_get_prefix(bdp), table,
    1342             :                         afi, bgp, prefix, &pfx_unicast_nexthop);
    1343             :         }
    1344             : 
    1345           0 :         if (ecom)
    1346           0 :                 ecommunity_free(&ecom);
    1347             : }
    1348             : 
    1349             : 
    1350             : /***********************************************************************
    1351             :  *                      Add/Delete CE->NVE routes
    1352             :  ***********************************************************************/
    1353             : 
    1354             : /*
    1355             :  * Should be called whan a bpi is added to VPN RIB. This function
    1356             :  * will check if it is a host route and return immediately if not.
    1357             :  */
    1358           0 : void vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
    1359             :         struct bgp *bgp, struct prefix_rd *prd, /* RD */
    1360             :         struct bgp_table *table_rd,             /* per-rd VPN route table */
    1361             :         const struct prefix *prefix,            /* VPN prefix */
    1362             :         struct bgp_path_info *bpi)              /* new VPN host route */
    1363             : {
    1364           0 :         afi_t afi = family2afi(prefix->family);
    1365           0 :         struct skiplist *sl = NULL;
    1366           0 :         int rc;
    1367           0 :         struct prefix_bag *pb;
    1368           0 :         void *cursor;
    1369           0 :         struct rfapi_cfg *hc = NULL;
    1370             : 
    1371           0 :         vnc_zlog_debug_verbose("%s: entry", __func__);
    1372             : 
    1373           0 :         if (afi != AFI_IP && afi != AFI_IP6) {
    1374           0 :                 vnc_zlog_debug_verbose("%s: bad afi %d, skipping", __func__,
    1375             :                                        afi);
    1376           0 :                 return;
    1377             :         }
    1378             : 
    1379           0 :         if (!(hc = bgp->rfapi_cfg)) {
    1380           0 :                 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
    1381             :                                        __func__);
    1382           0 :                 return;
    1383             :         }
    1384             : 
    1385             :         /* check vnc redist flag for bgp direct routes */
    1386           0 :         if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
    1387           0 :                 vnc_zlog_debug_verbose(
    1388             :                         "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
    1389             :                         __func__, afi);
    1390           0 :                 return;
    1391             :         }
    1392             : 
    1393           0 :         if (hc->redist_mode != VNC_REDIST_MODE_RESOLVE_NVE) {
    1394           0 :                 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
    1395             :                                        __func__);
    1396           0 :                 return;
    1397             :         }
    1398             : 
    1399           0 :         if (bgp->rfapi)
    1400           0 :                 sl = bgp->rfapi->resolve_nve_nexthop;
    1401             : 
    1402           0 :         if (!sl) {
    1403           0 :                 vnc_zlog_debug_verbose(
    1404             :                         "%s: no resolve_nve_nexthop skiplist, skipping",
    1405             :                         __func__);
    1406           0 :                 return;
    1407             :         }
    1408             : 
    1409           0 :         if (!is_host_prefix(prefix)) {
    1410           0 :                 vnc_zlog_debug_verbose("%s: not host prefix, skipping",
    1411             :                                        __func__);
    1412           0 :                 return;
    1413             :         }
    1414             : 
    1415           0 :         rc = skiplist_first_value(sl, prefix, (void *)&pb, &cursor);
    1416           0 :         while (!rc) {
    1417           0 :                 struct ecommunity *ecom;
    1418           0 :                 struct prefix pfx_unicast_nexthop;
    1419           0 :                 uint32_t *med = NULL;
    1420           0 :                 uint32_t local_pref;
    1421             : 
    1422           0 :                 memset(&pfx_unicast_nexthop, 0,
    1423             :                        sizeof(pfx_unicast_nexthop)); /* keep valgrind happy */
    1424             : 
    1425           0 :                 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE))
    1426           0 :                         vnc_zlog_debug_any(
    1427             :                                 "%s: examining RHN Entry (q=%p): upfx=%pFX, hpfx=%pFX, ubpi=%p",
    1428             :                                 __func__, cursor, &pb->upfx, &pb->hpfx,
    1429             :                                 pb->ubpi);
    1430             : 
    1431           0 :                 if (process_unicast_route(bgp, afi, &pb->upfx, pb->ubpi, &ecom,
    1432             :                                           &pfx_unicast_nexthop)) {
    1433             : 
    1434           0 :                         vnc_zlog_debug_verbose(
    1435             :                                 "%s: process_unicast_route error, skipping",
    1436             :                                 __func__);
    1437           0 :                         continue;
    1438             :                 }
    1439           0 :                 local_pref = calc_local_pref(pb->ubpi->attr, pb->ubpi->peer);
    1440             : 
    1441           0 :                 if (pb->ubpi->attr->flag
    1442           0 :                     & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
    1443           0 :                         med = &pb->ubpi->attr->med;
    1444             : 
    1445             :                 /*
    1446             :                  * Sanity check
    1447             :                  */
    1448           0 :                 if (vnc_prefix_cmp(&pfx_unicast_nexthop, prefix)) {
    1449           0 :                         vnc_zlog_debug_verbose(
    1450             :                                 "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %pFX != nve pfx %pFX",
    1451             :                                 __func__, &pfx_unicast_nexthop, prefix);
    1452           0 :                         assert(0);
    1453             :                 }
    1454             : 
    1455           0 :                 vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
    1456             :                         bgp, afi, bpi,  /* VPN bpi */
    1457           0 :                         prd, &pb->upfx, /* unicast prefix */
    1458             :                         &local_pref, med, ecom);
    1459             : 
    1460           0 :                 if (ecom)
    1461           0 :                         ecommunity_free(&ecom);
    1462             : 
    1463             : #if DEBUG_RHN_LIST
    1464             :                 /* debug */
    1465             :                 {
    1466             :                         vnc_zlog_debug_verbose(
    1467             :                                 "%s: advancing past RHN Entry (q=%p): with prefix %pFX",
    1468             :                                 __func__, cursor, prefix);
    1469             :                         print_rhn_list(__func__, NULL); /* debug */
    1470             :                 }
    1471             : #endif
    1472           0 :                 rc = skiplist_next_value(sl, prefix, (void *)&pb, &cursor);
    1473             :         }
    1474           0 :         vnc_zlog_debug_verbose("%s: done", __func__);
    1475             : }
    1476             : 
    1477             : 
    1478           0 : void vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
    1479             :         struct bgp *bgp, struct prefix_rd *prd, /* RD */
    1480             :         struct bgp_table *table_rd,             /* per-rd VPN route table */
    1481             :         const struct prefix *prefix,            /* VPN prefix */
    1482             :         struct bgp_path_info *bpi)              /* old VPN host route */
    1483             : {
    1484           0 :         afi_t afi = family2afi(prefix->family);
    1485           0 :         struct skiplist *sl = NULL;
    1486           0 :         struct prefix_bag *pb;
    1487           0 :         void *cursor;
    1488           0 :         struct rfapi_cfg *hc = NULL;
    1489           0 :         int rc;
    1490             : 
    1491           0 :         vnc_zlog_debug_verbose("%s(bgp=%p, nve prefix=%pFX)", __func__, bgp,
    1492             :                                prefix);
    1493             : 
    1494           0 :         if (afi != AFI_IP && afi != AFI_IP6)
    1495           0 :                 return;
    1496             : 
    1497           0 :         if (!(hc = bgp->rfapi_cfg)) {
    1498           0 :                 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
    1499             :                                        __func__);
    1500           0 :                 return;
    1501             :         }
    1502             : 
    1503             :         /* check vnc redist flag for bgp direct routes */
    1504           0 :         if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
    1505           0 :                 vnc_zlog_debug_verbose(
    1506             :                         "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
    1507             :                         __func__, afi);
    1508           0 :                 return;
    1509             :         }
    1510             : 
    1511           0 :         if (hc->redist_mode != VNC_REDIST_MODE_RESOLVE_NVE) {
    1512           0 :                 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
    1513             :                                        __func__);
    1514           0 :                 return;
    1515             :         }
    1516             : 
    1517           0 :         if (bgp->rfapi)
    1518           0 :                 sl = bgp->rfapi->resolve_nve_nexthop;
    1519             : 
    1520           0 :         if (!sl) {
    1521           0 :                 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
    1522             :                                        __func__);
    1523           0 :                 return;
    1524             :         }
    1525             : 
    1526           0 :         if (!is_host_prefix(prefix)) {
    1527           0 :                 vnc_zlog_debug_verbose("%s: not host route, skip", __func__);
    1528           0 :                 return;
    1529             :         }
    1530             : 
    1531             :         /*
    1532             :          * Find all entries with key == CE in the RHN list
    1533             :          */
    1534           0 :         rc = skiplist_first_value(sl, prefix, (void *)&pb, &cursor);
    1535           0 :         while (!rc) {
    1536             : 
    1537           0 :                 struct ecommunity *ecom;
    1538           0 :                 struct prefix pfx_unicast_nexthop;
    1539             : 
    1540           0 :                 memset(&pfx_unicast_nexthop, 0,
    1541             :                        sizeof(pfx_unicast_nexthop)); /* keep valgrind happy */
    1542             : 
    1543           0 :                 if (process_unicast_route(bgp, afi, &pb->upfx, pb->ubpi, &ecom,
    1544             :                                           &pfx_unicast_nexthop)) {
    1545             : 
    1546           0 :                         vnc_zlog_debug_verbose(
    1547             :                                 "%s: process_unicast_route error, skipping",
    1548             :                                 __func__);
    1549           0 :                         continue;
    1550             :                 }
    1551             : 
    1552             :                 /*
    1553             :                  * Sanity check
    1554             :                  */
    1555           0 :                 if (vnc_prefix_cmp(&pfx_unicast_nexthop, prefix)) {
    1556           0 :                         vnc_zlog_debug_verbose(
    1557             :                                 "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %pFX != nve pfx %pFX",
    1558             :                                 __func__, &pfx_unicast_nexthop, prefix);
    1559           0 :                         assert(0);
    1560             :                 }
    1561             : 
    1562           0 :                 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
    1563           0 :                         bgp, afi, bpi, prd, &pb->upfx);
    1564             : 
    1565           0 :                 if (ecom)
    1566           0 :                         ecommunity_free(&ecom);
    1567             : 
    1568           0 :                 rc = skiplist_next_value(sl, prefix, (void *)&pb, &cursor);
    1569             :         }
    1570             : }
    1571             : 
    1572             : 
    1573             : /***********************************************************************
    1574             :  *                      Exterior Routes
    1575             :  ***********************************************************************/
    1576             : 
    1577             : #define DEBUG_IS_USABLE_INTERIOR 1
    1578             : 
    1579           0 : static int is_usable_interior_route(struct bgp_path_info *bpi_interior)
    1580             : {
    1581           0 :         if (!VALID_INTERIOR_TYPE(bpi_interior->type)) {
    1582             : #if DEBUG_IS_USABLE_INTERIOR
    1583           0 :                 vnc_zlog_debug_verbose(
    1584             :                         "%s: NO: type %d is not valid interior type", __func__,
    1585             :                         bpi_interior->type);
    1586             : #endif
    1587           0 :                 return 0;
    1588             :         }
    1589           0 :         if (!CHECK_FLAG(bpi_interior->flags, BGP_PATH_VALID)) {
    1590             : #if DEBUG_IS_USABLE_INTERIOR
    1591           0 :                 vnc_zlog_debug_verbose("%s: NO: BGP_PATH_VALID not set",
    1592             :                                        __func__);
    1593             : #endif
    1594           0 :                 return 0;
    1595             :         }
    1596             :         return 1;
    1597             : }
    1598             : 
    1599             : /*
    1600             :  * There should be only one of these per prefix at a time.
    1601             :  * This should be called as a result of selection operation
    1602             :  *
    1603             :  * NB should be called espacially for bgp instances that are named,
    1604             :  * because the exterior routes will always come from one of those.
    1605             :  * We filter here on the instance name to make sure we get only the
    1606             :  * right routes.
    1607             :  */
    1608          78 : static void vnc_import_bgp_exterior_add_route_it(
    1609             :         struct bgp *bgp,                    /* exterior instance, we hope */
    1610             :         const struct prefix *prefix,        /* unicast prefix */
    1611             :         struct bgp_path_info *info,         /* unicast info */
    1612             :         struct rfapi_import_table *it_only) /* NULL, or limit to this IT */
    1613             : {
    1614          78 :         struct rfapi *h;
    1615          78 :         struct rfapi_cfg *hc;
    1616          78 :         struct prefix pfx_orig_nexthop;
    1617          78 :         struct rfapi_import_table *it;
    1618          78 :         struct bgp *bgp_default = bgp_get_default();
    1619          78 :         afi_t afi = family2afi(prefix->family);
    1620             : 
    1621          78 :         if (!bgp_default)
    1622          78 :                 return;
    1623             : 
    1624          78 :         h = bgp_default->rfapi;
    1625          78 :         hc = bgp_default->rfapi_cfg;
    1626             : 
    1627          78 :         vnc_zlog_debug_verbose("%s: entry with it=%p", __func__, it_only);
    1628             : 
    1629          78 :         if (!h || !hc) {
    1630           0 :                 vnc_zlog_debug_verbose(
    1631             :                         "%s: rfapi or rfapi_cfg not instantiated, skipping",
    1632             :                         __func__);
    1633           0 :                 return;
    1634             :         }
    1635          78 :         if (!hc->redist_bgp_exterior_view) {
    1636          78 :                 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
    1637             :                                        __func__);
    1638          78 :                 return;
    1639             :         }
    1640           0 :         if (bgp != hc->redist_bgp_exterior_view) {
    1641           0 :                 vnc_zlog_debug_verbose(
    1642             :                         "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
    1643             :                         __func__, bgp, hc->redist_bgp_exterior_view);
    1644           0 :                 return;
    1645             :         }
    1646             : 
    1647           0 :         if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
    1648           0 :                 vnc_zlog_debug_verbose(
    1649             :                         "%s: redist of exterior routes not enabled, skipping",
    1650             :                         __func__);
    1651           0 :                 return;
    1652             :         }
    1653             : 
    1654             :         /*
    1655             :          * Extract nexthop from exterior route
    1656             :          *
    1657             :          * Incoming prefix is unicast. If v6, it is in multiprotocol area,
    1658             :          * but if v4 it is in attr->nexthop
    1659             :          */
    1660           0 :         rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_orig_nexthop);
    1661             : 
    1662           0 :         for (it = h->imports; it; it = it->next) {
    1663           0 :                 struct agg_table *table;
    1664           0 :                 struct agg_node *rn;
    1665           0 :                 struct agg_node *par;
    1666           0 :                 struct bgp_path_info *bpi_interior;
    1667           0 :                 int have_usable_route;
    1668             : 
    1669           0 :                 vnc_zlog_debug_verbose("%s: doing it %p", __func__, it);
    1670             : 
    1671           0 :                 if (it_only && (it_only != it)) {
    1672           0 :                         vnc_zlog_debug_verbose("%s: doesn't match it_only %p",
    1673             :                                                __func__, it_only);
    1674           0 :                         continue;
    1675             :                 }
    1676             : 
    1677           0 :                 table = it->imported_vpn[afi];
    1678             : 
    1679           0 :                 for (rn = agg_node_match(table, &pfx_orig_nexthop),
    1680           0 :                     have_usable_route = 0;
    1681           0 :                      (!have_usable_route) && rn;) {
    1682             : 
    1683           0 :                         vnc_zlog_debug_verbose("%s: it %p trying rn %p",
    1684             :                                                __func__, it, rn);
    1685             : 
    1686           0 :                         for (bpi_interior = rn->info; bpi_interior;
    1687           0 :                              bpi_interior = bpi_interior->next) {
    1688           0 :                                 struct prefix_rd *prd;
    1689           0 :                                 struct attr new_attr;
    1690           0 :                                 uint32_t label = 0;
    1691             : 
    1692           0 :                                 if (!is_usable_interior_route(bpi_interior))
    1693           0 :                                         continue;
    1694             : 
    1695           0 :                                 vnc_zlog_debug_verbose(
    1696             :                                         "%s: usable: bpi_interior %p", __func__,
    1697             :                                         bpi_interior);
    1698             : 
    1699             :                                 /*
    1700             :                                  * have a legitimate route to exterior's nexthop
    1701             :                                  * via NVE.
    1702             :                                  *
    1703             :                                  * Import unicast route to the import table
    1704             :                                  */
    1705           0 :                                 have_usable_route = 1;
    1706             : 
    1707           0 :                                 if (bpi_interior->extra) {
    1708           0 :                                         prd = &bpi_interior->extra->vnc.import
    1709             :                                                        .rd;
    1710           0 :                                         label = decode_label(
    1711             :                                                 &bpi_interior->extra->label[0]);
    1712             :                                 } else
    1713             :                                         prd = NULL;
    1714             : 
    1715             :                                 /* use local_pref from unicast route */
    1716           0 :                                 memset(&new_attr, 0, sizeof(new_attr));
    1717           0 :                                 new_attr = *bpi_interior->attr;
    1718           0 :                                 if (info->attr->flag
    1719           0 :                                     & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
    1720           0 :                                         new_attr.local_pref =
    1721           0 :                                                 info->attr->local_pref;
    1722           0 :                                         new_attr.flag |= ATTR_FLAG_BIT(
    1723             :                                                 BGP_ATTR_LOCAL_PREF);
    1724             :                                 }
    1725             : 
    1726           0 :                                 rfapiBgpInfoFilteredImportVPN(
    1727             :                                         it, FIF_ACTION_UPDATE,
    1728             :                                         bpi_interior->peer, NULL, /* rfd */
    1729             :                                         prefix, NULL, afi, prd, &new_attr,
    1730             :                                         ZEBRA_ROUTE_BGP_DIRECT_EXT,
    1731             :                                         BGP_ROUTE_REDISTRIBUTE, &label);
    1732             :                         }
    1733             : 
    1734           0 :                         if (have_usable_route) {
    1735             :                                 /*
    1736             :                                  * Make monitor
    1737             :                                  *
    1738             :                                  * TBD factor this out into its own function
    1739             :                                  */
    1740           0 :                                 struct prefix *pfx_mon = prefix_new();
    1741           0 :                                 if (!RFAPI_MONITOR_EXTERIOR(rn)->source) {
    1742           0 :                                         RFAPI_MONITOR_EXTERIOR(rn)->source =
    1743           0 :                                                 skiplist_new(
    1744             :                                                         0, NULL,
    1745             :                                                         prefix_free_lists);
    1746           0 :                                         agg_lock_node(rn); /* for skiplist */
    1747             :                                 }
    1748           0 :                                 agg_lock_node(rn); /* for skiplist entry */
    1749           0 :                                 prefix_copy(pfx_mon, prefix);
    1750           0 :                                 if (!skiplist_insert(
    1751           0 :                                             RFAPI_MONITOR_EXTERIOR(rn)->source,
    1752             :                                             info, pfx_mon)) {
    1753             : 
    1754           0 :                                         bgp_path_info_lock(info);
    1755             :                                 }
    1756             :                         }
    1757           0 :                         par = agg_node_parent(rn);
    1758           0 :                         if (par)
    1759           0 :                                 agg_lock_node(par);
    1760           0 :                         agg_unlock_node(rn);
    1761           0 :                         rn = par;
    1762             :                 }
    1763           0 :                 if (rn)
    1764           0 :                         agg_unlock_node(rn);
    1765             : 
    1766           0 :                 if (!have_usable_route) {
    1767           0 :                         struct prefix *pfx_mon = prefix_new();
    1768           0 :                         prefix_copy(pfx_mon, prefix);
    1769           0 :                         if (!skiplist_insert(it->monitor_exterior_orphans, info,
    1770             :                                              pfx_mon)) {
    1771             : 
    1772           0 :                                 bgp_path_info_lock(info);
    1773             :                         }
    1774             :                 }
    1775             :         }
    1776             : }
    1777             : 
    1778          78 : void vnc_import_bgp_exterior_add_route(
    1779             :         struct bgp *bgp,             /* exterior instance, we hope */
    1780             :         const struct prefix *prefix, /* unicast prefix */
    1781             :         struct bgp_path_info *info)  /* unicast info */
    1782             : {
    1783          78 :         vnc_import_bgp_exterior_add_route_it(bgp, prefix, info, NULL);
    1784           0 : }
    1785             : 
    1786             : /*
    1787             :  * There should be only one of these per prefix at a time.
    1788             :  * This should probably be called as a result of selection operation.
    1789             :  *
    1790             :  * NB should be called espacially for bgp instances that are named,
    1791             :  * because the exterior routes will always come from one of those.
    1792             :  * We filter here on the instance name to make sure we get only the
    1793             :  * right routes.
    1794             :  */
    1795           5 : void vnc_import_bgp_exterior_del_route(
    1796             :         struct bgp *bgp, const struct prefix *prefix, /* unicast prefix */
    1797             :         struct bgp_path_info *info)                   /* unicast info */
    1798             : {
    1799           5 :         struct rfapi *h;
    1800           5 :         struct rfapi_cfg *hc;
    1801           5 :         struct rfapi_import_table *it;
    1802           5 :         struct prefix pfx_orig_nexthop;
    1803           5 :         afi_t afi = family2afi(prefix->family);
    1804           5 :         struct bgp *bgp_default = bgp_get_default();
    1805             : 
    1806           5 :         if (!bgp_default)
    1807           5 :                 return;
    1808             : 
    1809           5 :         memset(&pfx_orig_nexthop, 0,
    1810             :                sizeof(pfx_orig_nexthop)); /* keep valgrind happy */
    1811             : 
    1812           5 :         h = bgp_default->rfapi;
    1813           5 :         hc = bgp_default->rfapi_cfg;
    1814             : 
    1815           5 :         if (!h || !hc) {
    1816           0 :                 vnc_zlog_debug_verbose(
    1817             :                         "%s: rfapi or rfapi_cfg not instantiated, skipping",
    1818             :                         __func__);
    1819           0 :                 return;
    1820             :         }
    1821           5 :         if (!hc->redist_bgp_exterior_view) {
    1822           5 :                 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
    1823             :                                        __func__);
    1824           5 :                 return;
    1825             :         }
    1826           0 :         if (bgp != hc->redist_bgp_exterior_view) {
    1827           0 :                 vnc_zlog_debug_verbose(
    1828             :                         "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
    1829             :                         __func__, bgp, hc->redist_bgp_exterior_view);
    1830           0 :                 return;
    1831             :         }
    1832           0 :         if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
    1833           0 :                 vnc_zlog_debug_verbose(
    1834             :                         "%s: redist of exterior routes no enabled, skipping",
    1835             :                         __func__);
    1836           0 :                 return;
    1837             :         }
    1838             : 
    1839             :         /*
    1840             :          * Extract nexthop from exterior route
    1841             :          *
    1842             :          * Incoming prefix is unicast. If v6, it is in multiprotocol area,
    1843             :          * but if v4 it is in attr->nexthop
    1844             :          */
    1845           0 :         rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_orig_nexthop);
    1846             : 
    1847           0 :         for (it = h->imports; it; it = it->next) {
    1848           0 :                 struct agg_table *table;
    1849           0 :                 struct agg_node *rn;
    1850           0 :                 struct agg_node *par;
    1851           0 :                 struct bgp_path_info *bpi_interior;
    1852           0 :                 int have_usable_route;
    1853             : 
    1854           0 :                 table = it->imported_vpn[afi];
    1855             : 
    1856           0 :                 for (rn = agg_node_match(table, &pfx_orig_nexthop),
    1857           0 :                     have_usable_route = 0;
    1858           0 :                      (!have_usable_route) && rn;) {
    1859             : 
    1860           0 :                         for (bpi_interior = rn->info; bpi_interior;
    1861           0 :                              bpi_interior = bpi_interior->next) {
    1862           0 :                                 struct prefix_rd *prd;
    1863           0 :                                 uint32_t label = 0;
    1864             : 
    1865           0 :                                 if (!is_usable_interior_route(bpi_interior))
    1866           0 :                                         continue;
    1867             : 
    1868             :                                 /*
    1869             :                                  * have a legitimate route to exterior's nexthop
    1870             :                                  * via NVE.
    1871             :                                  *
    1872             :                                  * Import unicast route to the import table
    1873             :                                  */
    1874           0 :                                 have_usable_route = 1;
    1875             : 
    1876           0 :                                 if (bpi_interior->extra) {
    1877           0 :                                         prd = &bpi_interior->extra->vnc.import
    1878             :                                                        .rd;
    1879           0 :                                         label = decode_label(
    1880             :                                                 &bpi_interior->extra->label[0]);
    1881             :                                 } else
    1882             :                                         prd = NULL;
    1883             : 
    1884           0 :                                 rfapiBgpInfoFilteredImportVPN(
    1885             :                                         it, FIF_ACTION_KILL, bpi_interior->peer,
    1886             :                                         NULL, /* rfd */
    1887             :                                         prefix, NULL, afi, prd,
    1888             :                                         bpi_interior->attr,
    1889             :                                         ZEBRA_ROUTE_BGP_DIRECT_EXT,
    1890             :                                         BGP_ROUTE_REDISTRIBUTE, &label);
    1891             : 
    1892             :                                 /*
    1893             :                                  * Delete monitor
    1894             :                                  *
    1895             :                                  * TBD factor this out into its own function
    1896             :                                  */
    1897             :                                 {
    1898           0 :                                         if (RFAPI_MONITOR_EXTERIOR(rn)
    1899           0 :                                                     ->source) {
    1900           0 :                                                 if (!skiplist_delete(
    1901           0 :                                                             RFAPI_MONITOR_EXTERIOR(
    1902             :                                                                     rn)
    1903             :                                                                     ->source,
    1904             :                                                             info, NULL)) {
    1905             : 
    1906           0 :                                                         bgp_path_info_unlock(
    1907             :                                                                 info);
    1908           0 :                                                         agg_unlock_node(
    1909             :                                                                 rn); /* sl entry
    1910             :                                                                       */
    1911             :                                                 }
    1912           0 :                                                 if (skiplist_empty(
    1913           0 :                                                             RFAPI_MONITOR_EXTERIOR(
    1914             :                                                                     rn)
    1915             :                                                                     ->source)) {
    1916           0 :                                                         skiplist_free(
    1917           0 :                                                                 RFAPI_MONITOR_EXTERIOR(
    1918             :                                                                         rn)
    1919             :                                                                         ->source);
    1920           0 :                                                         RFAPI_MONITOR_EXTERIOR(
    1921             :                                                                 rn)
    1922           0 :                                                                 ->source = NULL;
    1923           0 :                                                         agg_unlock_node(
    1924             :                                                                 rn); /* skiplist
    1925             :                                                                         itself
    1926             :                                                                         */
    1927             :                                                 }
    1928             :                                         }
    1929             :                                 }
    1930             :                         }
    1931           0 :                         par = agg_node_parent(rn);
    1932           0 :                         if (par)
    1933           0 :                                 agg_lock_node(par);
    1934           0 :                         agg_unlock_node(rn);
    1935           0 :                         rn = par;
    1936             :                 }
    1937           0 :                 if (rn)
    1938           0 :                         agg_unlock_node(rn);
    1939             : 
    1940           0 :                 if (!have_usable_route) {
    1941           0 :                         if (!skiplist_delete(it->monitor_exterior_orphans, info,
    1942             :                                              NULL)) {
    1943             : 
    1944           0 :                                 bgp_path_info_unlock(info);
    1945             :                         }
    1946             :                 }
    1947             :         }
    1948             : }
    1949             : 
    1950             : /*
    1951             :  * This function should be called after a new interior VPN route
    1952             :  * has been added to an import_table.
    1953             :  *
    1954             :  * NB should also be called whenever an existing vpn interior route
    1955             :  * becomes valid (e.g., valid_interior_count is inremented)
    1956             :  */
    1957           0 : void vnc_import_bgp_exterior_add_route_interior(
    1958             :         struct bgp *bgp, struct rfapi_import_table *it,
    1959             :         struct agg_node *rn_interior,       /* VPN IT node */
    1960             :         struct bgp_path_info *bpi_interior) /* VPN IT route */
    1961             : {
    1962           0 :         const struct prefix *p = agg_node_get_prefix(rn_interior);
    1963           0 :         afi_t afi = family2afi(p->family);
    1964           0 :         struct agg_node *par;
    1965           0 :         struct bgp_path_info *bpi_exterior;
    1966           0 :         struct prefix *pfx_exterior; /* exterior pfx */
    1967           0 :         void *cursor;
    1968           0 :         int rc;
    1969           0 :         struct list *list_adopted;
    1970             : 
    1971           0 :         vnc_zlog_debug_verbose("%s: entry", __func__);
    1972             : 
    1973           0 :         if (!is_usable_interior_route(bpi_interior)) {
    1974           0 :                 vnc_zlog_debug_verbose(
    1975             :                         "%s: not usable interior route, skipping", __func__);
    1976           0 :                 return;
    1977             :         }
    1978             : 
    1979           0 :         if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
    1980           0 :                 vnc_zlog_debug_verbose(
    1981             :                         "%s: redist of exterior routes no enabled, skipping",
    1982             :                         __func__);
    1983           0 :                 return;
    1984             :         }
    1985             : 
    1986           0 :         if (it == bgp->rfapi->it_ce) {
    1987           0 :                 vnc_zlog_debug_verbose("%s: import table is it_ce, skipping",
    1988             :                                        __func__);
    1989           0 :                 return;
    1990             :         }
    1991             : 
    1992             :         /*debugging */
    1993           0 :         vnc_zlog_debug_verbose("%s: interior prefix=%pRN, bpi type=%d",
    1994             :                                __func__, rn_interior, bpi_interior->type);
    1995             : 
    1996           0 :         if (RFAPI_HAS_MONITOR_EXTERIOR(rn_interior)) {
    1997             : 
    1998           0 :                 int count = 0; /* debugging */
    1999             : 
    2000           0 :                 vnc_zlog_debug_verbose(
    2001             :                         "%s: has exterior monitor; ext src: %p", __func__,
    2002             :                         RFAPI_MONITOR_EXTERIOR(rn_interior)->source);
    2003             : 
    2004             :                 /*
    2005             :                  * There is a monitor here already. Therefore, we do not need
    2006             :                  * to do any pulldown. Just construct exterior routes based
    2007             :                  * on the new interior route.
    2008             :                  */
    2009           0 :                 cursor = NULL;
    2010           0 :                 for (rc = skiplist_next(
    2011           0 :                              RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
    2012             :                              (void **)&bpi_exterior, (void **)&pfx_exterior,
    2013             :                              &cursor);
    2014           0 :                      !rc; rc = skiplist_next(
    2015           0 :                                   RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
    2016             :                                   (void **)&bpi_exterior,
    2017             :                                   (void **)&pfx_exterior, &cursor)) {
    2018             : 
    2019           0 :                         struct prefix_rd *prd;
    2020           0 :                         struct attr new_attr;
    2021           0 :                         uint32_t label = 0;
    2022             : 
    2023             : 
    2024           0 :                         ++count; /* debugging */
    2025             : 
    2026           0 :                         assert(bpi_exterior);
    2027           0 :                         assert(pfx_exterior);
    2028             : 
    2029           0 :                         if (bpi_interior->extra) {
    2030           0 :                                 prd = &bpi_interior->extra->vnc.import.rd;
    2031           0 :                                 label = decode_label(
    2032             :                                         &bpi_interior->extra->label[0]);
    2033             :                         } else
    2034             :                                 prd = NULL;
    2035             : 
    2036             :                         /* use local_pref from unicast route */
    2037           0 :                         memset(&new_attr, 0, sizeof(struct attr));
    2038           0 :                         new_attr = *bpi_interior->attr;
    2039           0 :                         if (bpi_exterior
    2040           0 :                             && (bpi_exterior->attr->flag
    2041           0 :                                 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) {
    2042           0 :                                 new_attr.local_pref =
    2043           0 :                                         bpi_exterior->attr->local_pref;
    2044           0 :                                 new_attr.flag |=
    2045             :                                         ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
    2046             :                         }
    2047             : 
    2048           0 :                         rfapiBgpInfoFilteredImportVPN(
    2049             :                                 it, FIF_ACTION_UPDATE, bpi_interior->peer,
    2050             :                                 NULL, /* rfd */
    2051             :                                 pfx_exterior, NULL, afi, prd, &new_attr,
    2052             :                                 ZEBRA_ROUTE_BGP_DIRECT_EXT,
    2053             :                                 BGP_ROUTE_REDISTRIBUTE, &label);
    2054             :                 }
    2055           0 :                 vnc_zlog_debug_verbose(
    2056             :                         "%s: finished constructing exteriors based on existing monitors",
    2057             :                         __func__);
    2058           0 :                 return;
    2059             :         }
    2060             : 
    2061           0 :         vnc_zlog_debug_verbose("%s: no exterior monitor", __func__);
    2062             : 
    2063             :         /*
    2064             :          * No monitor at this node. Is this the first valid interior
    2065             :          * route at this node?
    2066             :          */
    2067           0 :         if (RFAPI_MONITOR_EXTERIOR(rn_interior)->valid_interior_count > 1) {
    2068           0 :                 vnc_zlog_debug_verbose(
    2069             :                         "%s: new interior route not first valid one, skipping pulldown",
    2070             :                         __func__);
    2071           0 :                 return;
    2072             :         }
    2073             : 
    2074             :         /*
    2075             :          * Look up the tree for possible pulldown candidates.
    2076             :          * Find nearest parent with an exterior route monitor
    2077             :          */
    2078           0 :         for (par = agg_node_parent(rn_interior); par;
    2079           0 :              par = agg_node_parent(par)) {
    2080           0 :                 if (RFAPI_HAS_MONITOR_EXTERIOR(par))
    2081             :                         break;
    2082             :         }
    2083             : 
    2084           0 :         if (par) {
    2085             : 
    2086           0 :                 vnc_zlog_debug_verbose(
    2087             :                         "%s: checking parent %p for possible pulldowns",
    2088             :                         __func__, par);
    2089             : 
    2090             :                 /* check monitors at par for possible pulldown */
    2091           0 :                 cursor = NULL;
    2092           0 :                 for (rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(par)->source,
    2093             :                                         (void **)&bpi_exterior,
    2094             :                                         (void **)&pfx_exterior, &cursor);
    2095           0 :                      !rc;
    2096           0 :                      rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(par)->source,
    2097             :                                         (void **)&bpi_exterior,
    2098             :                                         (void **)&pfx_exterior, &cursor)) {
    2099             : 
    2100           0 :                         struct prefix pfx_nexthop;
    2101             : 
    2102           0 :                         memset(&pfx_nexthop, 0,
    2103             :                                sizeof(struct prefix)); /* keep valgrind happy */
    2104             : 
    2105             :                         /* check original nexthop for prefix match */
    2106           0 :                         rfapiUnicastNexthop2Prefix(afi, bpi_exterior->attr,
    2107             :                                                    &pfx_nexthop);
    2108             : 
    2109           0 :                         if (prefix_match(p, &pfx_nexthop)) {
    2110             : 
    2111           0 :                                 struct bgp_path_info *bpi;
    2112           0 :                                 struct prefix_rd *prd;
    2113           0 :                                 struct attr new_attr;
    2114           0 :                                 uint32_t label = 0;
    2115             : 
    2116             :                                 /* do pull-down */
    2117             : 
    2118             :                                 /*
    2119             :                                  * add monitor to longer prefix
    2120             :                                  */
    2121           0 :                                 struct prefix *pfx_mon = prefix_new();
    2122           0 :                                 prefix_copy(pfx_mon, pfx_exterior);
    2123           0 :                                 if (!RFAPI_MONITOR_EXTERIOR(rn_interior)
    2124           0 :                                              ->source) {
    2125           0 :                                         RFAPI_MONITOR_EXTERIOR(rn_interior)
    2126           0 :                                                 ->source = skiplist_new(
    2127             :                                                 0, NULL, prefix_free_lists);
    2128           0 :                                         agg_lock_node(rn_interior);
    2129             :                                 }
    2130           0 :                                 skiplist_insert(
    2131           0 :                                         RFAPI_MONITOR_EXTERIOR(rn_interior)
    2132             :                                                 ->source,
    2133             :                                         bpi_exterior, pfx_mon);
    2134           0 :                                 agg_lock_node(rn_interior);
    2135             : 
    2136             :                                 /*
    2137             :                                  * Delete constructed exterior routes based on
    2138             :                                  * parent routes.
    2139             :                                  */
    2140           0 :                                 for (bpi = par->info; bpi; bpi = bpi->next) {
    2141             : 
    2142           0 :                                         if (bpi->extra) {
    2143           0 :                                                 prd = &bpi->extra->vnc.import
    2144             :                                                                .rd;
    2145           0 :                                                 label = decode_label(
    2146             :                                                         &bpi->extra->label[0]);
    2147             :                                         } else
    2148             :                                                 prd = NULL;
    2149             : 
    2150           0 :                                         rfapiBgpInfoFilteredImportVPN(
    2151             :                                                 it, FIF_ACTION_KILL, bpi->peer,
    2152             :                                                 NULL, /* rfd */
    2153             :                                                 pfx_exterior, NULL, afi, prd,
    2154             :                                                 bpi->attr,
    2155             :                                                 ZEBRA_ROUTE_BGP_DIRECT_EXT,
    2156             :                                                 BGP_ROUTE_REDISTRIBUTE, &label);
    2157             :                                 }
    2158             : 
    2159             : 
    2160             :                                 /*
    2161             :                                  * Add constructed exterior routes based on
    2162             :                                  * the new interior route at longer prefix.
    2163             :                                  */
    2164           0 :                                 if (bpi_interior->extra) {
    2165           0 :                                         prd = &bpi_interior->extra->vnc.import
    2166             :                                                        .rd;
    2167           0 :                                         label = decode_label(
    2168             :                                                 &bpi_interior->extra->label[0]);
    2169             :                                 } else
    2170             :                                         prd = NULL;
    2171             : 
    2172             :                                 /* use local_pref from unicast route */
    2173           0 :                                 memset(&new_attr, 0, sizeof(struct attr));
    2174           0 :                                 new_attr = *bpi_interior->attr;
    2175           0 :                                 if (bpi_exterior
    2176           0 :                                     && (bpi_exterior->attr->flag
    2177           0 :                                         & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) {
    2178           0 :                                         new_attr.local_pref =
    2179           0 :                                                 bpi_exterior->attr->local_pref;
    2180           0 :                                         new_attr.flag |= ATTR_FLAG_BIT(
    2181             :                                                 BGP_ATTR_LOCAL_PREF);
    2182             :                                 }
    2183             : 
    2184           0 :                                 rfapiBgpInfoFilteredImportVPN(
    2185             :                                         it, FIF_ACTION_UPDATE,
    2186             :                                         bpi_interior->peer, NULL, /* rfd */
    2187             :                                         pfx_exterior, NULL, afi, prd, &new_attr,
    2188             :                                         ZEBRA_ROUTE_BGP_DIRECT_EXT,
    2189             :                                         BGP_ROUTE_REDISTRIBUTE, &label);
    2190             :                         }
    2191             :                 }
    2192             : 
    2193             :                 /*
    2194             :                  * The only monitors at rn_interior are the ones we added just
    2195             :                  * above, so we can use the rn_interior list to identify which
    2196             :                  * monitors to delete from the parent.
    2197             :                  */
    2198           0 :                 cursor = NULL;
    2199           0 :                 for (rc = skiplist_next(
    2200           0 :                              RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
    2201             :                              (void **)&bpi_exterior, NULL, &cursor);
    2202           0 :                      !rc; rc = skiplist_next(
    2203           0 :                                   RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
    2204             :                                   (void **)&bpi_exterior, NULL, &cursor)) {
    2205             : 
    2206             : 
    2207           0 :                         skiplist_delete(RFAPI_MONITOR_EXTERIOR(par)->source,
    2208             :                                         bpi_exterior, NULL);
    2209           0 :                         agg_unlock_node(par); /* sl entry */
    2210             :                 }
    2211           0 :                 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(par)->source)) {
    2212           0 :                         skiplist_free(RFAPI_MONITOR_EXTERIOR(par)->source);
    2213           0 :                         RFAPI_MONITOR_EXTERIOR(par)->source = NULL;
    2214           0 :                         agg_unlock_node(par); /* sl itself */
    2215             :                 }
    2216             :         }
    2217             : 
    2218           0 :         vnc_zlog_debug_verbose("%s: checking orphans", __func__);
    2219             : 
    2220             :         /*
    2221             :          * See if any orphans can be pulled down to the current node
    2222             :          */
    2223           0 :         cursor = NULL;
    2224           0 :         list_adopted = NULL;
    2225           0 :         for (rc = skiplist_next(it->monitor_exterior_orphans,
    2226             :                                 (void **)&bpi_exterior, (void **)&pfx_exterior,
    2227             :                                 &cursor);
    2228           0 :              !rc; rc = skiplist_next(it->monitor_exterior_orphans,
    2229             :                                      (void **)&bpi_exterior,
    2230             :                                      (void **)&pfx_exterior, &cursor)) {
    2231             : 
    2232           0 :                 struct prefix pfx_nexthop;
    2233           0 :                 afi_t afi_exterior = family2afi(pfx_exterior->family);
    2234             : 
    2235           0 :                 vnc_zlog_debug_verbose(
    2236             :                         "%s: checking exterior orphan at prefix %pFX", __func__,
    2237             :                         pfx_exterior);
    2238             : 
    2239           0 :                 if (afi_exterior != afi) {
    2240           0 :                         vnc_zlog_debug_verbose(
    2241             :                                 "%s: exterior orphan afi %d != interior afi %d, skip",
    2242             :                                 __func__, afi_exterior, afi);
    2243           0 :                         continue;
    2244             :                 }
    2245             : 
    2246             :                 /* check original nexthop for prefix match */
    2247           0 :                 rfapiUnicastNexthop2Prefix(afi, bpi_exterior->attr,
    2248             :                                            &pfx_nexthop);
    2249             : 
    2250           0 :                 if (prefix_match(p, &pfx_nexthop)) {
    2251             : 
    2252           0 :                         struct prefix_rd *prd;
    2253           0 :                         struct attr new_attr;
    2254           0 :                         uint32_t label = 0;
    2255             : 
    2256             :                         /* do pull-down */
    2257             : 
    2258             :                         /*
    2259             :                          * add monitor to longer prefix
    2260             :                          */
    2261             : 
    2262           0 :                         struct prefix *pfx_mon = prefix_new();
    2263           0 :                         prefix_copy(pfx_mon, pfx_exterior);
    2264           0 :                         if (!RFAPI_MONITOR_EXTERIOR(rn_interior)->source) {
    2265           0 :                                 RFAPI_MONITOR_EXTERIOR(rn_interior)->source =
    2266           0 :                                         skiplist_new(
    2267             :                                                 0, NULL, prefix_free_lists);
    2268           0 :                                 agg_lock_node(rn_interior); /* sl */
    2269             :                         }
    2270           0 :                         skiplist_insert(
    2271           0 :                                 RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
    2272             :                                 bpi_exterior, pfx_mon);
    2273           0 :                         agg_lock_node(rn_interior); /* sl entry */
    2274           0 :                         if (!list_adopted) {
    2275           0 :                                 list_adopted = list_new();
    2276             :                         }
    2277           0 :                         listnode_add(list_adopted, bpi_exterior);
    2278             : 
    2279             :                         /*
    2280             :                          * Add constructed exterior routes based on the
    2281             :                          * new interior route at the longer prefix.
    2282             :                          */
    2283           0 :                         if (bpi_interior->extra) {
    2284           0 :                                 prd = &bpi_interior->extra->vnc.import.rd;
    2285           0 :                                 label = decode_label(
    2286             :                                         &bpi_interior->extra->label[0]);
    2287             :                         } else
    2288             :                                 prd = NULL;
    2289             : 
    2290             :                         /* use local_pref from unicast route */
    2291           0 :                         memset(&new_attr, 0, sizeof(struct attr));
    2292           0 :                         new_attr = *bpi_interior->attr;
    2293           0 :                         if (bpi_exterior
    2294           0 :                             && (bpi_exterior->attr->flag
    2295           0 :                                 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) {
    2296           0 :                                 new_attr.local_pref =
    2297           0 :                                         bpi_exterior->attr->local_pref;
    2298           0 :                                 new_attr.flag |=
    2299             :                                         ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
    2300             :                         }
    2301             : 
    2302           0 :                         rfapiBgpInfoFilteredImportVPN(
    2303             :                                 it, FIF_ACTION_UPDATE, bpi_interior->peer,
    2304             :                                 NULL, /* rfd */
    2305             :                                 pfx_exterior, NULL, afi, prd, &new_attr,
    2306             :                                 ZEBRA_ROUTE_BGP_DIRECT_EXT,
    2307             :                                 BGP_ROUTE_REDISTRIBUTE, &label);
    2308             :                 }
    2309             :         }
    2310           0 :         if (list_adopted) {
    2311           0 :                 struct listnode *node;
    2312           0 :                 struct agg_node *an_bpi_exterior;
    2313             : 
    2314           0 :                 for (ALL_LIST_ELEMENTS_RO(list_adopted, node,
    2315             :                                           an_bpi_exterior)) {
    2316           0 :                         skiplist_delete(it->monitor_exterior_orphans,
    2317             :                                         an_bpi_exterior, NULL);
    2318             :                 }
    2319           0 :                 list_delete(&list_adopted);
    2320             :         }
    2321             : }
    2322             : 
    2323             : /*
    2324             :  * This function should be called after an interior VPN route
    2325             :  * has been deleted from an import_table.
    2326             :  * bpi_interior must still be valid, but it must already be detached
    2327             :  * from its route node and the route node's valid_interior_count
    2328             :  * must already be decremented.
    2329             :  *
    2330             :  * NB should also be called whenever an existing vpn interior route
    2331             :  * becomes invalid (e.g., valid_interior_count is decremented)
    2332             :  */
    2333           0 : void vnc_import_bgp_exterior_del_route_interior(
    2334             :         struct bgp *bgp, struct rfapi_import_table *it,
    2335             :         struct agg_node *rn_interior,       /* VPN IT node */
    2336             :         struct bgp_path_info *bpi_interior) /* VPN IT route */
    2337             : {
    2338           0 :         const struct prefix *p = agg_node_get_prefix(rn_interior);
    2339           0 :         afi_t afi = family2afi(p->family);
    2340           0 :         struct agg_node *par;
    2341           0 :         struct bgp_path_info *bpi_exterior;
    2342           0 :         struct prefix *pfx_exterior; /* exterior pfx */
    2343           0 :         void *cursor;
    2344           0 :         int rc;
    2345             : 
    2346           0 :         if (!VALID_INTERIOR_TYPE(bpi_interior->type)) {
    2347           0 :                 vnc_zlog_debug_verbose(
    2348             :                         "%s: type %d not valid interior type, skipping",
    2349             :                         __func__, bpi_interior->type);
    2350           0 :                 return;
    2351             :         }
    2352             : 
    2353           0 :         if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
    2354           0 :                 vnc_zlog_debug_verbose(
    2355             :                         "%s: redist of exterior routes no enabled, skipping",
    2356             :                         __func__);
    2357           0 :                 return;
    2358             :         }
    2359             : 
    2360           0 :         if (it == bgp->rfapi->it_ce) {
    2361           0 :                 vnc_zlog_debug_verbose("%s: it is it_ce, skipping", __func__);
    2362           0 :                 return;
    2363             :         }
    2364             : 
    2365             :         /* If no exterior routes depend on this prefix, nothing to do */
    2366           0 :         if (!RFAPI_HAS_MONITOR_EXTERIOR(rn_interior)) {
    2367           0 :                 vnc_zlog_debug_verbose("%s: no exterior monitor, skipping",
    2368             :                                        __func__);
    2369           0 :                 return;
    2370             :         }
    2371             : 
    2372             :         /*debugging */
    2373           0 :         vnc_zlog_debug_verbose("%s: interior prefix=%pRN, bpi type=%d",
    2374             :                                __func__, rn_interior, bpi_interior->type);
    2375             : 
    2376             :         /*
    2377             :          * Remove constructed routes based on the deleted interior route
    2378             :          */
    2379           0 :         cursor = NULL;
    2380           0 :         for (rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
    2381             :                                 (void **)&bpi_exterior, (void **)&pfx_exterior,
    2382             :                                 &cursor);
    2383           0 :              !rc;
    2384           0 :              rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
    2385             :                                 (void **)&bpi_exterior, (void **)&pfx_exterior,
    2386             :                                 &cursor)) {
    2387             : 
    2388           0 :                 struct prefix_rd *prd;
    2389           0 :                 uint32_t label = 0;
    2390             : 
    2391           0 :                 if (bpi_interior->extra) {
    2392           0 :                         prd = &bpi_interior->extra->vnc.import.rd;
    2393           0 :                         label = decode_label(&bpi_interior->extra->label[0]);
    2394             :                 } else
    2395             :                         prd = NULL;
    2396             : 
    2397           0 :                 rfapiBgpInfoFilteredImportVPN(
    2398             :                         it, FIF_ACTION_KILL, bpi_interior->peer, NULL, /* rfd */
    2399             :                         pfx_exterior, NULL, afi, prd, bpi_interior->attr,
    2400             :                         ZEBRA_ROUTE_BGP_DIRECT_EXT, BGP_ROUTE_REDISTRIBUTE,
    2401             :                         &label);
    2402             :         }
    2403             : 
    2404             :         /*
    2405             :          * If there are no remaining valid interior routes at this prefix,
    2406             :          * we need to look up the tree for a possible node to move monitors to
    2407             :          */
    2408           0 :         if (RFAPI_MONITOR_EXTERIOR(rn_interior)->valid_interior_count) {
    2409           0 :                 vnc_zlog_debug_verbose(
    2410             :                         "%s: interior routes still present, skipping",
    2411             :                         __func__);
    2412           0 :                 return;
    2413             :         }
    2414             : 
    2415             :         /*
    2416             :          * Find nearest parent with at least one valid interior route
    2417             :          * If none is found, par will end up NULL, and we will move
    2418             :          * the monitors to the orphan list for this import table
    2419             :          */
    2420           0 :         for (par = agg_node_parent(rn_interior); par;
    2421           0 :              par = agg_node_parent(par)) {
    2422           0 :                 if (RFAPI_MONITOR_EXTERIOR(par)->valid_interior_count)
    2423             :                         break;
    2424             :         }
    2425             : 
    2426           0 :         vnc_zlog_debug_verbose("%s: par=%p, ext src: %p", __func__, par,
    2427             :                                RFAPI_MONITOR_EXTERIOR(rn_interior)->source);
    2428             : 
    2429             :         /* move all monitors */
    2430             :         /*
    2431             :          * We will use and delete every element of the source skiplist
    2432             :          */
    2433           0 :         while (!skiplist_first(RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
    2434             :                                (void **)&bpi_exterior,
    2435             :                                (void **)&pfx_exterior)) {
    2436             : 
    2437           0 :                 struct prefix *pfx_mon = prefix_new();
    2438             : 
    2439           0 :                 prefix_copy(pfx_mon, pfx_exterior);
    2440             : 
    2441           0 :                 if (par) {
    2442             : 
    2443           0 :                         struct bgp_path_info *bpi;
    2444             : 
    2445             :                         /*
    2446             :                          * Add monitor to parent node
    2447             :                          */
    2448           0 :                         if (!RFAPI_MONITOR_EXTERIOR(par)->source) {
    2449           0 :                                 RFAPI_MONITOR_EXTERIOR(par)->source =
    2450           0 :                                         skiplist_new(
    2451             :                                                 0, NULL, prefix_free_lists);
    2452           0 :                                 agg_lock_node(par); /* sl */
    2453             :                         }
    2454           0 :                         skiplist_insert(RFAPI_MONITOR_EXTERIOR(par)->source,
    2455             :                                         bpi_exterior, pfx_mon);
    2456           0 :                         agg_lock_node(par); /* sl entry */
    2457             : 
    2458             :                         /* Add constructed exterior routes based on parent */
    2459           0 :                         for (bpi = par->info; bpi; bpi = bpi->next) {
    2460             : 
    2461           0 :                                 struct prefix_rd *prd;
    2462           0 :                                 struct attr new_attr;
    2463           0 :                                 uint32_t label = 0;
    2464             : 
    2465           0 :                                 if (bpi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT)
    2466           0 :                                         continue;
    2467             : 
    2468           0 :                                 if (bpi->extra) {
    2469           0 :                                         prd = &bpi->extra->vnc.import.rd;
    2470           0 :                                         label = decode_label(
    2471             :                                                 &bpi->extra->label[0]);
    2472             :                                 } else
    2473             :                                         prd = NULL;
    2474             : 
    2475             :                                 /* use local_pref from unicast route */
    2476           0 :                                 memset(&new_attr, 0, sizeof(new_attr));
    2477           0 :                                 new_attr = *bpi->attr;
    2478           0 :                                 if (bpi_exterior
    2479           0 :                                     && (bpi_exterior->attr->flag
    2480           0 :                                         & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) {
    2481           0 :                                         new_attr.local_pref =
    2482           0 :                                                 bpi_exterior->attr->local_pref;
    2483           0 :                                         new_attr.flag |= ATTR_FLAG_BIT(
    2484             :                                                 BGP_ATTR_LOCAL_PREF);
    2485             :                                 }
    2486             : 
    2487           0 :                                 rfapiBgpInfoFilteredImportVPN(
    2488             :                                         it, FIF_ACTION_UPDATE, bpi->peer,
    2489             :                                         NULL, /* rfd */
    2490             :                                         pfx_exterior, NULL, afi, prd, &new_attr,
    2491             :                                         ZEBRA_ROUTE_BGP_DIRECT_EXT,
    2492             :                                         BGP_ROUTE_REDISTRIBUTE, &label);
    2493             :                         }
    2494             : 
    2495             :                 } else {
    2496             : 
    2497             :                         /*
    2498             :                          * No interior route for exterior's nexthop. Save
    2499             :                          * monitor
    2500             :                          * in orphan list to await future route.
    2501             :                          */
    2502           0 :                         skiplist_insert(it->monitor_exterior_orphans,
    2503             :                                         bpi_exterior, pfx_mon);
    2504             :                 }
    2505             : 
    2506           0 :                 skiplist_delete_first(
    2507           0 :                         RFAPI_MONITOR_EXTERIOR(rn_interior)->source);
    2508           0 :                 agg_unlock_node(rn_interior); /* sl entry */
    2509             :         }
    2510           0 :         if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(rn_interior)->source)) {
    2511           0 :                 skiplist_free(RFAPI_MONITOR_EXTERIOR(rn_interior)->source);
    2512           0 :                 RFAPI_MONITOR_EXTERIOR(rn_interior)->source = NULL;
    2513           0 :                 agg_unlock_node(rn_interior); /* sl itself */
    2514             :         }
    2515             : }
    2516             : 
    2517             : /***********************************************************************
    2518             :  *                      Generic add/delete unicast routes
    2519             :  ***********************************************************************/
    2520             : 
    2521          78 : void vnc_import_bgp_add_route(struct bgp *bgp, const struct prefix *prefix,
    2522             :                               struct bgp_path_info *info)
    2523             : {
    2524          78 :         afi_t afi = family2afi(prefix->family);
    2525             : 
    2526          78 :         if (VNC_DEBUG(VERBOSE)) {
    2527           0 :                 struct prefix pfx_nexthop;
    2528             : 
    2529           0 :                 rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_nexthop);
    2530           0 :                 vnc_zlog_debug_verbose("%s: pfx %pFX, nh %pFX", __func__,
    2531             :                                        prefix, &pfx_nexthop);
    2532             :         }
    2533             : #if DEBUG_RHN_LIST
    2534             :         print_rhn_list(__func__, "ENTER ");
    2535             : #endif
    2536          78 :         VNC_RHNCK(enter);
    2537             : 
    2538          78 :         if (!afi) {
    2539           0 :                 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of prefix",
    2540             :                          __func__);
    2541           0 :                 return;
    2542             :         }
    2543             : 
    2544          78 :         if (!bgp->rfapi_cfg) {
    2545           0 :                 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
    2546             :                                        __func__);
    2547           0 :                 return;
    2548             :         }
    2549             : 
    2550             :         /* check vnc redist flag for bgp direct routes */
    2551          78 :         if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
    2552          78 :                 vnc_zlog_debug_verbose(
    2553             :                         "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
    2554             :                         __func__, afi, ZEBRA_ROUTE_BGP_DIRECT);
    2555          78 :                 return;
    2556             :         }
    2557             : 
    2558           0 :         switch (bgp->rfapi_cfg->redist_mode) {
    2559           0 :         case VNC_REDIST_MODE_PLAIN:
    2560           0 :                 vnc_import_bgp_add_route_mode_plain(bgp, prefix, info);
    2561           0 :                 break;
    2562             : 
    2563           0 :         case VNC_REDIST_MODE_RFG:
    2564           0 :                 if (bgp->rfapi_cfg->rfg_redist)
    2565           0 :                         vnc_import_bgp_add_route_mode_nvegroup(
    2566             :                                 bgp, prefix, info, bgp->rfapi_cfg->rfg_redist);
    2567             :                 else
    2568           0 :                         vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
    2569             :                                                __func__);
    2570             :                 break;
    2571             : 
    2572           0 :         case VNC_REDIST_MODE_RESOLVE_NVE:
    2573           0 :                 vnc_import_bgp_add_route_mode_resolve_nve(bgp, prefix, info);
    2574           0 :                 break;
    2575             :         }
    2576             : #if DEBUG_RHN_LIST
    2577             :         print_rhn_list(__func__, "LEAVE ");
    2578             : #endif
    2579           0 :         VNC_RHNCK(leave);
    2580             : }
    2581             : 
    2582             : /*
    2583             :  * "Withdrawing a Route" import process
    2584             :  */
    2585           5 : void vnc_import_bgp_del_route(struct bgp *bgp, const struct prefix *prefix,
    2586             :                               struct bgp_path_info *info) /* unicast info */
    2587             : {
    2588           5 :         afi_t afi = family2afi(prefix->family);
    2589             : 
    2590           5 :         assert(afi);
    2591             : 
    2592             :         {
    2593           5 :                 struct prefix pfx_nexthop;
    2594             : 
    2595           5 :                 rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_nexthop);
    2596           5 :                 vnc_zlog_debug_verbose("%s: pfx %pFX, nh %pFX", __func__,
    2597             :                                        prefix, &pfx_nexthop);
    2598             :         }
    2599             : #if DEBUG_RHN_LIST
    2600             :         print_rhn_list(__func__, "ENTER ");
    2601             : #endif
    2602           5 :         VNC_RHNCK(enter);
    2603             : 
    2604           5 :         if (!bgp->rfapi_cfg) {
    2605           0 :                 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
    2606             :                                        __func__);
    2607           0 :                 return;
    2608             :         }
    2609             : 
    2610             :         /* check bgp redist flag for vnc direct ("vpn") routes */
    2611           5 :         if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
    2612           5 :                 vnc_zlog_debug_verbose(
    2613             :                         "%s: bgp redistribution of afi=%d VNC direct routes is off",
    2614             :                         __func__, afi);
    2615           5 :                 return;
    2616             :         }
    2617             : 
    2618           0 :         switch (bgp->rfapi_cfg->redist_mode) {
    2619           0 :         case VNC_REDIST_MODE_PLAIN:
    2620           0 :                 vnc_import_bgp_del_route_mode_plain(bgp, prefix, info);
    2621           0 :                 break;
    2622             : 
    2623           0 :         case VNC_REDIST_MODE_RFG:
    2624           0 :                 if (bgp->rfapi_cfg->rfg_redist)
    2625           0 :                         vnc_import_bgp_del_route_mode_nvegroup(bgp, prefix,
    2626             :                                                                info);
    2627             :                 else
    2628           0 :                         vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
    2629             :                                                __func__);
    2630             :                 break;
    2631             : 
    2632           0 :         case VNC_REDIST_MODE_RESOLVE_NVE:
    2633           0 :                 vnc_import_bgp_del_route_mode_resolve_nve(bgp, afi, prefix,
    2634             :                                                           info);
    2635           0 :                 break;
    2636             :         }
    2637             : #if DEBUG_RHN_LIST
    2638             :         print_rhn_list(__func__, "LEAVE ");
    2639             : #endif
    2640           0 :         VNC_RHNCK(leave);
    2641             : }
    2642             : 
    2643             : 
    2644             : /***********************************************************************
    2645             :  *                      Enable/Disable
    2646             :  ***********************************************************************/
    2647             : 
    2648           0 : void vnc_import_bgp_redist_enable(struct bgp *bgp, afi_t afi)
    2649             : {
    2650             :         /* iterate over bgp unicast v4 and v6 routes, call
    2651             :          * vnc_import_bgp_add_route */
    2652             : 
    2653           0 :         struct bgp_dest *dest;
    2654             : 
    2655           0 :         vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
    2656             : 
    2657           0 :         if (bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
    2658           0 :                 vnc_zlog_debug_verbose(
    2659             :                         "%s: already enabled for afi %d, skipping", __func__,
    2660             :                         afi);
    2661           0 :                 return;
    2662             :         }
    2663           0 :         bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT] = 1;
    2664             : 
    2665           0 :         for (dest = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); dest;
    2666           0 :              dest = bgp_route_next(dest)) {
    2667             : 
    2668           0 :                 struct bgp_path_info *bpi;
    2669             : 
    2670           0 :                 for (bpi = bgp_dest_get_bgp_path_info(dest); bpi;
    2671           0 :                      bpi = bpi->next) {
    2672             : 
    2673           0 :                         if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
    2674           0 :                                 continue;
    2675             : 
    2676           0 :                         vnc_import_bgp_add_route(bgp, bgp_dest_get_prefix(dest),
    2677             :                                                  bpi);
    2678             :                 }
    2679             :         }
    2680           0 :         vnc_zlog_debug_verbose(
    2681             :                 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
    2682             :                 __func__, afi, ZEBRA_ROUTE_BGP_DIRECT);
    2683             : }
    2684             : 
    2685           0 : void vnc_import_bgp_exterior_redist_enable(struct bgp *bgp, afi_t afi)
    2686             : {
    2687           0 :         struct bgp *bgp_exterior;
    2688           0 :         struct bgp_dest *dest;
    2689             : 
    2690           0 :         bgp_exterior = bgp->rfapi_cfg->redist_bgp_exterior_view;
    2691             : 
    2692           0 :         if (bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
    2693           0 :                 vnc_zlog_debug_verbose(
    2694             :                         "%s: already enabled for afi %d, skipping", __func__,
    2695             :                         afi);
    2696           0 :                 return;
    2697             :         }
    2698           0 :         bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT] = 1;
    2699             : 
    2700           0 :         if (!bgp_exterior) {
    2701           0 :                 vnc_zlog_debug_verbose(
    2702             :                         "%s: no exterior view set yet, no routes to import yet",
    2703             :                         __func__);
    2704           0 :                 return;
    2705             :         }
    2706             : 
    2707           0 :         for (dest = bgp_table_top(bgp_exterior->rib[afi][SAFI_UNICAST]); dest;
    2708           0 :              dest = bgp_route_next(dest)) {
    2709             : 
    2710           0 :                 struct bgp_path_info *bpi;
    2711             : 
    2712           0 :                 for (bpi = bgp_dest_get_bgp_path_info(dest); bpi;
    2713           0 :                      bpi = bpi->next) {
    2714             : 
    2715           0 :                         if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
    2716           0 :                                 continue;
    2717             : 
    2718           0 :                         vnc_import_bgp_exterior_add_route(
    2719             :                                 bgp_exterior, bgp_dest_get_prefix(dest), bpi);
    2720             :                 }
    2721             :         }
    2722           0 :         vnc_zlog_debug_verbose(
    2723             :                 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
    2724             :                 __func__, afi, ZEBRA_ROUTE_BGP_DIRECT);
    2725             : }
    2726             : 
    2727             : /*
    2728             :  * This function is for populating a newly-created Import Table
    2729             :  */
    2730           0 : void vnc_import_bgp_exterior_redist_enable_it(
    2731             :         struct bgp *bgp, afi_t afi, struct rfapi_import_table *it_only)
    2732             : {
    2733           0 :         struct bgp *bgp_exterior;
    2734           0 :         struct bgp_dest *dest;
    2735             : 
    2736           0 :         vnc_zlog_debug_verbose("%s: entry", __func__);
    2737             : 
    2738           0 :         bgp_exterior = bgp->rfapi_cfg->redist_bgp_exterior_view;
    2739             : 
    2740           0 :         if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
    2741           0 :                 vnc_zlog_debug_verbose("%s: not enabled for afi %d, skipping",
    2742             :                                        __func__, afi);
    2743           0 :                 return;
    2744             :         }
    2745             : 
    2746           0 :         if (!bgp_exterior) {
    2747           0 :                 vnc_zlog_debug_verbose(
    2748             :                         "%s: no exterior view set yet, no routes to import yet",
    2749             :                         __func__);
    2750           0 :                 return;
    2751             :         }
    2752             : 
    2753           0 :         for (dest = bgp_table_top(bgp_exterior->rib[afi][SAFI_UNICAST]); dest;
    2754           0 :              dest = bgp_route_next(dest)) {
    2755             : 
    2756           0 :                 struct bgp_path_info *bpi;
    2757             : 
    2758           0 :                 for (bpi = bgp_dest_get_bgp_path_info(dest); bpi;
    2759           0 :                      bpi = bpi->next) {
    2760             : 
    2761           0 :                         if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
    2762           0 :                                 continue;
    2763             : 
    2764           0 :                         vnc_import_bgp_exterior_add_route_it(
    2765             :                                 bgp_exterior, bgp_dest_get_prefix(dest), bpi,
    2766             :                                 it_only);
    2767             :                 }
    2768             :         }
    2769             : }
    2770             : 
    2771             : 
    2772           0 : void vnc_import_bgp_redist_disable(struct bgp *bgp, afi_t afi)
    2773             : {
    2774             :         /*
    2775             :          * iterate over vpn routes, find routes of type ZEBRA_ROUTE_BGP_DIRECT,
    2776             :          * delete (call timer expire immediately)
    2777             :          */
    2778           0 :         struct bgp_dest *dest1;
    2779           0 :         struct bgp_dest *dest2;
    2780             : 
    2781           0 :         vnc_zlog_debug_verbose("%s: entry", __func__);
    2782             : 
    2783           0 :         if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
    2784           0 :                 vnc_zlog_debug_verbose(
    2785             :                         "%s: already disabled for afi %d, skipping", __func__,
    2786             :                         afi);
    2787           0 :                 return;
    2788             :         }
    2789             : 
    2790             :         /*
    2791             :          * Two-level table for SAFI_MPLS_VPN
    2792             :          * Be careful when changing the things we iterate over
    2793             :          */
    2794           0 :         for (dest1 = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); dest1;
    2795           0 :              dest1 = bgp_route_next(dest1)) {
    2796           0 :                 const struct prefix *dest1_p;
    2797             : 
    2798           0 :                 if (!bgp_dest_has_bgp_path_info_data(dest1))
    2799           0 :                         continue;
    2800             : 
    2801           0 :                 dest1_p = bgp_dest_get_prefix(dest1);
    2802           0 :                 for (dest2 = bgp_table_top(bgp_dest_get_bgp_table_info(dest1));
    2803           0 :                      dest2; dest2 = bgp_route_next(dest2)) {
    2804           0 :                         const struct prefix *dest2_p =
    2805           0 :                                 bgp_dest_get_prefix(dest2);
    2806           0 :                         struct bgp_path_info *bpi;
    2807           0 :                         struct bgp_path_info *nextbpi;
    2808             : 
    2809           0 :                         for (bpi = bgp_dest_get_bgp_path_info(dest2); bpi;
    2810             :                              bpi = nextbpi) {
    2811             : 
    2812           0 :                                 nextbpi = bpi->next;
    2813             : 
    2814           0 :                                 if (bpi->type != ZEBRA_ROUTE_BGP_DIRECT)
    2815           0 :                                         continue;
    2816             : 
    2817           0 :                                 struct rfapi_descriptor *rfd;
    2818           0 :                                 vncHDBgpDirect.peer = bpi->peer;
    2819             : 
    2820           0 :                                 assert(bpi->extra);
    2821             : 
    2822           0 :                                 rfd = bpi->extra->vnc.export.rfapi_handle;
    2823             : 
    2824           0 :                                 vnc_zlog_debug_verbose(
    2825             :                                         "%s: deleting bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p [passing rfd=%p]",
    2826             :                                         __func__, bpi, bpi->peer, bpi->type,
    2827             :                                         bpi->sub_type,
    2828             :                                         (bpi->extra ? bpi->extra->vnc.export
    2829             :                                                               .rfapi_handle
    2830             :                                                     : NULL),
    2831             :                                         rfd);
    2832             : 
    2833           0 :                                 del_vnc_route(rfd, bpi->peer, bgp,
    2834             :                                               SAFI_MPLS_VPN, dest2_p,
    2835             :                                               (struct prefix_rd *)dest1_p,
    2836           0 :                                               bpi->type, bpi->sub_type, NULL,
    2837             :                                               1); /* kill */
    2838             : 
    2839           0 :                                 vncHDBgpDirect.peer = NULL;
    2840             :                         }
    2841             :                 }
    2842             :         }
    2843             :         /* Clear RHN list */
    2844           0 :         if (bgp->rfapi->resolve_nve_nexthop) {
    2845             :                 struct prefix_bag *pb;
    2846             :                 struct bgp_path_info *info;
    2847           0 :                 while (!skiplist_first(bgp->rfapi->resolve_nve_nexthop, NULL,
    2848             :                                        (void *)&pb)) {
    2849           0 :                         info = pb->ubpi;
    2850           0 :                         skiplist_delete_first(bgp->rfapi->resolve_nve_nexthop);
    2851           0 :                         bgp_path_info_unlock(info);
    2852             :                 }
    2853             :         }
    2854             : 
    2855           0 :         bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT] = 0;
    2856           0 :         vnc_zlog_debug_verbose("%s: return", __func__);
    2857             : }
    2858             : 
    2859             : 
    2860           0 : void vnc_import_bgp_exterior_redist_disable(struct bgp *bgp, afi_t afi)
    2861             : {
    2862           0 :         struct rfapi_cfg *hc = bgp->rfapi_cfg;
    2863           0 :         struct bgp *bgp_exterior = hc->redist_bgp_exterior_view;
    2864             : 
    2865           0 :         vnc_zlog_debug_verbose("%s: entry", __func__);
    2866             : 
    2867           0 :         if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
    2868           0 :                 vnc_zlog_debug_verbose(
    2869             :                         "%s: already disabled for afi %d, skipping", __func__,
    2870             :                         afi);
    2871           0 :                 return;
    2872             :         }
    2873             : 
    2874           0 :         if (!bgp_exterior) {
    2875           0 :                 vnc_zlog_debug_verbose(
    2876             :                         "%s: bgp exterior view not defined, skipping",
    2877             :                         __func__);
    2878           0 :                 return;
    2879             :         }
    2880             : 
    2881             : 
    2882             :         {
    2883           0 :                 struct bgp_dest *dest;
    2884           0 :                 for (dest = bgp_table_top(bgp_exterior->rib[afi][SAFI_UNICAST]);
    2885           0 :                      dest; dest = bgp_route_next(dest)) {
    2886             : 
    2887           0 :                         struct bgp_path_info *bpi;
    2888             : 
    2889           0 :                         for (bpi = bgp_dest_get_bgp_path_info(dest); bpi;
    2890           0 :                              bpi = bpi->next) {
    2891             : 
    2892           0 :                                 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
    2893           0 :                                         continue;
    2894             : 
    2895           0 :                                 vnc_import_bgp_exterior_del_route(
    2896             :                                         bgp_exterior, bgp_dest_get_prefix(dest),
    2897             :                                         bpi);
    2898             :                         }
    2899             :                 }
    2900             : #if DEBUG_RHN_LIST
    2901             :                 print_rhn_list(__func__, NULL);
    2902             : #endif
    2903             :         }
    2904             : 
    2905           0 :         bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT] = 0;
    2906           0 :         vnc_zlog_debug_verbose("%s: return", __func__);
    2907             : }

Generated by: LCOV version v1.16-topotato