back to topotato report
topotato coverage report
Current view: top level - bgpd/rfapi - vnc_export_bgp.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 10 824 1.2 %
Date: 2023-02-24 19:38:44 Functions: 3 35 8.6 %

          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_export_bgp.c
      23             :  * Purpose:     Export routes to BGP 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/stream.h"
      32             : #include "lib/memory.h"
      33             : #include "lib/linklist.h"
      34             : #include "lib/plist.h"
      35             : #include "lib/routemap.h"
      36             : #include "lib/lib_errors.h"
      37             : 
      38             : #include "bgpd/bgpd.h"
      39             : #include "bgpd/bgp_ecommunity.h"
      40             : #include "bgpd/bgp_attr.h"
      41             : #include "bgpd/bgp_aspath.h"
      42             : 
      43             : #include "bgpd/rfapi/vnc_export_bgp.h"
      44             : #include "bgpd/rfapi/vnc_export_bgp_p.h"
      45             : #include "bgpd/rfapi/vnc_export_table.h"
      46             : #include "bgpd/rfapi/bgp_rfapi_cfg.h"
      47             : #include "bgpd/rfapi/rfapi.h"
      48             : #include "bgpd/rfapi/rfapi_import.h"
      49             : #include "bgpd/rfapi/rfapi_private.h"
      50             : #include "bgpd/rfapi/rfapi_backend.h"
      51             : #include "bgpd/rfapi/rfapi_vty.h"
      52             : #include "bgpd/rfapi/vnc_debug.h"
      53             : 
      54             : 
      55             : static void vnc_direct_add_rn_group_rd(struct bgp *bgp,
      56             :                                        struct rfapi_nve_group_cfg *rfg,
      57             :                                        struct agg_node *rn, struct attr *attr,
      58             :                                        afi_t afi,
      59             :                                        struct rfapi_descriptor *irfd);
      60             : 
      61             : /***********************************************************************
      62             :  * Export methods that set nexthop to CE (from 5226 roo EC) BEGIN
      63             :  ***********************************************************************/
      64             : 
      65             : /*
      66             :  * Memory allocation approach: make a ghost attr that
      67             :  * has non-interned parts for the modifications. ghost attr
      68             :  * memory is allocated by caller.
      69             :  *
      70             :  *      - extract ce (=5226) EC and use as new nexthop
      71             :  *      - strip Tunnel Encap attr
      72             :  *      - copy all ECs
      73             :  */
      74           0 : static void encap_attr_export_ce(struct attr *new, struct attr *orig,
      75             :                                  struct prefix *use_nexthop)
      76             : {
      77             :         /*
      78             :          * Make "new" a ghost attr copy of "orig"
      79             :          */
      80           0 :         memset(new, 0, sizeof(struct attr));
      81           0 :         *new = *orig;
      82             : 
      83             :         /*
      84             :          * Set nexthop
      85             :          */
      86           0 :         switch (use_nexthop->family) {
      87           0 :         case AF_INET:
      88           0 :                 new->nexthop = use_nexthop->u.prefix4;
      89           0 :                 new->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; /* bytes */
      90           0 :                 new->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
      91           0 :                 break;
      92             : 
      93           0 :         case AF_INET6:
      94           0 :                 new->mp_nexthop_global = use_nexthop->u.prefix6;
      95           0 :                 new->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; /* bytes */
      96           0 :                 break;
      97             : 
      98             :         default:
      99           0 :                 assert(0);
     100             :                 break;
     101             :         }
     102             : 
     103             :         /*
     104             :          * Set MED
     105             :          *
     106             :          * Note that it will be deleted when BGP sends to any eBGP
     107             :          * peer unless PEER_FLAG_MED_UNCHANGED is set:
     108             :          *
     109             :          *          neighbor NEIGHBOR attribute-unchanged med
     110             :          */
     111           0 :         if (!CHECK_FLAG(new->flag, BGP_ATTR_MULTI_EXIT_DISC)) {
     112           0 :                 if (CHECK_FLAG(new->flag, BGP_ATTR_LOCAL_PREF)) {
     113           0 :                         if (new->local_pref > 255)
     114           0 :                                 new->med = 0;
     115             :                         else
     116           0 :                                 new->med = 255 - new->local_pref;
     117             :                 } else {
     118           0 :                         new->med = 255; /* shouldn't happen */
     119             :                 }
     120           0 :                 new->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
     121             :         }
     122             : 
     123             :         /*
     124             :          * "new" is now a ghost attr:
     125             :          *  - it owns an "extra" struct
     126             :          *  - it owns any non-interned parts
     127             :          *  - any references to interned parts are not counted
     128             :          *
     129             :          * Caller should, after using the attr, call:
     130             :          *  - bgp_attr_flush() to free non-interned parts
     131             :          */
     132           0 : }
     133             : 
     134           0 : static int getce(struct bgp *bgp, struct attr *attr, struct prefix *pfx_ce)
     135             : {
     136           0 :         uint8_t *ecp;
     137           0 :         uint32_t i;
     138           0 :         uint16_t localadmin = bgp->rfapi_cfg->resolve_nve_roo_local_admin;
     139           0 :         struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
     140             : 
     141           0 :         for (ecp = ecomm->val, i = 0; i < ecomm->size;
     142           0 :              ++i, ecp += ECOMMUNITY_SIZE) {
     143             : 
     144           0 :                 if (VNC_DEBUG(EXPORT_BGP_GETCE)) {
     145           0 :                         vnc_zlog_debug_any(
     146             :                                 "%s: %02x %02x %02x %02x %02x %02x %02x %02x",
     147             :                                 __func__, ecp[0], ecp[1], ecp[2], ecp[3],
     148             :                                 ecp[4], ecp[5], ecp[6], ecp[7]);
     149             :                 }
     150             : 
     151             :                 /*
     152             :                  * is it ROO?
     153             :                  */
     154           0 :                 if (ecp[0] != 1 || ecp[1] != 3) {
     155           0 :                         continue;
     156             :                 }
     157             : 
     158             :                 /*
     159             :                  * Match local admin value?
     160             :                  */
     161           0 :                 if (ecp[6] != ((localadmin & 0xff00) >> 8)
     162           0 :                     || ecp[7] != (localadmin & 0xff))
     163           0 :                         continue;
     164             : 
     165           0 :                 memset((uint8_t *)pfx_ce, 0, sizeof(*pfx_ce));
     166           0 :                 memcpy(&pfx_ce->u.prefix4, ecp + 2, 4);
     167           0 :                 pfx_ce->family = AF_INET;
     168           0 :                 pfx_ce->prefixlen = IPV4_MAX_BITLEN;
     169             : 
     170           0 :                 return 0;
     171             :         }
     172             :         return -1;
     173             : }
     174             : 
     175             : 
     176           0 : void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct agg_node *rn,
     177             :                                  struct bgp_path_info *bpi)
     178             : {
     179           0 :         struct attr *attr = bpi->attr;
     180           0 :         struct peer *peer = bpi->peer;
     181           0 :         const struct prefix *prefix = agg_node_get_prefix(rn);
     182           0 :         afi_t afi = family2afi(prefix->family);
     183           0 :         struct bgp_dest *udest;
     184           0 :         struct bgp_path_info *ubpi;
     185           0 :         struct attr hattr;
     186           0 :         struct attr *iattr;
     187           0 :         struct prefix ce_nexthop;
     188           0 :         struct prefix post_routemap_nexthop;
     189             : 
     190             : 
     191           0 :         if (!afi) {
     192           0 :                 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of route node",
     193             :                          __func__);
     194           0 :                 return;
     195             :         }
     196             : 
     197           0 :         if ((bpi->type != ZEBRA_ROUTE_BGP)
     198           0 :             || (bpi->sub_type != BGP_ROUTE_NORMAL
     199           0 :                 && bpi->sub_type != BGP_ROUTE_RFP
     200           0 :                 && bpi->sub_type != BGP_ROUTE_STATIC)) {
     201             : 
     202           0 :                 vnc_zlog_debug_verbose(
     203             :                         "%s: wrong route type/sub_type for export, skipping",
     204             :                         __func__);
     205           0 :                 return;
     206             :         }
     207             : 
     208             :         /* check bgp redist flag for vnc direct ("vpn") routes */
     209           0 :         if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
     210           0 :                 vnc_zlog_debug_verbose(
     211             :                         "%s: bgp redistribution of VNC direct routes is off",
     212             :                         __func__);
     213           0 :                 return;
     214             :         }
     215             : 
     216           0 :         if (!bgp->rfapi_cfg) {
     217           0 :                 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
     218             :                                        __func__);
     219           0 :                 return;
     220             :         }
     221             : 
     222           0 :         if (!VNC_EXPORT_BGP_CE_ENABLED(bgp->rfapi_cfg)) {
     223           0 :                 vnc_zlog_debug_verbose(
     224             :                         "%s: export-to-bgp ce mode not enabled, skipping",
     225             :                         __func__);
     226           0 :                 return;
     227             :         }
     228             : 
     229             :         /*
     230             :          * prefix list check
     231             :          */
     232           0 :         if (bgp->rfapi_cfg->plist_export_bgp[afi]) {
     233           0 :                 if (prefix_list_apply(bgp->rfapi_cfg->plist_export_bgp[afi],
     234             :                                       prefix)
     235             :                     == PREFIX_DENY) {
     236           0 :                         vnc_zlog_debug_verbose(
     237             :                                 "%s: prefix list denied, skipping", __func__);
     238           0 :                         return;
     239             :                 }
     240             :         }
     241             : 
     242             : 
     243             :         /*
     244             :          * Extract CE
     245             :          * This works only for IPv4 because IPv6 addresses are too big
     246             :          * to fit in an extended community
     247             :          */
     248           0 :         if (getce(bgp, attr, &ce_nexthop)) {
     249           0 :                 vnc_zlog_debug_verbose("%s: EC has no encoded CE, skipping",
     250             :                                        __func__);
     251           0 :                 return;
     252             :         }
     253             : 
     254             :         /*
     255             :          * Is this route already represented in the unicast RIB?
     256             :          * (look up prefix; compare route type, sub_type, peer, nexthop)
     257             :          */
     258           0 :         udest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST,
     259             :                                  prefix, NULL);
     260           0 :         for (ubpi = bgp_dest_get_bgp_path_info(udest); ubpi;
     261           0 :              ubpi = ubpi->next) {
     262           0 :                 struct prefix unicast_nexthop;
     263             : 
     264           0 :                 if (CHECK_FLAG(ubpi->flags, BGP_PATH_REMOVED))
     265           0 :                         continue;
     266             : 
     267           0 :                 rfapiUnicastNexthop2Prefix(afi, ubpi->attr, &unicast_nexthop);
     268             : 
     269           0 :                 if (ubpi->type == ZEBRA_ROUTE_VNC_DIRECT
     270           0 :                     && ubpi->sub_type == BGP_ROUTE_REDISTRIBUTE
     271           0 :                     && ubpi->peer == peer
     272           0 :                     && prefix_same(&unicast_nexthop, &ce_nexthop)) {
     273             : 
     274           0 :                         vnc_zlog_debug_verbose(
     275             :                                 "%s: already have matching exported unicast route, skipping",
     276             :                                 __func__);
     277           0 :                         return;
     278             :                 }
     279             :         }
     280             : 
     281             :         /*
     282             :          * Construct new attribute set with CE addr as
     283             :          * nexthop and without Tunnel Encap attr
     284             :          */
     285           0 :         encap_attr_export_ce(&hattr, attr, &ce_nexthop);
     286           0 :         if (bgp->rfapi_cfg->routemap_export_bgp) {
     287           0 :                 struct bgp_path_info info;
     288           0 :                 route_map_result_t ret;
     289             : 
     290           0 :                 memset(&info, 0, sizeof(info));
     291           0 :                 info.peer = peer;
     292           0 :                 info.attr = &hattr;
     293           0 :                 ret = route_map_apply(bgp->rfapi_cfg->routemap_export_bgp,
     294             :                                       prefix, &info);
     295           0 :                 if (ret == RMAP_DENYMATCH) {
     296           0 :                         bgp_attr_flush(&hattr);
     297           0 :                         return;
     298             :                 }
     299             :         }
     300             : 
     301           0 :         iattr = bgp_attr_intern(&hattr);
     302           0 :         bgp_attr_flush(&hattr);
     303             : 
     304             :         /*
     305             :          * Rule: disallow route-map alteration of next-hop, because it
     306             :          * would make it too difficult to keep track of the correspondence
     307             :          * between VPN routes and unicast routes.
     308             :          */
     309           0 :         rfapiUnicastNexthop2Prefix(afi, iattr, &post_routemap_nexthop);
     310             : 
     311           0 :         if (!prefix_same(&ce_nexthop, &post_routemap_nexthop)) {
     312           0 :                 vnc_zlog_debug_verbose(
     313             :                         "%s: route-map modification of nexthop not allowed, skipping",
     314             :                         __func__);
     315           0 :                 bgp_attr_unintern(&iattr);
     316           0 :                 return;
     317             :         }
     318             : 
     319           0 :         bgp_update(peer, prefix, 0, /* addpath_id */
     320             :                    iattr,          /* bgp_update copies this attr */
     321             :                    afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
     322             :                    BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
     323             :                    NULL, 0,                      /* tag not used for unicast */
     324             :                    0, NULL);                     /* EVPN not used */
     325           0 :         bgp_attr_unintern(&iattr);
     326             : }
     327             : 
     328             : 
     329             : /*
     330             :  * "Withdrawing a Route" export process
     331             :  */
     332           0 : void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct agg_node *rn,
     333             :                                  struct bgp_path_info *bpi)
     334             : {
     335           0 :         const struct prefix *p = agg_node_get_prefix(rn);
     336           0 :         afi_t afi = family2afi(p->family);
     337           0 :         struct bgp_path_info *vbpi;
     338           0 :         struct prefix ce_nexthop;
     339             : 
     340           0 :         if (!afi) {
     341           0 :                 flog_err(EC_LIB_DEVELOPMENT, "%s: bad afi", __func__);
     342           0 :                 return;
     343             :         }
     344             : 
     345             :         /* check bgp redist flag for vnc direct ("vpn") routes */
     346           0 :         if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
     347           0 :                 vnc_zlog_debug_verbose(
     348             :                         "%s: bgp redistribution of VNC direct routes is off",
     349             :                         __func__);
     350           0 :                 return;
     351             :         }
     352             : 
     353           0 :         if (!bgp->rfapi_cfg) {
     354           0 :                 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
     355             :                                        __func__);
     356           0 :                 return;
     357             :         }
     358           0 :         if (!VNC_EXPORT_BGP_CE_ENABLED(bgp->rfapi_cfg)) {
     359           0 :                 vnc_zlog_debug_verbose(
     360             :                         "%s: export-to-bgp ce mode not enabled, skipping",
     361             :                         __func__);
     362           0 :                 return;
     363             :         }
     364             : 
     365             :         /*
     366             :          * Extract CE
     367             :          * This works only for IPv4 because IPv6 addresses are too big
     368             :          * to fit in an extended community
     369             :          */
     370           0 :         if (getce(bgp, bpi->attr, &ce_nexthop)) {
     371           0 :                 vnc_zlog_debug_verbose("%s: EC has no encoded CE, skipping",
     372             :                                        __func__);
     373           0 :                 return;
     374             :         }
     375             : 
     376             :         /*
     377             :          * Look for other VPN routes with same prefix, same 5226 CE,
     378             :          * same peer. If at least one is present, don't remove the
     379             :          * route from the unicast RIB
     380             :          */
     381             : 
     382           0 :         for (vbpi = rn->info; vbpi; vbpi = vbpi->next) {
     383           0 :                 struct prefix ce;
     384           0 :                 if (bpi == vbpi)
     385           0 :                         continue;
     386           0 :                 if (bpi->peer != vbpi->peer)
     387           0 :                         continue;
     388           0 :                 if (getce(bgp, vbpi->attr, &ce))
     389           0 :                         continue;
     390           0 :                 if (prefix_same(&ce, &ce_nexthop)) {
     391           0 :                         vnc_zlog_debug_verbose(
     392             :                                 "%s: still have a route via CE, not deleting unicast",
     393             :                                 __func__);
     394           0 :                         return;
     395             :                 }
     396             :         }
     397             : 
     398             :         /*
     399             :          * withdraw the route
     400             :          */
     401           0 :         bgp_withdraw(bpi->peer, p, 0, /* addpath_id */
     402             :                      NULL,            /* attr, ignored */
     403             :                      afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
     404             :                      BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
     405             :                      NULL, 0, NULL); /* tag not used for unicast */
     406             : }
     407             : 
     408           0 : static void vnc_direct_bgp_vpn_enable_ce(struct bgp *bgp, afi_t afi)
     409             : {
     410           0 :         struct agg_node *rn;
     411           0 :         struct bgp_path_info *ri;
     412             : 
     413           0 :         vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
     414             : 
     415           0 :         if (!bgp)
     416             :                 return;
     417             : 
     418           0 :         if (!(bgp->rfapi_cfg))
     419             :                 return;
     420             : 
     421           0 :         if (!VNC_EXPORT_BGP_CE_ENABLED(bgp->rfapi_cfg)) {
     422           0 :                 vnc_zlog_debug_verbose(
     423             :                         "%s: export of CE routes not enabled, skipping",
     424             :                         __func__);
     425           0 :                 return;
     426             :         }
     427             : 
     428           0 :         if (afi != AFI_IP && afi != AFI_IP6) {
     429           0 :                 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
     430           0 :                 return;
     431             :         }
     432             : 
     433             :         /*
     434             :          * Go through entire ce import table and export to BGP unicast.
     435             :          */
     436           0 :         for (rn = agg_route_top(bgp->rfapi->it_ce->imported_vpn[afi]); rn;
     437           0 :              rn = agg_route_next(rn)) {
     438           0 :                 if (!rn->info)
     439           0 :                         continue;
     440             : 
     441           0 :                 vnc_zlog_debug_verbose("%s: checking prefix %pRN", __func__,
     442             :                                        rn);
     443             : 
     444           0 :                 for (ri = rn->info; ri; ri = ri->next) {
     445             : 
     446           0 :                         vnc_zlog_debug_verbose("%s: ri->sub_type: %d", __func__,
     447             :                                                ri->sub_type);
     448             : 
     449           0 :                         if (ri->sub_type == BGP_ROUTE_NORMAL
     450           0 :                             || ri->sub_type == BGP_ROUTE_RFP
     451           0 :                             || ri->sub_type == BGP_ROUTE_STATIC) {
     452             : 
     453           0 :                                 vnc_direct_bgp_add_route_ce(bgp, rn, ri);
     454             :                         }
     455             :                 }
     456             :         }
     457             : }
     458             : 
     459           0 : static void vnc_direct_bgp_vpn_disable_ce(struct bgp *bgp, afi_t afi)
     460             : {
     461           0 :         struct bgp_dest *dest;
     462             : 
     463           0 :         vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
     464             : 
     465           0 :         if (!bgp)
     466             :                 return;
     467             : 
     468           0 :         if (afi != AFI_IP && afi != AFI_IP6) {
     469           0 :                 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
     470           0 :                 return;
     471             :         }
     472             : 
     473             :         /*
     474             :          * Go through the entire BGP unicast table and remove routes that
     475             :          * originated from us
     476             :          */
     477           0 :         for (dest = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); dest;
     478           0 :              dest = bgp_route_next(dest)) {
     479             : 
     480           0 :                 struct bgp_path_info *ri;
     481           0 :                 struct bgp_path_info *next;
     482             : 
     483           0 :                 for (ri = bgp_dest_get_bgp_path_info(dest), next = NULL; ri;
     484             :                      ri = next) {
     485             : 
     486           0 :                         next = ri->next;
     487             : 
     488           0 :                         if (ri->type == ZEBRA_ROUTE_VNC_DIRECT
     489           0 :                             && ri->sub_type == BGP_ROUTE_REDISTRIBUTE) {
     490             : 
     491           0 :                                 bgp_withdraw(
     492             :                                         ri->peer, bgp_dest_get_prefix(dest),
     493             :                                         0,    /* addpath_id */
     494             :                                         NULL, /* ignored */
     495             :                                         AFI_IP, SAFI_UNICAST,
     496             :                                         ZEBRA_ROUTE_VNC_DIRECT,
     497             :                                         BGP_ROUTE_REDISTRIBUTE,
     498             :                                         NULL, /* RD not used for unicast */
     499             :                                         NULL, 0,
     500             :                                         NULL); /* tag not used for unicast */
     501             :                         }
     502             :                 }
     503             :         }
     504             : }
     505             : 
     506             : /***********************************************************************
     507             :  * Export methods that set nexthop to CE (from 5226 roo EC) END
     508             :  ***********************************************************************/
     509             : 
     510             : /***********************************************************************
     511             :  * Export methods that proxy nexthop BEGIN
     512             :  ***********************************************************************/
     513             : 
     514           0 : static struct ecommunity *vnc_route_origin_ecom(struct agg_node *rn)
     515             : {
     516           0 :         struct ecommunity *new;
     517           0 :         struct bgp_path_info *bpi;
     518             : 
     519           0 :         if (!rn->info)
     520             :                 return NULL;
     521             : 
     522           0 :         new = ecommunity_new();
     523             : 
     524           0 :         for (bpi = rn->info; bpi; bpi = bpi->next) {
     525             : 
     526           0 :                 struct ecommunity_val roec;
     527             : 
     528           0 :                 switch (BGP_MP_NEXTHOP_FAMILY(bpi->attr->mp_nexthop_len)) {
     529             :                 case AF_INET:
     530           0 :                         memset(&roec, 0, sizeof(roec));
     531           0 :                         roec.val[0] = 0x01;
     532           0 :                         roec.val[1] = 0x03;
     533           0 :                         memcpy(roec.val + 2,
     534             :                                &bpi->attr->mp_nexthop_global_in.s_addr, 4);
     535           0 :                         roec.val[6] = 0;
     536           0 :                         roec.val[7] = 0;
     537           0 :                         ecommunity_add_val(new, &roec, false, false);
     538           0 :                         break;
     539             :                 case AF_INET6:
     540             :                         /* No support for IPv6 addresses in extended communities
     541             :                          */
     542             :                         break;
     543             :                 }
     544             :         }
     545             : 
     546           0 :         if (!new->size) {
     547           0 :                 ecommunity_free(&new);
     548           0 :                 new = NULL;
     549             :         }
     550             : 
     551           0 :         return new;
     552             : }
     553             : 
     554           0 : static struct ecommunity *vnc_route_origin_ecom_single(struct in_addr *origin)
     555             : {
     556           0 :         struct ecommunity *new;
     557           0 :         struct ecommunity_val roec;
     558             : 
     559           0 :         memset(&roec, 0, sizeof(roec));
     560           0 :         roec.val[0] = 0x01;
     561           0 :         roec.val[1] = 0x03;
     562           0 :         memcpy(roec.val + 2, &origin->s_addr, 4);
     563           0 :         roec.val[6] = 0;
     564           0 :         roec.val[7] = 0;
     565             : 
     566           0 :         new = ecommunity_new();
     567           0 :         ecommunity_add_val(new, &roec, false, false);
     568             : 
     569           0 :         if (!new->size) {
     570           0 :                 ecommunity_free(&new);
     571           0 :                 new = NULL;
     572             :         }
     573             : 
     574           0 :         return new;
     575             : }
     576             : 
     577             : 
     578             : /*
     579             :  * New memory allocation approach: make a ghost attr that
     580             :  * has non-interned parts for the modifications. ghost attr
     581             :  * memory is allocated by caller.
     582             :  */
     583             : static int
     584           0 : encap_attr_export(struct attr *new, struct attr *orig,
     585             :                   struct prefix *new_nexthop,
     586             :                   struct agg_node *rn) /* for VN addrs for ecom list */
     587             :                                        /* if rn is 0, use route's nexthop */
     588             : {
     589           0 :         struct prefix orig_nexthop;
     590           0 :         struct prefix *use_nexthop;
     591           0 :         static struct ecommunity *ecom_ro;
     592             : 
     593           0 :         if (new_nexthop) {
     594             :                 use_nexthop = new_nexthop;
     595             :         } else {
     596           0 :                 use_nexthop = &orig_nexthop;
     597           0 :                 orig_nexthop.family =
     598           0 :                         BGP_MP_NEXTHOP_FAMILY(orig->mp_nexthop_len);
     599           0 :                 if (orig_nexthop.family == AF_INET) {
     600           0 :                         orig_nexthop.prefixlen = IPV4_MAX_BITLEN;
     601           0 :                         orig_nexthop.u.prefix4 = orig->mp_nexthop_global_in;
     602           0 :                 } else if (orig_nexthop.family == AF_INET6) {
     603           0 :                         orig_nexthop.prefixlen = IPV6_MAX_BITLEN;
     604           0 :                         orig_nexthop.u.prefix6 = orig->mp_nexthop_global;
     605             :                 } else {
     606             :                         return -1; /* FAIL - can't compute nexthop */
     607             :                 }
     608             :         }
     609             : 
     610             : 
     611             :         /*
     612             :          * Make "new" a ghost attr copy of "orig"
     613             :          */
     614           0 :         memset(new, 0, sizeof(struct attr));
     615           0 :         *new = *orig;
     616             : 
     617             :         /*
     618             :          * Set nexthop
     619             :          */
     620           0 :         switch (use_nexthop->family) {
     621           0 :         case AF_INET:
     622           0 :                 new->nexthop = use_nexthop->u.prefix4;
     623           0 :                 new->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; /* bytes */
     624           0 :                 new->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
     625           0 :                 break;
     626             : 
     627           0 :         case AF_INET6:
     628           0 :                 new->mp_nexthop_global = use_nexthop->u.prefix6;
     629           0 :                 new->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; /* bytes */
     630           0 :                 break;
     631             : 
     632             :         default:
     633           0 :                 assert(0);
     634             :                 break;
     635             :         }
     636             : 
     637           0 :         if (rn) {
     638           0 :                 ecom_ro = vnc_route_origin_ecom(rn);
     639             :         } else {
     640             :                 /* TBD  use lcom for IPv6 */
     641           0 :                 ecom_ro = vnc_route_origin_ecom_single(&use_nexthop->u.prefix4);
     642             :         }
     643           0 :         if (bgp_attr_get_ecommunity(new)) {
     644           0 :                 if (ecom_ro)
     645           0 :                         bgp_attr_set_ecommunity(
     646             :                                 new,
     647             :                                 ecommunity_merge(ecom_ro,
     648             :                                                  bgp_attr_get_ecommunity(new)));
     649             :         } else {
     650           0 :                 bgp_attr_set_ecommunity(new, ecom_ro);
     651             :         }
     652             : 
     653             :         /*
     654             :          * Set MED
     655             :          *
     656             :          * Note that it will be deleted when BGP sends to any eBGP
     657             :          * peer unless PEER_FLAG_MED_UNCHANGED is set:
     658             :          *
     659             :          *          neighbor NEIGHBOR attribute-unchanged med
     660             :          */
     661           0 :         if (!CHECK_FLAG(new->flag, BGP_ATTR_MULTI_EXIT_DISC)) {
     662           0 :                 if (CHECK_FLAG(new->flag, BGP_ATTR_LOCAL_PREF)) {
     663           0 :                         if (new->local_pref > 255)
     664           0 :                                 new->med = 0;
     665             :                         else
     666           0 :                                 new->med = 255 - new->local_pref;
     667             :                 } else {
     668           0 :                         new->med = 255; /* shouldn't happen */
     669             :                 }
     670           0 :                 new->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
     671             :         }
     672             : 
     673             :         /*
     674             :          * "new" is now a ghost attr:
     675             :          *  - it owns an "extra" struct
     676             :          *  - it owns any non-interned parts
     677             :          *  - any references to interned parts are not counted
     678             :          *
     679             :          * Caller should, after using the attr, call:
     680             :          *  - bgp_attr_flush() to free non-interned parts
     681             :          */
     682             : 
     683             :         return 0;
     684             : }
     685             : 
     686             : /*
     687             :  * "Adding a Route" export process
     688             :  */
     689           0 : void vnc_direct_bgp_add_prefix(struct bgp *bgp,
     690             :                                struct rfapi_import_table *import_table,
     691             :                                struct agg_node *rn)
     692             : {
     693           0 :         struct attr attr = {0};
     694           0 :         struct listnode *node, *nnode;
     695           0 :         struct rfapi_rfg_name *rfgn;
     696           0 :         const struct prefix *p = agg_node_get_prefix(rn);
     697           0 :         afi_t afi = family2afi(p->family);
     698             : 
     699           0 :         if (!afi) {
     700           0 :                 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of route node",
     701             :                          __func__);
     702           0 :                 return;
     703             :         }
     704             : 
     705             :         /* check bgp redist flag for vnc direct ("vpn") routes */
     706           0 :         if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
     707           0 :                 vnc_zlog_debug_verbose(
     708             :                         "%s: bgp redistribution of VNC direct routes is off",
     709             :                         __func__);
     710           0 :                 return;
     711             :         }
     712             : 
     713           0 :         if (!bgp->rfapi_cfg) {
     714           0 :                 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
     715             :                                        __func__);
     716           0 :                 return;
     717             :         }
     718             : 
     719           0 :         if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) {
     720           0 :                 vnc_zlog_debug_verbose(
     721             :                         "%s: export-to-bgp group mode not enabled, skipping",
     722             :                         __func__);
     723           0 :                 return;
     724             :         }
     725             : 
     726           0 :         if (!listcount(bgp->rfapi_cfg->rfg_export_direct_bgp_l)) {
     727           0 :                 vnc_zlog_debug_verbose(
     728             :                         "%s: no bgp-direct export nve group, skipping",
     729             :                         __func__);
     730           0 :                 return;
     731             :         }
     732             : 
     733           0 :         bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
     734             :         /* TBD set some configured med, see add_vnc_route() */
     735             : 
     736           0 :         vnc_zlog_debug_verbose(
     737             :                 "%s: looping over nve-groups in direct-bgp export list",
     738             :                 __func__);
     739             : 
     740           0 :         for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node,
     741             :                                nnode, rfgn)) {
     742             : 
     743           0 :                 struct listnode *ln;
     744             : 
     745             :                 /*
     746             :                  * If nve group is not defined yet, skip it
     747             :                  */
     748           0 :                 if (!rfgn->rfg)
     749           0 :                         continue;
     750             : 
     751             :                 /*
     752             :                  * If the nve group uses a different import table, skip it
     753             :                  */
     754           0 :                 if (import_table != rfgn->rfg->rfapi_import_table)
     755           0 :                         continue;
     756             : 
     757             :                 /*
     758             :                  * if no NVEs currently associated with this group, skip it
     759             :                  */
     760           0 :                 if (rfgn->rfg->type != RFAPI_GROUP_CFG_VRF && !rfgn->rfg->nves)
     761           0 :                         continue;
     762             : 
     763             :                 /*
     764             :                  * per-nve-group prefix list check
     765             :                  */
     766           0 :                 if (rfgn->rfg->plist_export_bgp[afi]) {
     767           0 :                         if (prefix_list_apply(rfgn->rfg->plist_export_bgp[afi],
     768             :                                               p)
     769             :                             == PREFIX_DENY)
     770             : 
     771           0 :                                 continue;
     772             :                 }
     773             : 
     774           0 :                 if (rfgn->rfg->type == RFAPI_GROUP_CFG_VRF) {
     775           0 :                         vnc_direct_add_rn_group_rd(bgp, rfgn->rfg, rn, &attr,
     776             :                                                    afi, rfgn->rfg->rfd);
     777             :                         /*
     778             :                          * yuck!
     779             :                          *  - but consistent with rest of function
     780             :                          */
     781           0 :                         continue;
     782             :                 }
     783             :                 /*
     784             :                  * For each NVE that is assigned to the export nve group,
     785             :                  * generate
     786             :                  * a route with that NVE as its next hop
     787             :                  */
     788           0 :                 for (ln = listhead(rfgn->rfg->nves); ln;
     789           0 :                      ln = listnextnode(ln)) {
     790           0 :                         vnc_direct_add_rn_group_rd(bgp, rfgn->rfg, rn, &attr,
     791           0 :                                                    afi, listgetdata(ln));
     792             :                 }
     793             :         }
     794             : 
     795           0 :         aspath_unintern(&attr.aspath);
     796             : }
     797             : 
     798             : /*
     799             :  * "Withdrawing a Route" export process
     800             :  */
     801           0 : void vnc_direct_bgp_del_prefix(struct bgp *bgp,
     802             :                                struct rfapi_import_table *import_table,
     803             :                                struct agg_node *rn)
     804             : {
     805           0 :         struct listnode *node, *nnode;
     806           0 :         struct rfapi_rfg_name *rfgn;
     807           0 :         const struct prefix *p = agg_node_get_prefix(rn);
     808           0 :         afi_t afi = family2afi(p->family);
     809             : 
     810           0 :         if (!afi) {
     811           0 :                 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi route node",
     812             :                          __func__);
     813           0 :                 return;
     814             :         }
     815             : 
     816             :         /* check bgp redist flag for vnc direct ("vpn") routes */
     817           0 :         if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
     818           0 :                 vnc_zlog_debug_verbose(
     819             :                         "%s: bgp redistribution of VNC direct routes is off",
     820             :                         __func__);
     821           0 :                 return;
     822             :         }
     823             : 
     824           0 :         if (!bgp->rfapi_cfg) {
     825           0 :                 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
     826             :                                        __func__);
     827           0 :                 return;
     828             :         }
     829             : 
     830           0 :         if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) {
     831           0 :                 vnc_zlog_debug_verbose(
     832             :                         "%s: export-to-bgp group mode not enabled, skipping",
     833             :                         __func__);
     834           0 :                 return;
     835             :         }
     836             : 
     837           0 :         if (!listcount(bgp->rfapi_cfg->rfg_export_direct_bgp_l)) {
     838           0 :                 vnc_zlog_debug_verbose(
     839             :                         "%s: no bgp-direct export nve group, skipping",
     840             :                         __func__);
     841           0 :                 return;
     842             :         }
     843             : 
     844           0 :         for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node,
     845             :                                nnode, rfgn)) {
     846             : 
     847           0 :                 struct listnode *ln;
     848             : 
     849             :                 /*
     850             :                  * If nve group is not defined yet, skip it
     851             :                  */
     852           0 :                 if (!rfgn->rfg)
     853           0 :                         continue;
     854             : 
     855             :                 /*
     856             :                  * if no NVEs currently associated with this group, skip it
     857             :                  */
     858           0 :                 if (rfgn->rfg->type != RFAPI_GROUP_CFG_VRF && !rfgn->rfg->nves)
     859           0 :                         continue;
     860             : 
     861             :                 /*
     862             :                  * If the nve group uses a different import table,
     863             :                  * skip it
     864             :                  */
     865           0 :                 if (import_table != rfgn->rfg->rfapi_import_table)
     866           0 :                         continue;
     867             : 
     868           0 :                 if (rfgn->rfg->type == RFAPI_GROUP_CFG_VRF) {
     869           0 :                         struct prefix nhp;
     870           0 :                         struct rfapi_descriptor *irfd;
     871             : 
     872           0 :                         irfd = rfgn->rfg->rfd;
     873             : 
     874           0 :                         if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
     875           0 :                                 continue;
     876             : 
     877           0 :                         bgp_withdraw(irfd->peer, p, /* prefix */
     878             :                                      0,             /* addpath_id */
     879             :                                      NULL,          /* attr, ignored */
     880             :                                      afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
     881             :                                      BGP_ROUTE_REDISTRIBUTE,
     882             :                                      NULL, /* RD not used for unicast */
     883             :                                      NULL, 0,
     884             :                                      NULL); /* tag not used for unicast */
     885             :                         /*
     886             :                          * yuck!
     887             :                          *  - but consistent with rest of function
     888             :                          */
     889           0 :                         continue;
     890             :                 }
     891             :                 /*
     892             :                  * For each NVE that is assigned to the export nve group,
     893             :                  * generate
     894             :                  * a route with that NVE as its next hop
     895             :                  */
     896           0 :                 for (ln = listhead(rfgn->rfg->nves); ln;
     897           0 :                      ln = listnextnode(ln)) {
     898             : 
     899           0 :                         struct prefix nhp;
     900           0 :                         struct rfapi_descriptor *irfd;
     901             : 
     902           0 :                         irfd = listgetdata(ln);
     903             : 
     904           0 :                         if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
     905           0 :                                 continue;
     906             : 
     907           0 :                         bgp_withdraw(irfd->peer, p, /* prefix */
     908             :                                      0,             /* addpath_id */
     909             :                                      NULL,          /* attr, ignored */
     910             :                                      afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
     911             :                                      BGP_ROUTE_REDISTRIBUTE,
     912             :                                      NULL, /* RD not used for unicast */
     913             :                                      NULL, 0,
     914             :                                      NULL); /* tag not used for unicast */
     915             :                 }
     916             :         }
     917             : }
     918             : 
     919           0 : void vnc_direct_bgp_add_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
     920             : {
     921           0 :         struct listnode *node, *nnode;
     922           0 :         struct rfapi_rfg_name *rfgn;
     923           0 :         struct rfapi_nve_group_cfg *rfg = rfd->rfg;
     924           0 :         afi_t afi = family2afi(rfd->vn_addr.addr_family);
     925             : 
     926           0 :         if (!afi) {
     927           0 :                 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of nve vn addr",
     928             :                          __func__);
     929           0 :                 return;
     930             :         }
     931             : 
     932           0 :         if (!bgp)
     933             :                 return;
     934           0 :         if (!bgp->rfapi_cfg) {
     935           0 :                 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
     936             :                                        __func__);
     937           0 :                 return;
     938             :         }
     939           0 :         if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) {
     940           0 :                 vnc_zlog_debug_verbose(
     941             :                         "%s: export-to-bgp group mode not enabled, skipping",
     942             :                         __func__);
     943           0 :                 return;
     944             :         }
     945             : 
     946           0 :         if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
     947           0 :                 vnc_zlog_debug_verbose(
     948             :                         "%s: bgp redistribution of VNC direct routes is off",
     949             :                         __func__);
     950           0 :                 return;
     951             :         }
     952             : 
     953             :         /*
     954             :          * Loop over the list of NVE-Groups configured for
     955             :          * exporting to direct-bgp and see if this new NVE's
     956             :          * group is among them.
     957             :          */
     958           0 :         for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node,
     959             :                                nnode, rfgn)) {
     960             : 
     961             :                 /*
     962             :                  * Yes, this NVE's group is configured for export to direct-bgp
     963             :                  */
     964           0 :                 if (rfgn->rfg == rfg) {
     965             : 
     966           0 :                         struct agg_table *rt = NULL;
     967           0 :                         struct agg_node *rn;
     968           0 :                         struct attr attr = {0};
     969           0 :                         struct rfapi_import_table *import_table;
     970             : 
     971             : 
     972           0 :                         import_table = rfg->rfapi_import_table;
     973             : 
     974           0 :                         if (afi == AFI_IP || afi == AFI_IP6) {
     975           0 :                                 rt = import_table->imported_vpn[afi];
     976             :                         } else {
     977           0 :                                 flog_err(EC_LIB_DEVELOPMENT, "%s: bad afi %d",
     978             :                                          __func__, afi);
     979           0 :                                 return;
     980             :                         }
     981             : 
     982           0 :                         bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
     983             :                         /* TBD set some configured med, see add_vnc_route() */
     984             : 
     985             :                         /*
     986             :                          * Walk the NVE-Group's VNC Import table
     987             :                          */
     988           0 :                         for (rn = agg_route_top(rt); rn;
     989           0 :                              rn = agg_route_next(rn)) {
     990             : 
     991           0 :                                 if (rn->info) {
     992             : 
     993           0 :                                         struct prefix nhp;
     994           0 :                                         struct rfapi_descriptor *irfd = rfd;
     995           0 :                                         struct attr hattr;
     996           0 :                                         struct attr *iattr;
     997           0 :                                         struct bgp_path_info info;
     998           0 :                                         const struct prefix *p =
     999           0 :                                                 agg_node_get_prefix(rn);
    1000             : 
    1001           0 :                                         if (rfapiRaddr2Qprefix(&irfd->vn_addr,
    1002             :                                                                &nhp))
    1003           0 :                                                 continue;
    1004             : 
    1005             :                                         /*
    1006             :                                          * per-nve-group prefix list check
    1007             :                                          */
    1008           0 :                                         if (rfgn->rfg->plist_export_bgp[afi]) {
    1009           0 :                                                 if (prefix_list_apply(
    1010             :                                                             rfgn->rfg->plist_export_bgp
    1011             :                                                                     [afi],
    1012             :                                                             p)
    1013             :                                                     == PREFIX_DENY)
    1014             : 
    1015           0 :                                                         continue;
    1016             :                                         }
    1017             : 
    1018             : 
    1019             :                                         /*
    1020             :                                          * Construct new attribute set with
    1021             :                                          * NVE's VN addr as
    1022             :                                          * nexthop and without Tunnel Encap attr
    1023             :                                          */
    1024           0 :                                         if (encap_attr_export(&hattr, &attr,
    1025             :                                                               &nhp, rn))
    1026           0 :                                                 continue;
    1027             : 
    1028           0 :                                         if (rfgn->rfg->routemap_export_bgp) {
    1029           0 :                                                 route_map_result_t ret;
    1030           0 :                                                 info.peer = irfd->peer;
    1031           0 :                                                 info.attr = &hattr;
    1032           0 :                                                 ret = route_map_apply(
    1033             :                                                         rfgn->rfg
    1034             :                                                                 ->routemap_export_bgp,
    1035             :                                                         p, &info);
    1036           0 :                                                 if (ret == RMAP_DENYMATCH) {
    1037           0 :                                                         bgp_attr_flush(&hattr);
    1038           0 :                                                         continue;
    1039             :                                                 }
    1040             :                                         }
    1041             : 
    1042           0 :                                         iattr = bgp_attr_intern(&hattr);
    1043           0 :                                         bgp_attr_flush(&hattr);
    1044           0 :                                         bgp_update(
    1045             :                                                 irfd->peer, p, /* prefix */
    1046             :                                                 0,             /* addpath_id */
    1047             :                                                 iattr, /* bgp_update copies
    1048             :                                                           it */
    1049             :                                                 afi, SAFI_UNICAST,
    1050             :                                                 ZEBRA_ROUTE_VNC_DIRECT,
    1051             :                                                 BGP_ROUTE_REDISTRIBUTE, NULL,
    1052             :                                                 /* RD not used for unicast */
    1053             :                                                 NULL,
    1054             :                                                 /* tag not used for unicast */
    1055             :                                                 0, 0, NULL); /* EVPN not used */
    1056             : 
    1057           0 :                                         bgp_attr_unintern(&iattr);
    1058             :                                 }
    1059             :                         }
    1060             : 
    1061           0 :                         aspath_unintern(&attr.aspath);
    1062             :                 }
    1063             :         }
    1064             : }
    1065             : 
    1066             : 
    1067           0 : void vnc_direct_bgp_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
    1068             : {
    1069           0 :         struct listnode *node, *nnode;
    1070           0 :         struct rfapi_rfg_name *rfgn;
    1071           0 :         struct rfapi_nve_group_cfg *rfg = rfd->rfg;
    1072           0 :         afi_t afi = family2afi(rfd->vn_addr.addr_family);
    1073             : 
    1074           0 :         if (!afi) {
    1075           0 :                 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of nve vn addr",
    1076             :                          __func__);
    1077           0 :                 return;
    1078             :         }
    1079             : 
    1080           0 :         if (!bgp)
    1081             :                 return;
    1082           0 :         if (!bgp->rfapi_cfg) {
    1083           0 :                 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
    1084             :                                        __func__);
    1085           0 :                 return;
    1086             :         }
    1087           0 :         if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) {
    1088           0 :                 vnc_zlog_debug_verbose(
    1089             :                         "%s: export-to-bgp group mode not enabled, skipping",
    1090             :                         __func__);
    1091           0 :                 return;
    1092             :         }
    1093             : 
    1094           0 :         if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
    1095           0 :                 vnc_zlog_debug_verbose(
    1096             :                         "%s: bgp redistribution of VNC direct routes is off",
    1097             :                         __func__);
    1098           0 :                 return;
    1099             :         }
    1100             : 
    1101             :         /*
    1102             :          * Loop over the list of NVE-Groups configured for
    1103             :          * exporting to direct-bgp and see if this new NVE's
    1104             :          * group is among them.
    1105             :          */
    1106           0 :         for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node,
    1107             :                                nnode, rfgn)) {
    1108             : 
    1109             :                 /*
    1110             :                  * Yes, this NVE's group is configured for export to direct-bgp
    1111             :                  */
    1112           0 :                 if (rfg && rfgn->rfg == rfg) {
    1113             : 
    1114           0 :                         struct agg_table *rt = NULL;
    1115           0 :                         struct agg_node *rn;
    1116           0 :                         struct rfapi_import_table *import_table;
    1117             : 
    1118           0 :                         import_table = rfg->rfapi_import_table;
    1119             : 
    1120           0 :                         if (afi == AFI_IP || afi == AFI_IP6) {
    1121           0 :                                 rt = import_table->imported_vpn[afi];
    1122             :                         } else {
    1123           0 :                                 flog_err(EC_LIB_DEVELOPMENT, "%s: bad afi %d",
    1124             :                                          __func__, afi);
    1125           0 :                                 return;
    1126             :                         }
    1127             : 
    1128             :                         /*
    1129             :                          * Walk the NVE-Group's VNC Import table
    1130             :                          */
    1131           0 :                         for (rn = agg_route_top(rt); rn;
    1132           0 :                              rn = agg_route_next(rn)) {
    1133             : 
    1134           0 :                                 if (rn->info) {
    1135           0 :                                         const struct prefix *p =
    1136           0 :                                                 agg_node_get_prefix(rn);
    1137           0 :                                         struct prefix nhp;
    1138           0 :                                         struct rfapi_descriptor *irfd = rfd;
    1139             : 
    1140           0 :                                         if (rfapiRaddr2Qprefix(&irfd->vn_addr,
    1141             :                                                                &nhp))
    1142           0 :                                                 continue;
    1143             : 
    1144           0 :                                         bgp_withdraw(irfd->peer, p, /* prefix */
    1145             :                                                      0,    /* addpath_id */
    1146             :                                                      NULL, /* attr, ignored */
    1147             :                                                      afi, SAFI_UNICAST,
    1148             :                                                      ZEBRA_ROUTE_VNC_DIRECT,
    1149             :                                                      BGP_ROUTE_REDISTRIBUTE,
    1150             :                                                      NULL, /* RD not used for
    1151             :                                                               unicast */
    1152             :                                                      NULL, 0, NULL); /* tag not
    1153             :                                                                      used for
    1154             :                                                                      unicast */
    1155             :                                 }
    1156             :                         }
    1157             :                 }
    1158             :         }
    1159             : }
    1160             : 
    1161           0 : static void vnc_direct_add_rn_group_rd(struct bgp *bgp,
    1162             :                                        struct rfapi_nve_group_cfg *rfg,
    1163             :                                        struct agg_node *rn, struct attr *attr,
    1164             :                                        afi_t afi, struct rfapi_descriptor *irfd)
    1165             : {
    1166           0 :         struct prefix nhp;
    1167           0 :         struct bgp_path_info info;
    1168           0 :         struct attr hattr;
    1169           0 :         struct attr *iattr;
    1170           0 :         const struct prefix *p = agg_node_get_prefix(rn);
    1171             : 
    1172           0 :         if (irfd == NULL && rfg->type != RFAPI_GROUP_CFG_VRF) {
    1173             :                 /* need new rfapi_handle, for peer strcture
    1174             :                  * -- based on vnc_add_vrf_prefi */
    1175           0 :                 assert(rfg->rfd == NULL);
    1176             : 
    1177           0 :                 if (!rfg->rt_export_list || !rfg->rfapi_import_table) {
    1178           0 :                         vnc_zlog_debug_verbose(
    1179             :                                 "%s: VRF \"%s\" is missing RT import/export configuration.",
    1180             :                                 __func__, rfg->name);
    1181           0 :                         return;
    1182             :                 }
    1183           0 :                 if (!rfg->rd.prefixlen) {
    1184           0 :                         vnc_zlog_debug_verbose(
    1185             :                                 "%s: VRF \"%s\" is missing RD configuration.",
    1186             :                                 __func__, rfg->name);
    1187           0 :                         return;
    1188             :                 }
    1189           0 :                 if (rfg->label > MPLS_LABEL_MAX) {
    1190           0 :                         vnc_zlog_debug_verbose(
    1191             :                                 "%s: VRF \"%s\" is missing default label configuration.",
    1192             :                                 __func__, rfg->name);
    1193           0 :                         return;
    1194             :                 }
    1195             : 
    1196           0 :                 irfd = XCALLOC(MTYPE_RFAPI_DESC,
    1197             :                                sizeof(struct rfapi_descriptor));
    1198           0 :                 irfd->bgp = bgp;
    1199           0 :                 rfg->rfd = irfd;
    1200             :                 /*
    1201             :                  * leave most fields empty as will get from (dynamic) config
    1202             :                  * when needed
    1203             :                  */
    1204           0 :                 irfd->default_tunneltype_option.type = BGP_ENCAP_TYPE_MPLS;
    1205           0 :                 irfd->cookie = rfg;
    1206           0 :                 if (rfg->vn_prefix.family
    1207           0 :                     && !CHECK_FLAG(rfg->flags, RFAPI_RFG_VPN_NH_SELF)) {
    1208           0 :                         rfapiQprefix2Raddr(&rfg->vn_prefix, &irfd->vn_addr);
    1209             :                 } else {
    1210           0 :                         memset(&irfd->vn_addr, 0, sizeof(struct rfapi_ip_addr));
    1211           0 :                         irfd->vn_addr.addr_family = AF_INET;
    1212           0 :                         irfd->vn_addr.addr.v4 = bgp->router_id;
    1213             :                 }
    1214           0 :                 irfd->un_addr = irfd->vn_addr; /* sigh, need something in UN for
    1215             :                                                 lookups */
    1216           0 :                 vnc_zlog_debug_verbose("%s: Opening RFD for VRF %s", __func__,
    1217             :                                        rfg->name);
    1218           0 :                 rfapi_init_and_open(bgp, irfd, rfg);
    1219             :         }
    1220             : 
    1221           0 :         if (irfd == NULL || rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
    1222           0 :                 return;
    1223             : 
    1224             :         /*
    1225             :          * Construct new attribute set with NVE's VN
    1226             :          * addr as
    1227             :          * nexthop and without Tunnel Encap attr
    1228             :          */
    1229           0 :         if (encap_attr_export(&hattr, attr, &nhp, rn))
    1230             :                 return;
    1231             : 
    1232           0 :         if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD)) {
    1233           0 :                 vnc_zlog_debug_any("%s: attr follows", __func__);
    1234           0 :                 rfapiPrintAttrPtrs(NULL, attr);
    1235           0 :                 vnc_zlog_debug_any("%s: hattr follows", __func__);
    1236           0 :                 rfapiPrintAttrPtrs(NULL, &hattr);
    1237             :         }
    1238             : 
    1239           0 :         if (rfg->routemap_export_bgp) {
    1240           0 :                 route_map_result_t ret;
    1241             : 
    1242           0 :                 info.peer = irfd->peer;
    1243           0 :                 info.attr = &hattr;
    1244           0 :                 ret = route_map_apply(rfg->routemap_export_bgp, p, &info);
    1245           0 :                 if (ret == RMAP_DENYMATCH) {
    1246           0 :                         bgp_attr_flush(&hattr);
    1247           0 :                         vnc_zlog_debug_verbose(
    1248             :                                 "%s: route map says DENY, so not calling bgp_update",
    1249             :                                 __func__);
    1250           0 :                         return;
    1251             :                 }
    1252             :         }
    1253             : 
    1254           0 :         if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD)) {
    1255           0 :                 vnc_zlog_debug_any("%s: hattr after route_map_apply:",
    1256             :                                    __func__);
    1257           0 :                 rfapiPrintAttrPtrs(NULL, &hattr);
    1258             :         }
    1259           0 :         iattr = bgp_attr_intern(&hattr);
    1260           0 :         bgp_attr_flush(&hattr);
    1261             : 
    1262           0 :         bgp_update(irfd->peer, p, /* prefix */
    1263             :                    0,             /* addpath_id */
    1264             :                    iattr,         /* bgp_update copies it */
    1265             :                    afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
    1266             :                    BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
    1267             :                    NULL,                         /* tag not used for unicast */
    1268             :                    0, 0, NULL);                  /* EVPN not used */
    1269             : 
    1270           0 :         bgp_attr_unintern(&iattr);
    1271             : 
    1272           0 :         return;
    1273             : }
    1274             : 
    1275             : /*
    1276             :  * Caller is responsible for ensuring that the specified nve-group
    1277             :  * is actually part of the list of exported nve groups.
    1278             :  */
    1279           0 : static void vnc_direct_bgp_add_group_afi(struct bgp *bgp,
    1280             :                                          struct rfapi_nve_group_cfg *rfg,
    1281             :                                          afi_t afi)
    1282             : {
    1283           0 :         struct agg_table *rt = NULL;
    1284           0 :         struct agg_node *rn;
    1285           0 :         struct attr attr = {0};
    1286           0 :         struct rfapi_import_table *import_table;
    1287             : 
    1288           0 :         vnc_zlog_debug_verbose("%s: entry", __func__);
    1289             : 
    1290           0 :         import_table = rfg->rfapi_import_table;
    1291           0 :         if (!import_table) {
    1292           0 :                 vnc_zlog_debug_verbose(
    1293             :                         "%s: import table not defined, returning", __func__);
    1294           0 :                 return;
    1295             :         }
    1296             : 
    1297           0 :         if (afi == AFI_IP || afi == AFI_IP6) {
    1298           0 :                 rt = import_table->imported_vpn[afi];
    1299             :         } else {
    1300           0 :                 flog_err(EC_LIB_DEVELOPMENT, "%s: bad afi %d", __func__, afi);
    1301           0 :                 return;
    1302             :         }
    1303             : 
    1304           0 :         if (!rfg->nves && rfg->type != RFAPI_GROUP_CFG_VRF) {
    1305           0 :                 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__);
    1306           0 :                 return;
    1307             :         }
    1308             : 
    1309           0 :         bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
    1310             :         /* TBD set some configured med, see add_vnc_route() */
    1311             : 
    1312             :         /*
    1313             :          * Walk the NVE-Group's VNC Import table
    1314             :          */
    1315           0 :         for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) {
    1316             : 
    1317           0 :                 if (rn->info) {
    1318           0 :                         const struct prefix *p = agg_node_get_prefix(rn);
    1319           0 :                         struct listnode *ln;
    1320             : 
    1321             :                         /*
    1322             :                          * per-nve-group prefix list check
    1323             :                          */
    1324           0 :                         if (rfg->plist_export_bgp[afi]) {
    1325           0 :                                 if (prefix_list_apply(
    1326             :                                             rfg->plist_export_bgp[afi], p)
    1327             :                                     == PREFIX_DENY)
    1328             : 
    1329           0 :                                         continue;
    1330             :                         }
    1331           0 :                         if (rfg->type == RFAPI_GROUP_CFG_VRF) {
    1332           0 :                                 vnc_direct_add_rn_group_rd(bgp, rfg, rn, &attr,
    1333             :                                                            afi, rfg->rfd);
    1334             :                                 /*
    1335             :                                  * yuck!
    1336             :                                  *  - but consistent with rest of function
    1337             :                                  */
    1338           0 :                                 continue;
    1339             :                         }
    1340             :                         /*
    1341             :                          * For each NVE that is assigned to the export nve
    1342             :                          * group, generate
    1343             :                          * a route with that NVE as its next hop
    1344             :                          */
    1345           0 :                         for (ln = listhead(rfg->nves); ln;
    1346           0 :                              ln = listnextnode(ln)) {
    1347           0 :                                 vnc_direct_add_rn_group_rd(bgp, rfg, rn, &attr,
    1348             :                                                            afi,
    1349           0 :                                                            listgetdata(ln));
    1350             :                         }
    1351             :                 }
    1352             :         }
    1353             : 
    1354           0 :         aspath_unintern(&attr.aspath);
    1355             : }
    1356             : 
    1357             : 
    1358             : /*
    1359             :  * Caller is responsible for ensuring that the specified nve-group
    1360             :  * is actually part of the list of exported nve groups.
    1361             :  */
    1362           0 : void vnc_direct_bgp_add_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
    1363             : {
    1364           0 :         vnc_direct_bgp_add_group_afi(bgp, rfg, AFI_IP);
    1365           0 :         vnc_direct_bgp_add_group_afi(bgp, rfg, AFI_IP6);
    1366           0 : }
    1367             : 
    1368           0 : static void vnc_direct_del_rn_group_rd(struct bgp *bgp,
    1369             :                                        struct rfapi_nve_group_cfg *rfg,
    1370             :                                        struct agg_node *rn, afi_t afi,
    1371             :                                        struct rfapi_descriptor *irfd)
    1372             : {
    1373           0 :         if (irfd == NULL)
    1374             :                 return;
    1375             : 
    1376           0 :         bgp_withdraw(irfd->peer, agg_node_get_prefix(rn), /* prefix */
    1377             :                      0,                                   /* addpath_id */
    1378             :                      NULL,                                /* attr, ignored */
    1379             :                      afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
    1380             :                      BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
    1381             :                      NULL, 0, NULL); /* tag not used for unicast */
    1382           0 :         return;
    1383             : }
    1384             : 
    1385             : /*
    1386             :  * Caller is responsible for ensuring that the specified nve-group
    1387             :  * was actually part of the list of exported nve groups.
    1388             :  */
    1389           0 : static void vnc_direct_bgp_del_group_afi(struct bgp *bgp,
    1390             :                                          struct rfapi_nve_group_cfg *rfg,
    1391             :                                          afi_t afi)
    1392             : {
    1393           0 :         struct agg_table *rt = NULL;
    1394           0 :         struct agg_node *rn;
    1395           0 :         struct rfapi_import_table *import_table;
    1396             : 
    1397           0 :         vnc_zlog_debug_verbose("%s: entry", __func__);
    1398             : 
    1399           0 :         import_table = rfg->rfapi_import_table;
    1400           0 :         if (!import_table) {
    1401           0 :                 vnc_zlog_debug_verbose(
    1402             :                         "%s: import table not defined, returning", __func__);
    1403           0 :                 return;
    1404             :         }
    1405             : 
    1406           0 :         rt = import_table->imported_vpn[afi];
    1407             : 
    1408           0 :         if (!rfg->nves && rfg->type != RFAPI_GROUP_CFG_VRF) {
    1409           0 :                 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__);
    1410           0 :                 return;
    1411             :         }
    1412             : 
    1413             :         /*
    1414             :          * Walk the NVE-Group's VNC Import table
    1415             :          */
    1416           0 :         for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn))
    1417           0 :                 if (rn->info) {
    1418           0 :                         if (rfg->type == RFAPI_GROUP_CFG_VRF)
    1419           0 :                                 vnc_direct_del_rn_group_rd(bgp, rfg, rn, afi,
    1420             :                                                            rfg->rfd);
    1421             :                         else {
    1422           0 :                                 struct listnode *ln;
    1423             : 
    1424             :                                 /*
    1425             :                                  * For each NVE that is assigned to the export
    1426             :                                  * nve
    1427             :                                  * group, generate
    1428             :                                  * a route with that NVE as its next hop
    1429             :                                  */
    1430           0 :                                 for (ln = listhead(rfg->nves); ln;
    1431           0 :                                      ln = listnextnode(ln))
    1432           0 :                                         vnc_direct_del_rn_group_rd(
    1433             :                                                 bgp, rfg, rn, afi,
    1434           0 :                                                 listgetdata(ln));
    1435             :                         }
    1436             :                 }
    1437             : }
    1438             : 
    1439             : /*
    1440             :  * Caller is responsible for ensuring that the specified nve-group
    1441             :  * was actually part of the list of exported nve groups.
    1442             :  */
    1443           0 : void vnc_direct_bgp_del_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
    1444             : {
    1445           0 :         vnc_direct_bgp_del_group_afi(bgp, rfg, AFI_IP);
    1446           0 :         vnc_direct_bgp_del_group_afi(bgp, rfg, AFI_IP6);
    1447           0 : }
    1448             : 
    1449           0 : void vnc_direct_bgp_reexport_group_afi(struct bgp *bgp,
    1450             :                                        struct rfapi_nve_group_cfg *rfg,
    1451             :                                        afi_t afi)
    1452             : {
    1453           0 :         struct listnode *node;
    1454           0 :         struct rfapi_rfg_name *rfgn;
    1455             : 
    1456           0 :         if (VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) {
    1457             :                 /*
    1458             :                  * look in the list of currently-exported groups
    1459             :                  */
    1460           0 :                 for (ALL_LIST_ELEMENTS_RO(
    1461             :                              bgp->rfapi_cfg->rfg_export_direct_bgp_l, node,
    1462             :                              rfgn)) {
    1463             : 
    1464           0 :                         if (rfgn->rfg == rfg) {
    1465             :                                 /*
    1466             :                                  * If it matches, reexport it
    1467             :                                  */
    1468           0 :                                 vnc_direct_bgp_del_group_afi(bgp, rfg, afi);
    1469           0 :                                 vnc_direct_bgp_add_group_afi(bgp, rfg, afi);
    1470           0 :                                 break;
    1471             :                         }
    1472             :                 }
    1473             :         }
    1474           0 : }
    1475             : 
    1476             : 
    1477           0 : static void vnc_direct_bgp_unexport_table(afi_t afi, struct agg_table *rt,
    1478             :                                           struct list *nve_list)
    1479             : {
    1480           0 :         if (nve_list) {
    1481             : 
    1482           0 :                 struct agg_node *rn;
    1483             : 
    1484           0 :                 for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) {
    1485             : 
    1486           0 :                         if (rn->info) {
    1487             : 
    1488           0 :                                 struct listnode *hln;
    1489           0 :                                 struct rfapi_descriptor *irfd;
    1490             : 
    1491           0 :                                 for (ALL_LIST_ELEMENTS_RO(nve_list, hln,
    1492             :                                                           irfd)) {
    1493             : 
    1494           0 :                                         bgp_withdraw(irfd->peer,
    1495             :                                                      agg_node_get_prefix(rn),
    1496             :                                                      0,    /* addpath_id */
    1497             :                                                      NULL, /* attr, ignored */
    1498             :                                                      afi, SAFI_UNICAST,
    1499             :                                                      ZEBRA_ROUTE_VNC_DIRECT,
    1500             :                                                      BGP_ROUTE_REDISTRIBUTE,
    1501             :                                                      NULL, /* RD not used for
    1502             :                                                               unicast */
    1503             :                                                      NULL, 0, NULL); /* tag not
    1504             :                                                                      used for
    1505             :                                                                      unicast,
    1506             :                                                                      EVPN
    1507             :                                                                      neither */
    1508             :                                 }
    1509             :                         }
    1510             :                 }
    1511             :         }
    1512           0 : }
    1513             : 
    1514           0 : static void import_table_to_nve_list_direct_bgp(struct bgp *bgp,
    1515             :                                                 struct rfapi_import_table *it,
    1516             :                                                 struct list **nves,
    1517             :                                                 uint8_t family)
    1518             : {
    1519           0 :         struct listnode *node;
    1520           0 :         struct rfapi_rfg_name *rfgn;
    1521             : 
    1522             :         /*
    1523             :          * Loop over the list of NVE-Groups configured for
    1524             :          * exporting to direct-bgp.
    1525             :          *
    1526             :          * Build a list of NVEs that use this import table
    1527             :          */
    1528           0 :         *nves = NULL;
    1529           0 :         for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node,
    1530             :                                   rfgn)) {
    1531             : 
    1532             :                 /*
    1533             :                  * If this NVE-Group's import table matches the current one
    1534             :                  */
    1535           0 :                 if (rfgn->rfg && rfgn->rfg->rfapi_import_table == it) {
    1536           0 :                         if (rfgn->rfg->nves)
    1537           0 :                                 nve_group_to_nve_list(rfgn->rfg, nves, family);
    1538           0 :                         else if (rfgn->rfg->rfd
    1539           0 :                                  && rfgn->rfg->type == RFAPI_GROUP_CFG_VRF) {
    1540           0 :                                 if (!*nves)
    1541           0 :                                         *nves = list_new();
    1542           0 :                                 listnode_add(*nves, rfgn->rfg->rfd);
    1543             :                         }
    1544             :                 }
    1545             :         }
    1546           0 : }
    1547             : 
    1548           0 : void vnc_direct_bgp_vpn_enable(struct bgp *bgp, afi_t afi)
    1549             : {
    1550           0 :         struct listnode *rfgn;
    1551           0 :         struct rfapi_nve_group_cfg *rfg;
    1552             : 
    1553           0 :         if (!bgp)
    1554             :                 return;
    1555             : 
    1556           0 :         if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) {
    1557           0 :                 vnc_zlog_debug_verbose(
    1558             :                         "%s: export-to-bgp group mode not enabled, skipping",
    1559             :                         __func__);
    1560           0 :                 return;
    1561             :         }
    1562             : 
    1563           0 :         if (afi != AFI_IP && afi != AFI_IP6) {
    1564           0 :                 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
    1565           0 :                 return;
    1566             :         }
    1567             : 
    1568             :         /*
    1569             :          * Policy is applied per-nve-group, so we need to iterate
    1570             :          * over the groups to add everything.
    1571             :          */
    1572           0 :         for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->nve_groups_sequential, rfgn,
    1573             :                                   rfg)) {
    1574             : 
    1575             :                 /*
    1576             :                  * contains policy management
    1577             :                  */
    1578           0 :                 vnc_direct_bgp_add_group_afi(bgp, rfg, afi);
    1579             :         }
    1580             : }
    1581             : 
    1582             : 
    1583           0 : void vnc_direct_bgp_vpn_disable(struct bgp *bgp, afi_t afi)
    1584             : {
    1585           0 :         struct rfapi_import_table *it;
    1586           0 :         uint8_t family = afi2family(afi);
    1587             : 
    1588           0 :         vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
    1589             : 
    1590           0 :         if (!bgp)
    1591             :                 return;
    1592             : 
    1593           0 :         if (!bgp->rfapi) {
    1594           0 :                 vnc_zlog_debug_verbose("%s: rfapi not initialized", __func__);
    1595           0 :                 return;
    1596             :         }
    1597             : 
    1598           0 :         if (!family || (afi != AFI_IP && afi != AFI_IP6)) {
    1599           0 :                 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
    1600           0 :                 return;
    1601             :         }
    1602             : 
    1603           0 :         for (it = bgp->rfapi->imports; it; it = it->next) {
    1604             : 
    1605           0 :                 struct list *nve_list = NULL;
    1606             : 
    1607           0 :                 import_table_to_nve_list_direct_bgp(bgp, it, &nve_list, family);
    1608             : 
    1609           0 :                 if (nve_list) {
    1610           0 :                         vnc_direct_bgp_unexport_table(
    1611             :                                 afi, it->imported_vpn[afi], nve_list);
    1612           0 :                         list_delete(&nve_list);
    1613             :                 }
    1614             :         }
    1615             : }
    1616             : 
    1617             : 
    1618             : /***********************************************************************
    1619             :  * Export methods that proxy nexthop END
    1620             :  ***********************************************************************/
    1621             : 
    1622             : 
    1623             : /***********************************************************************
    1624             :  * Export methods that preserve original nexthop BEGIN
    1625             :  * rh = "registering nve"
    1626             :  ***********************************************************************/
    1627             : 
    1628             : 
    1629             : /*
    1630             :  * "Adding a Route" export process
    1631             :  * TBD do we need to check bpi->type and bpi->sub_type here, or does
    1632             :  * caller do it?
    1633             :  */
    1634           0 : void vnc_direct_bgp_rh_add_route(struct bgp *bgp, afi_t afi,
    1635             :                                  const struct prefix *prefix, struct peer *peer,
    1636             :                                  struct attr *attr)
    1637             : {
    1638           0 :         struct vnc_export_info *eti;
    1639           0 :         struct attr hattr;
    1640           0 :         struct rfapi_cfg *hc;
    1641           0 :         struct attr *iattr;
    1642             : 
    1643           0 :         if (!afi) {
    1644           0 :                 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of route node",
    1645             :                          __func__);
    1646           0 :                 return;
    1647             :         }
    1648             : 
    1649             :         /* check bgp redist flag for vnc direct ("vpn") routes */
    1650           0 :         if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
    1651           0 :                 vnc_zlog_debug_verbose(
    1652             :                         "%s: bgp redistribution of VNC direct routes is off",
    1653             :                         __func__);
    1654           0 :                 return;
    1655             :         }
    1656             : 
    1657           0 :         if (!(hc = bgp->rfapi_cfg)) {
    1658           0 :                 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
    1659             :                                        __func__);
    1660           0 :                 return;
    1661             :         }
    1662             : 
    1663           0 :         if (!VNC_EXPORT_BGP_RH_ENABLED(bgp->rfapi_cfg)) {
    1664           0 :                 vnc_zlog_debug_verbose(
    1665             :                         "%s: export-to-bgp RH mode not enabled, skipping",
    1666             :                         __func__);
    1667           0 :                 return;
    1668             :         }
    1669             : 
    1670             :         /*
    1671             :          * prefix list check
    1672             :          */
    1673           0 :         if (hc->plist_export_bgp[afi]) {
    1674           0 :                 if (prefix_list_apply(hc->plist_export_bgp[afi], prefix)
    1675             :                     == PREFIX_DENY)
    1676             :                         return;
    1677             :         }
    1678             : 
    1679             :         /*
    1680             :          * Construct new attribute set with NVE's VN addr as
    1681             :          * nexthop and without Tunnel Encap attr
    1682             :          */
    1683           0 :         if (encap_attr_export(&hattr, attr, NULL, NULL))
    1684             :                 return;
    1685           0 :         if (hc->routemap_export_bgp) {
    1686           0 :                 struct bgp_path_info info;
    1687           0 :                 route_map_result_t ret;
    1688             : 
    1689           0 :                 memset(&info, 0, sizeof(info));
    1690           0 :                 info.peer = peer;
    1691           0 :                 info.attr = &hattr;
    1692           0 :                 ret = route_map_apply(hc->routemap_export_bgp, prefix, &info);
    1693           0 :                 if (ret == RMAP_DENYMATCH) {
    1694           0 :                         bgp_attr_flush(&hattr);
    1695           0 :                         return;
    1696             :                 }
    1697             :         }
    1698             : 
    1699           0 :         iattr = bgp_attr_intern(&hattr);
    1700           0 :         bgp_attr_flush(&hattr);
    1701             : 
    1702             :         /*
    1703             :          * record route information that we will need to expire
    1704             :          * this route
    1705             :          */
    1706           0 :         eti = vnc_eti_get(bgp, EXPORT_TYPE_BGP, prefix, peer,
    1707             :                           ZEBRA_ROUTE_VNC_DIRECT_RH, BGP_ROUTE_REDISTRIBUTE);
    1708           0 :         rfapiGetVncLifetime(attr, &eti->lifetime);
    1709           0 :         eti->lifetime = rfapiGetHolddownFromLifetime(eti->lifetime);
    1710             : 
    1711             :         /*
    1712             :          * export expiration timer is already running on
    1713             :          * this route: cancel it
    1714             :          */
    1715           0 :         THREAD_OFF(eti->timer);
    1716             : 
    1717           0 :         bgp_update(peer, prefix, /* prefix */
    1718             :                    0,            /* addpath_id */
    1719             :                    iattr,       /* bgp_update copies this attr */
    1720             :                    afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT_RH,
    1721             :                    BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
    1722             :                    NULL,        /* tag not used for unicast, EVPN neither */
    1723             :                    0, 0, NULL); /* EVPN not used */
    1724           0 :         bgp_attr_unintern(&iattr);
    1725             : }
    1726             : 
    1727           0 : static void vncExportWithdrawTimer(struct thread *t)
    1728             : {
    1729           0 :         struct vnc_export_info *eti = THREAD_ARG(t);
    1730           0 :         const struct prefix *p = agg_node_get_prefix(eti->node);
    1731             : 
    1732             :         /*
    1733             :          * withdraw the route
    1734             :          */
    1735           0 :         bgp_withdraw(eti->peer, p, 0, /* addpath_id */
    1736             :                      NULL,            /* attr, ignored */
    1737           0 :                      family2afi(p->family), SAFI_UNICAST, eti->type,
    1738           0 :                      eti->subtype, NULL, /* RD not used for unicast */
    1739             :                      NULL, 0,
    1740             :                      NULL); /* tag not used for unicast, EVPN neither */
    1741             : 
    1742             :         /*
    1743             :          * Free the eti
    1744             :          */
    1745           0 :         vnc_eti_delete(eti);
    1746           0 : }
    1747             : 
    1748             : /*
    1749             :  * "Withdrawing a Route" export process
    1750             :  * TBD do we need to check bpi->type and bpi->sub_type here, or does
    1751             :  * caller do it?
    1752             :  */
    1753           0 : void vnc_direct_bgp_rh_del_route(struct bgp *bgp, afi_t afi,
    1754             :                                  const struct prefix *prefix, struct peer *peer)
    1755             : {
    1756           0 :         struct vnc_export_info *eti;
    1757             : 
    1758           0 :         if (!afi) {
    1759           0 :                 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi route node",
    1760             :                          __func__);
    1761           0 :                 return;
    1762             :         }
    1763             : 
    1764             :         /* check bgp redist flag for vnc direct ("vpn") routes */
    1765           0 :         if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
    1766           0 :                 vnc_zlog_debug_verbose(
    1767             :                         "%s: bgp redistribution of VNC direct routes is off",
    1768             :                         __func__);
    1769           0 :                 return;
    1770             :         }
    1771             : 
    1772           0 :         if (!bgp->rfapi_cfg) {
    1773           0 :                 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
    1774             :                                        __func__);
    1775           0 :                 return;
    1776             :         }
    1777           0 :         if (!VNC_EXPORT_BGP_RH_ENABLED(bgp->rfapi_cfg)) {
    1778           0 :                 vnc_zlog_debug_verbose(
    1779             :                         "%s: export-to-bgp group mode not enabled, skipping",
    1780             :                         __func__);
    1781           0 :                 return;
    1782             :         }
    1783             : 
    1784           0 :         eti = vnc_eti_get(bgp, EXPORT_TYPE_BGP, prefix, peer,
    1785             :                           ZEBRA_ROUTE_VNC_DIRECT_RH, BGP_ROUTE_REDISTRIBUTE);
    1786             : 
    1787           0 :         if (!eti->timer && eti->lifetime <= INT32_MAX) {
    1788           0 :                 eti->timer = NULL;
    1789           0 :                 thread_add_timer(bm->master, vncExportWithdrawTimer, eti,
    1790             :                                  eti->lifetime, &eti->timer);
    1791           0 :                 vnc_zlog_debug_verbose(
    1792             :                         "%s: set expiration timer for %u seconds", __func__,
    1793             :                         eti->lifetime);
    1794             :         }
    1795             : }
    1796             : 
    1797             : 
    1798           0 : void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi)
    1799             : {
    1800           0 :         struct prefix_rd prd;
    1801           0 :         struct bgp_dest *pdest;
    1802           0 :         struct rfapi_cfg *hc;
    1803             : 
    1804           0 :         vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
    1805             : 
    1806           0 :         if (!bgp)
    1807           0 :                 return;
    1808             : 
    1809           0 :         if (!(hc = bgp->rfapi_cfg))
    1810             :                 return;
    1811             : 
    1812           0 :         if (!VNC_EXPORT_BGP_RH_ENABLED(bgp->rfapi_cfg)) {
    1813           0 :                 vnc_zlog_debug_verbose(
    1814             :                         "%s: export of RH routes not enabled, skipping",
    1815             :                         __func__);
    1816           0 :                 return;
    1817             :         }
    1818             : 
    1819           0 :         if (afi != AFI_IP && afi != AFI_IP6) {
    1820           0 :                 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
    1821           0 :                 return;
    1822             :         }
    1823             : 
    1824             :         /*
    1825             :          * Go through the entire BGP VPN table and export to BGP unicast.
    1826             :          */
    1827             : 
    1828           0 :         vnc_zlog_debug_verbose("%s: starting RD loop", __func__);
    1829             : 
    1830             :         /* Loop over all the RDs */
    1831           0 :         for (pdest = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); pdest;
    1832           0 :              pdest = bgp_route_next(pdest)) {
    1833             : 
    1834           0 :                 struct bgp_table *table;
    1835           0 :                 struct bgp_dest *dest;
    1836           0 :                 struct bgp_path_info *ri;
    1837           0 :                 const struct prefix *pdest_p = bgp_dest_get_prefix(pdest);
    1838             : 
    1839           0 :                 memset(&prd, 0, sizeof(prd));
    1840           0 :                 prd.family = AF_UNSPEC;
    1841           0 :                 prd.prefixlen = 64;
    1842           0 :                 memcpy(prd.val, pdest_p->u.val, 8);
    1843             : 
    1844             :                 /* This is the per-RD table of prefixes */
    1845           0 :                 table = bgp_dest_get_bgp_table_info(pdest);
    1846             : 
    1847           0 :                 if (!table)
    1848           0 :                         continue;
    1849             : 
    1850           0 :                 for (dest = bgp_table_top(table); dest;
    1851           0 :                      dest = bgp_route_next(dest)) {
    1852           0 :                         const struct prefix *dest_p;
    1853             : 
    1854             :                         /*
    1855             :                          * skip prefix list check if no routes here
    1856             :                          */
    1857           0 :                         if (!bgp_dest_has_bgp_path_info_data(dest))
    1858           0 :                                 continue;
    1859             : 
    1860           0 :                         vnc_zlog_debug_verbose("%s: checking prefix %pBD",
    1861             :                                                __func__, dest);
    1862             : 
    1863           0 :                         dest_p = bgp_dest_get_prefix(dest);
    1864             : 
    1865             :                         /*
    1866             :                          * prefix list check
    1867             :                          */
    1868           0 :                         if (hc->plist_export_bgp[afi]) {
    1869           0 :                                 if (prefix_list_apply(hc->plist_export_bgp[afi],
    1870             :                                                       dest_p)
    1871             :                                     == PREFIX_DENY) {
    1872             : 
    1873           0 :                                         vnc_zlog_debug_verbose(
    1874             :                                                 "%s:   prefix list says DENY",
    1875             :                                                 __func__);
    1876           0 :                                         continue;
    1877             :                                 }
    1878             :                         }
    1879             : 
    1880           0 :                         for (ri = bgp_dest_get_bgp_path_info(dest); ri;
    1881           0 :                              ri = ri->next) {
    1882             : 
    1883           0 :                                 vnc_zlog_debug_verbose("%s: ri->sub_type: %d",
    1884             :                                                        __func__, ri->sub_type);
    1885             : 
    1886           0 :                                 if (ri->sub_type == BGP_ROUTE_NORMAL
    1887           0 :                                     || ri->sub_type == BGP_ROUTE_RFP) {
    1888             : 
    1889           0 :                                         struct vnc_export_info *eti;
    1890           0 :                                         struct attr hattr;
    1891           0 :                                         struct attr *iattr;
    1892             : 
    1893             :                                         /*
    1894             :                                          * Construct new attribute set with
    1895             :                                          * NVE's VN addr as
    1896             :                                          * nexthop and without Tunnel Encap attr
    1897             :                                          */
    1898           0 :                                         if (encap_attr_export(&hattr, ri->attr,
    1899             :                                                               NULL, NULL)) {
    1900           0 :                                                 vnc_zlog_debug_verbose(
    1901             :                                                         "%s:   encap_attr_export failed",
    1902             :                                                         __func__);
    1903           0 :                                                 continue;
    1904             :                                         }
    1905             : 
    1906           0 :                                         if (hc->routemap_export_bgp) {
    1907           0 :                                                 struct bgp_path_info info;
    1908           0 :                                                 route_map_result_t ret;
    1909             : 
    1910           0 :                                                 memset(&info, 0, sizeof(info));
    1911           0 :                                                 info.peer = ri->peer;
    1912           0 :                                                 info.attr = &hattr;
    1913           0 :                                                 ret = route_map_apply(
    1914             :                                                         hc->routemap_export_bgp,
    1915             :                                                         dest_p, &info);
    1916           0 :                                                 if (ret == RMAP_DENYMATCH) {
    1917           0 :                                                         bgp_attr_flush(&hattr);
    1918           0 :                                                         vnc_zlog_debug_verbose(
    1919             :                                                                 "%s:   route map says DENY",
    1920             :                                                                 __func__);
    1921           0 :                                                         continue;
    1922             :                                                 }
    1923             :                                         }
    1924             : 
    1925           0 :                                         iattr = bgp_attr_intern(&hattr);
    1926           0 :                                         bgp_attr_flush(&hattr);
    1927             : 
    1928             :                                         /*
    1929             :                                          * record route information that we will
    1930             :                                          * need to expire
    1931             :                                          * this route
    1932             :                                          */
    1933           0 :                                         eti = vnc_eti_get(
    1934             :                                                 bgp, EXPORT_TYPE_BGP, dest_p,
    1935             :                                                 ri->peer,
    1936             :                                                 ZEBRA_ROUTE_VNC_DIRECT_RH,
    1937             :                                                 BGP_ROUTE_REDISTRIBUTE);
    1938           0 :                                         rfapiGetVncLifetime(ri->attr,
    1939             :                                                             &eti->lifetime);
    1940             : 
    1941             :                                         /*
    1942             :                                          * export expiration timer is
    1943             :                                          * already running on
    1944             :                                          * this route: cancel it
    1945             :                                          */
    1946           0 :                                         THREAD_OFF(eti->timer);
    1947             : 
    1948           0 :                                         vnc_zlog_debug_verbose(
    1949             :                                                 "%s: calling bgp_update",
    1950             :                                                 __func__);
    1951             : 
    1952           0 :                                         bgp_update(
    1953             :                                                 ri->peer, dest_p, /* prefix */
    1954             :                                                 0,     /* addpath_id */
    1955             :                                                 iattr, /* bgp_update copies
    1956             :                                                           it */
    1957             :                                                 AFI_IP, SAFI_UNICAST,
    1958             :                                                 ZEBRA_ROUTE_VNC_DIRECT_RH,
    1959             :                                                 BGP_ROUTE_REDISTRIBUTE, NULL,
    1960             :                                                 /* RD not used for unicast */
    1961             :                                                 NULL,
    1962             :                                                 /* tag not used for unicast,
    1963             :                                                    or EVPN */
    1964             :                                                 0, 0, NULL); /* EVPN not used */
    1965             : 
    1966           0 :                                         bgp_attr_unintern(&iattr);
    1967             :                                 }
    1968             :                         }
    1969             :                 }
    1970             :         }
    1971             : }
    1972             : 
    1973           0 : void vnc_direct_bgp_rh_vpn_disable(struct bgp *bgp, afi_t afi)
    1974             : {
    1975           0 :         struct bgp_dest *dest;
    1976             : 
    1977           0 :         vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
    1978             : 
    1979           0 :         if (!bgp)
    1980             :                 return;
    1981             : 
    1982           0 :         if (afi != AFI_IP && afi != AFI_IP6) {
    1983           0 :                 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
    1984           0 :                 return;
    1985             :         }
    1986             : 
    1987             :         /*
    1988             :          * Go through the entire BGP unicast table and remove routes that
    1989             :          * originated from us
    1990             :          */
    1991           0 :         for (dest = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); dest;
    1992           0 :              dest = bgp_route_next(dest)) {
    1993           0 :                 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
    1994           0 :                 struct bgp_path_info *ri;
    1995           0 :                 struct bgp_path_info *next;
    1996             : 
    1997           0 :                 for (ri = bgp_dest_get_bgp_path_info(dest), next = NULL; ri;
    1998             :                      ri = next) {
    1999             : 
    2000           0 :                         next = ri->next;
    2001             : 
    2002           0 :                         if (ri->type == ZEBRA_ROUTE_VNC_DIRECT_RH
    2003           0 :                             && ri->sub_type == BGP_ROUTE_REDISTRIBUTE) {
    2004             : 
    2005           0 :                                 struct vnc_export_info *eti;
    2006             : 
    2007             :                                 /*
    2008             :                                  * Delete routes immediately (no timer)
    2009             :                                  */
    2010           0 :                                 eti = vnc_eti_checktimer(
    2011             :                                         bgp, EXPORT_TYPE_BGP, dest_p, ri->peer,
    2012             :                                         ZEBRA_ROUTE_VNC_DIRECT_RH,
    2013             :                                         BGP_ROUTE_REDISTRIBUTE);
    2014           0 :                                 if (eti) {
    2015           0 :                                         THREAD_OFF(eti->timer);
    2016           0 :                                         vnc_eti_delete(eti);
    2017             :                                 }
    2018             : 
    2019           0 :                                 bgp_withdraw(ri->peer, dest_p, /* prefix */
    2020             :                                              0,                /* addpath_id */
    2021             :                                              NULL,             /* ignored */
    2022             :                                              AFI_IP, SAFI_UNICAST,
    2023             :                                              ZEBRA_ROUTE_VNC_DIRECT_RH,
    2024             :                                              BGP_ROUTE_REDISTRIBUTE,
    2025             :                                              NULL, /* RD not used for unicast */
    2026             :                                              NULL, 0, NULL); /* tag not used for
    2027             :                                                              unicast, EVPN
    2028             :                                                              neither */
    2029             :                         }
    2030             :                 }
    2031             :         }
    2032             : }
    2033             : 
    2034           0 : void vnc_direct_bgp_rh_reexport(struct bgp *bgp, afi_t afi)
    2035             : {
    2036           0 :         if (VNC_EXPORT_BGP_RH_ENABLED(bgp->rfapi_cfg)) {
    2037           0 :                 vnc_direct_bgp_rh_vpn_disable(bgp, afi);
    2038           0 :                 vnc_direct_bgp_rh_vpn_enable(bgp, afi);
    2039             :         }
    2040           0 : }
    2041             : 
    2042             : /***********************************************************************
    2043             :  * Generic Export methods
    2044             :  ***********************************************************************/
    2045             : 
    2046             : /*
    2047             :  * Assumes the correct mode bits are already turned on. Thus it
    2048             :  * is OK to call this function from, e.g., bgp_redistribute_set()
    2049             :  * without caring if export is enabled or not
    2050             :  */
    2051          26 : void vnc_export_bgp_enable(struct bgp *bgp, afi_t afi)
    2052             : {
    2053          26 :         if (!bgp->rfapi_cfg)
    2054             :                 return;
    2055             : 
    2056          26 :         switch (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) {
    2057             :         case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE:
    2058             :                 break;
    2059             : 
    2060           0 :         case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP:
    2061           0 :                 vnc_direct_bgp_vpn_enable(bgp, afi);
    2062           0 :                 break;
    2063             : 
    2064           0 :         case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH:
    2065           0 :                 vnc_direct_bgp_rh_vpn_enable(bgp, afi);
    2066           0 :                 break;
    2067             : 
    2068           0 :         case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE:
    2069           0 :                 vnc_direct_bgp_vpn_enable_ce(bgp, afi);
    2070           0 :                 break;
    2071             :         }
    2072             : }
    2073             : 
    2074          26 : void vnc_export_bgp_disable(struct bgp *bgp, afi_t afi)
    2075             : {
    2076          26 :         if (!bgp->rfapi_cfg)
    2077             :                 return;
    2078             : 
    2079          26 :         switch (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) {
    2080             :         case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE:
    2081             :                 break;
    2082             : 
    2083           0 :         case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP:
    2084           0 :                 vnc_direct_bgp_vpn_disable(bgp, afi);
    2085           0 :                 break;
    2086             : 
    2087           0 :         case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH:
    2088           0 :                 vnc_direct_bgp_rh_vpn_disable(bgp, afi);
    2089           0 :                 break;
    2090             : 
    2091           0 :         case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE:
    2092           0 :                 vnc_direct_bgp_vpn_disable_ce(bgp, afi);
    2093           0 :                 break;
    2094             :         }
    2095             : }
    2096             : 
    2097           0 : void vnc_export_bgp_prechange(struct bgp *bgp)
    2098             : {
    2099           0 :         vnc_export_bgp_disable(bgp, AFI_IP);
    2100           0 :         vnc_export_bgp_disable(bgp, AFI_IP6);
    2101           0 : }
    2102             : 
    2103           0 : void vnc_export_bgp_postchange(struct bgp *bgp)
    2104             : {
    2105           0 :         vnc_export_bgp_enable(bgp, AFI_IP);
    2106           0 :         vnc_export_bgp_enable(bgp, AFI_IP6);
    2107           0 : }
    2108             : 
    2109          26 : void vnc_direct_bgp_reexport(struct bgp *bgp, afi_t afi)
    2110             : {
    2111          26 :         vnc_export_bgp_disable(bgp, afi);
    2112          26 :         vnc_export_bgp_enable(bgp, afi);
    2113          26 : }

Generated by: LCOV version v1.16-topotato