back to topotato report
topotato coverage report
Current view: top level - bgpd/rfapi - vnc_zebra.c (source / functions) Hit Total Coverage
Test: test_bgp_minimum_holdtime.py::TestBGPMinimumHoldtime Lines: 9 395 2.3 %
Date: 2023-02-24 18:37:25 Functions: 2 21 9.5 %

          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_zebra.c
      23             :  * Purpose:     Handle exchange of routes between VNC and Zebra
      24             :  */
      25             : 
      26             : #include "lib/zebra.h"
      27             : #include "lib/prefix.h"
      28             : #include "lib/agg_table.h"
      29             : #include "lib/log.h"
      30             : #include "lib/command.h"
      31             : #include "lib/zclient.h"
      32             : #include "lib/stream.h"
      33             : #include "lib/ringbuf.h"
      34             : #include "lib/memory.h"
      35             : #include "lib/lib_errors.h"
      36             : 
      37             : #include "bgpd/bgpd.h"
      38             : #include "bgpd/bgp_ecommunity.h"
      39             : #include "bgpd/bgp_route.h"
      40             : #include "bgpd/bgp_debug.h"
      41             : #include "bgpd/bgp_advertise.h"
      42             : 
      43             : #include "bgpd/rfapi/bgp_rfapi_cfg.h"
      44             : #include "bgpd/rfapi/rfapi.h"
      45             : #include "bgpd/rfapi/rfapi_import.h"
      46             : #include "bgpd/rfapi/rfapi_private.h"
      47             : #include "bgpd/rfapi/vnc_zebra.h"
      48             : #include "bgpd/rfapi/rfapi_vty.h"
      49             : #include "bgpd/rfapi/rfapi_backend.h"
      50             : #include "bgpd/rfapi/vnc_debug.h"
      51             : 
      52             : static struct rfapi_descriptor vncHD1VR; /* Single-VR export dummy nve descr */
      53             : static struct zclient *zclient_vnc = NULL;
      54             : 
      55             : /***********************************************************************
      56             :  *      REDISTRIBUTE: Zebra sends updates/withdraws to BGPD
      57             :  ***********************************************************************/
      58             : 
      59             : /*
      60             :  * Routes coming from zebra get added to VNC here
      61             :  */
      62           0 : static void vnc_redistribute_add(struct prefix *p, uint32_t metric,
      63             :                                  uint8_t type)
      64             : {
      65           0 :         struct bgp *bgp = bgp_get_default();
      66           0 :         struct prefix_rd prd;
      67           0 :         struct rfapi_ip_addr vnaddr;
      68           0 :         afi_t afi;
      69           0 :         uint32_t local_pref =
      70           0 :                 rfp_cost_to_localpref(metric > 255 ? 255 : metric);
      71             : 
      72           0 :         if (!bgp)
      73           0 :                 return;
      74             : 
      75           0 :         if (!bgp->rfapi_cfg) {
      76           0 :                 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
      77             :                                        __func__);
      78           0 :                 return;
      79             :         }
      80             : 
      81           0 :         afi = family2afi(p->family);
      82           0 :         if (!afi) {
      83           0 :                 vnc_zlog_debug_verbose("%s: unknown prefix address family %d",
      84             :                                        __func__, p->family);
      85           0 :                 return;
      86             :         }
      87             : 
      88           0 :         if (!bgp->rfapi_cfg->redist[afi][type]) {
      89           0 :                 vnc_zlog_debug_verbose(
      90             :                         "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d] is 0, skipping",
      91             :                         __func__, afi, type);
      92           0 :                 return;
      93             :         }
      94           0 :         if (!bgp->rfapi_cfg->rfg_redist) {
      95           0 :                 vnc_zlog_debug_verbose("%s: no redist nve group, skipping",
      96             :                                        __func__);
      97           0 :                 return;
      98             :         }
      99             : 
     100             :         /*
     101             :          * Assume nve group's configured VN address prefix is a host
     102             :          * route which also happens to give the NVE VN address to use
     103             :          * for redistributing into VNC.
     104             :          */
     105           0 :         vnaddr.addr_family = bgp->rfapi_cfg->rfg_redist->vn_prefix.family;
     106           0 :         switch (bgp->rfapi_cfg->rfg_redist->vn_prefix.family) {
     107           0 :         case AF_INET:
     108           0 :                 if (bgp->rfapi_cfg->rfg_redist->vn_prefix.prefixlen
     109             :                     != IPV4_MAX_BITLEN) {
     110           0 :                         vnc_zlog_debug_verbose(
     111             :                                 "%s: redist nve group VN prefix len (%d) != 32, skipping",
     112             :                                 __func__,
     113             :                                 bgp->rfapi_cfg->rfg_redist->vn_prefix
     114             :                                         .prefixlen);
     115           0 :                         return;
     116             :                 }
     117           0 :                 vnaddr.addr.v4 =
     118             :                         bgp->rfapi_cfg->rfg_redist->vn_prefix.u.prefix4;
     119           0 :                 break;
     120           0 :         case AF_INET6:
     121           0 :                 if (bgp->rfapi_cfg->rfg_redist->vn_prefix.prefixlen
     122             :                     != IPV6_MAX_BITLEN) {
     123           0 :                         vnc_zlog_debug_verbose(
     124             :                                 "%s: redist nve group VN prefix len (%d) != 128, skipping",
     125             :                                 __func__,
     126             :                                 bgp->rfapi_cfg->rfg_redist->vn_prefix
     127             :                                         .prefixlen);
     128           0 :                         return;
     129             :                 }
     130           0 :                 vnaddr.addr.v6 =
     131             :                         bgp->rfapi_cfg->rfg_redist->vn_prefix.u.prefix6;
     132           0 :                 break;
     133           0 :         default:
     134           0 :                 vnc_zlog_debug_verbose(
     135             :                         "%s: no redist nve group VN host prefix configured, skipping",
     136             :                         __func__);
     137             :                 return;
     138             :         }
     139             : 
     140             :         /*
     141             :          * Assume nve group's configured UN address prefix is a host
     142             :          * route which also happens to give the NVE UN address to use
     143             :          * for redistributing into VNC.
     144             :          */
     145             : 
     146             :         /*
     147             :          * Set UN address in dummy nve descriptor so add_vnc_route
     148             :          * can use it in VNC tunnel SubTLV
     149             :          */
     150             :         {
     151           0 :                 struct rfapi_ip_prefix pfx_un;
     152             : 
     153           0 :                 rfapiQprefix2Rprefix(&bgp->rfapi_cfg->rfg_redist->un_prefix,
     154             :                                      &pfx_un);
     155             : 
     156           0 :                 switch (pfx_un.prefix.addr_family) {
     157           0 :                 case AF_INET:
     158           0 :                         if (pfx_un.length != IPV4_MAX_BITLEN) {
     159           0 :                                 vnc_zlog_debug_verbose(
     160             :                                         "%s: redist nve group UN prefix len (%d) != 32, skipping",
     161             :                                         __func__, pfx_un.length);
     162           0 :                                 return;
     163             :                         }
     164             :                         break;
     165           0 :                 case AF_INET6:
     166           0 :                         if (pfx_un.length != IPV6_MAX_BITLEN) {
     167           0 :                                 vnc_zlog_debug_verbose(
     168             :                                         "%s: redist nve group UN prefix len (%d) != 128, skipping",
     169             :                                         __func__, pfx_un.length);
     170           0 :                                 return;
     171             :                         }
     172             :                         break;
     173           0 :                 default:
     174           0 :                         vnc_zlog_debug_verbose(
     175             :                                 "%s: no redist nve group UN host prefix configured, skipping",
     176             :                                 __func__);
     177             :                         return;
     178             :                 }
     179             : 
     180           0 :                 vncHD1VR.un_addr = pfx_un.prefix;
     181             : 
     182           0 :                 if (!vncHD1VR.peer) {
     183             :                         /*
     184             :                          * Same setup as in rfapi_open()
     185             :                          */
     186           0 :                         vncHD1VR.peer = peer_new(bgp);
     187           0 :                         vncHD1VR.peer->status =
     188             :                                 Established; /* keep bgp core happy */
     189           0 :                         bgp_sync_delete(vncHD1VR.peer); /* don't need these */
     190             : 
     191             :                         /*
     192             :                          * since this peer is not on the I/O thread, this lock
     193             :                          * is not strictly necessary, but serves as a reminder
     194             :                          * to those who may meddle...
     195             :                          */
     196           0 :                         frr_with_mutex (&vncHD1VR.peer->io_mtx) {
     197             :                                 // we don't need any I/O related facilities
     198           0 :                                 if (vncHD1VR.peer->ibuf)
     199           0 :                                         stream_fifo_free(vncHD1VR.peer->ibuf);
     200           0 :                                 if (vncHD1VR.peer->obuf)
     201           0 :                                         stream_fifo_free(vncHD1VR.peer->obuf);
     202             : 
     203           0 :                                 if (vncHD1VR.peer->ibuf_work)
     204           0 :                                         ringbuf_del(vncHD1VR.peer->ibuf_work);
     205           0 :                                 if (vncHD1VR.peer->obuf_work)
     206           0 :                                         stream_free(vncHD1VR.peer->obuf_work);
     207             : 
     208           0 :                                 vncHD1VR.peer->ibuf = NULL;
     209           0 :                                 vncHD1VR.peer->obuf = NULL;
     210           0 :                                 vncHD1VR.peer->obuf_work = NULL;
     211           0 :                                 vncHD1VR.peer->ibuf_work = NULL;
     212             :                         }
     213             : 
     214             :                         /* base code assumes have valid host pointer */
     215           0 :                         vncHD1VR.peer->host =
     216           0 :                                 XSTRDUP(MTYPE_BGP_PEER_HOST, ".zebra.");
     217             : 
     218             :                         /* Mark peer as belonging to HD */
     219           0 :                         SET_FLAG(vncHD1VR.peer->flags, PEER_FLAG_IS_RFAPI_HD);
     220             :                 }
     221             :         }
     222             : 
     223           0 :         memset(&prd, 0, sizeof(prd));
     224           0 :         prd = bgp->rfapi_cfg->rfg_redist->rd;
     225           0 :         prd.family = AF_UNSPEC;
     226           0 :         prd.prefixlen = 64;
     227             : 
     228           0 :         add_vnc_route(&vncHD1VR, /* cookie + UN addr */
     229             :                       bgp, SAFI_MPLS_VPN, p, &prd, &vnaddr, &local_pref,
     230             :                       &(bgp->rfapi_cfg->redist_lifetime),
     231             :                       NULL, /* RFP options */
     232             :                       NULL, /* struct rfapi_un_option */
     233             :                       NULL, /* struct rfapi_vn_option */
     234             :                       bgp->rfapi_cfg->rfg_redist->rt_export_list, NULL,
     235             :                       NULL,                             /* label: default */
     236             :                       type, BGP_ROUTE_REDISTRIBUTE, 0); /* flags */
     237             : }
     238             : 
     239             : /*
     240             :  * Route deletions from zebra propagate to VNC here
     241             :  */
     242           0 : static void vnc_redistribute_delete(struct prefix *p, uint8_t type)
     243             : {
     244           0 :         struct bgp *bgp = bgp_get_default();
     245           0 :         struct prefix_rd prd;
     246           0 :         afi_t afi;
     247             : 
     248           0 :         if (!bgp)
     249           0 :                 return;
     250             : 
     251           0 :         if (!bgp->rfapi_cfg) {
     252           0 :                 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
     253             :                                        __func__);
     254           0 :                 return;
     255             :         }
     256           0 :         afi = family2afi(p->family);
     257           0 :         if (!afi) {
     258           0 :                 vnc_zlog_debug_verbose("%s: unknown prefix address family %d",
     259             :                                        __func__, p->family);
     260           0 :                 return;
     261             :         }
     262           0 :         if (!bgp->rfapi_cfg->redist[afi][type]) {
     263           0 :                 vnc_zlog_debug_verbose(
     264             :                         "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d] is 0, skipping",
     265             :                         __func__, afi, type);
     266           0 :                 return;
     267             :         }
     268           0 :         if (!bgp->rfapi_cfg->rfg_redist) {
     269           0 :                 vnc_zlog_debug_verbose("%s: no redist nve group, skipping",
     270             :                                        __func__);
     271           0 :                 return;
     272             :         }
     273             : 
     274           0 :         memset(&prd, 0, sizeof(prd));
     275           0 :         prd = bgp->rfapi_cfg->rfg_redist->rd;
     276           0 :         prd.family = AF_UNSPEC;
     277           0 :         prd.prefixlen = 64;
     278             : 
     279           0 :         del_vnc_route(&vncHD1VR, /* use dummy ptr as cookie */
     280             :                       vncHD1VR.peer, bgp, SAFI_MPLS_VPN, p, &prd, type,
     281             :                       BGP_ROUTE_REDISTRIBUTE, NULL, 0);
     282             : }
     283             : 
     284             : /*
     285             :  * Flush all redistributed routes of type <type>
     286             :  */
     287           0 : static void vnc_redistribute_withdraw(struct bgp *bgp, afi_t afi, uint8_t type)
     288             : {
     289           0 :         struct prefix_rd prd;
     290           0 :         struct bgp_table *table;
     291           0 :         struct bgp_dest *pdest;
     292           0 :         struct bgp_dest *dest;
     293             : 
     294           0 :         vnc_zlog_debug_verbose("%s: entry", __func__);
     295             : 
     296           0 :         if (!bgp)
     297           0 :                 return;
     298           0 :         if (!bgp->rfapi_cfg) {
     299           0 :                 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
     300             :                                        __func__);
     301           0 :                 return;
     302             :         }
     303             : 
     304             :         /*
     305             :          * Loop over all the RDs
     306             :          */
     307           0 :         for (pdest = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); pdest;
     308           0 :              pdest = bgp_route_next(pdest)) {
     309           0 :                 const struct prefix *pdest_p = bgp_dest_get_prefix(pdest);
     310             : 
     311           0 :                 memset(&prd, 0, sizeof(prd));
     312           0 :                 prd.family = AF_UNSPEC;
     313           0 :                 prd.prefixlen = 64;
     314           0 :                 memcpy(prd.val, pdest_p->u.val, 8);
     315             : 
     316             :                 /* This is the per-RD table of prefixes */
     317           0 :                 table = bgp_dest_get_bgp_table_info(pdest);
     318           0 :                 if (!table)
     319           0 :                         continue;
     320             : 
     321           0 :                 for (dest = bgp_table_top(table); dest;
     322           0 :                      dest = bgp_route_next(dest)) {
     323             : 
     324           0 :                         struct bgp_path_info *ri;
     325             : 
     326           0 :                         for (ri = bgp_dest_get_bgp_path_info(dest); ri;
     327           0 :                              ri = ri->next) {
     328           0 :                                 if (ri->type
     329             :                                     == type) { /* has matching redist type */
     330             :                                         break;
     331             :                                 }
     332             :                         }
     333           0 :                         if (ri) {
     334           0 :                                 del_vnc_route(
     335             :                                         &vncHD1VR, /* use dummy ptr as cookie */
     336             :                                         vncHD1VR.peer, bgp, SAFI_MPLS_VPN,
     337             :                                         bgp_dest_get_prefix(dest), &prd, type,
     338             :                                         BGP_ROUTE_REDISTRIBUTE, NULL, 0);
     339             :                         }
     340             :                 }
     341             :         }
     342           0 :         vnc_zlog_debug_verbose("%s: return", __func__);
     343             : }
     344             : 
     345             : /*
     346             :  * Zebra route add and delete treatment.
     347             :  *
     348             :  * Assumes 1 nexthop
     349             :  */
     350           0 : static int vnc_zebra_read_route(ZAPI_CALLBACK_ARGS)
     351             : {
     352           0 :         struct zapi_route api;
     353           0 :         int add;
     354             : 
     355           0 :         if (zapi_route_decode(zclient->ibuf, &api) < 0)
     356             :                 return -1;
     357             : 
     358             :         /* we completely ignore srcdest routes for now. */
     359           0 :         if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
     360             :                 return 0;
     361             : 
     362           0 :         add = (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
     363           0 :         if (add)
     364           0 :                 vnc_redistribute_add(&api.prefix, api.metric, api.type);
     365             :         else
     366           0 :                 vnc_redistribute_delete(&api.prefix, api.type);
     367             : 
     368           0 :         if (BGP_DEBUG(zebra, ZEBRA))
     369           0 :                 vnc_zlog_debug_verbose(
     370             :                         "%s: Zebra rcvd: route delete %s %pFX metric %u",
     371             :                         __func__, zebra_route_string(api.type), &api.prefix,
     372             :                         api.metric);
     373             : 
     374             :         return 0;
     375             : }
     376             : 
     377             : /***********************************************************************
     378             :  *      vnc_bgp_zebra_*: VNC sends updates/withdraws to Zebra
     379             :  ***********************************************************************/
     380             : 
     381             : /*
     382             :  * low-level message builder
     383             :  */
     384           0 : static void vnc_zebra_route_msg(const struct prefix *p, unsigned int nhp_count,
     385             :                                 void *nhp_ary, int add) /* 1 = add, 0 = del */
     386             : {
     387           0 :         struct zapi_route api;
     388           0 :         struct zapi_nexthop *api_nh;
     389           0 :         int i;
     390           0 :         struct in_addr **nhp_ary4 = nhp_ary;
     391           0 :         struct in6_addr **nhp_ary6 = nhp_ary;
     392             : 
     393           0 :         if (!nhp_count) {
     394           0 :                 vnc_zlog_debug_verbose("%s: empty nexthop list, skipping",
     395             :                                        __func__);
     396           0 :                 return;
     397             :         }
     398             : 
     399           0 :         memset(&api, 0, sizeof(api));
     400           0 :         api.vrf_id = VRF_DEFAULT;
     401           0 :         api.type = ZEBRA_ROUTE_VNC;
     402           0 :         api.safi = SAFI_UNICAST;
     403           0 :         api.prefix = *p;
     404             : 
     405             :         /* Nexthops */
     406           0 :         SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
     407           0 :         api.nexthop_num = MIN(nhp_count, multipath_num);
     408           0 :         for (i = 0; i < api.nexthop_num; i++) {
     409             : 
     410           0 :                 api_nh = &api.nexthops[i];
     411           0 :                 api_nh->vrf_id = VRF_DEFAULT;
     412           0 :                 switch (p->family) {
     413           0 :                 case AF_INET:
     414           0 :                         memcpy(&api_nh->gate.ipv4, nhp_ary4[i],
     415             :                                sizeof(api_nh->gate.ipv4));
     416           0 :                         api_nh->type = NEXTHOP_TYPE_IPV4;
     417           0 :                         break;
     418           0 :                 case AF_INET6:
     419           0 :                         memcpy(&api_nh->gate.ipv6, nhp_ary6[i],
     420             :                                sizeof(api_nh->gate.ipv6));
     421           0 :                         api_nh->type = NEXTHOP_TYPE_IPV6;
     422           0 :                         break;
     423             :                 }
     424             :         }
     425             : 
     426           0 :         if (BGP_DEBUG(zebra, ZEBRA))
     427           0 :                 vnc_zlog_debug_verbose(
     428             :                         "%s: Zebra send: route %s %pFX, nhp_count=%d", __func__,
     429             :                         (add ? "add" : "del"), &api.prefix, nhp_count);
     430             : 
     431           0 :         zclient_route_send((add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE),
     432             :                            zclient_vnc, &api);
     433             : }
     434             : 
     435             : 
     436             : static void
     437           0 : nve_list_to_nh_array(uint8_t family, struct list *nve_list,
     438             :                      unsigned int *nh_count_ret,
     439             :                      void **nh_ary_ret,  /* returned address array */
     440             :                      void **nhp_ary_ret) /* returned pointer array */
     441             : {
     442           0 :         int nve_count = listcount(nve_list);
     443             : 
     444           0 :         *nh_count_ret = 0;
     445           0 :         *nh_ary_ret = NULL;
     446           0 :         *nhp_ary_ret = NULL;
     447             : 
     448           0 :         if (!nve_count) {
     449           0 :                 vnc_zlog_debug_verbose("%s: empty nve_list, skipping",
     450             :                                        __func__);
     451           0 :                 return;
     452             :         }
     453             : 
     454           0 :         if (family == AF_INET) {
     455           0 :                 struct listnode *ln;
     456           0 :                 struct in_addr *iap;
     457           0 :                 struct in_addr **v;
     458             : 
     459             :                 /*
     460             :                  * Array of nexthop addresses
     461             :                  */
     462           0 :                 *nh_ary_ret =
     463           0 :                         XCALLOC(MTYPE_TMP, nve_count * sizeof(struct in_addr));
     464             : 
     465             :                 /*
     466             :                  * Array of pointers to nexthop addresses
     467             :                  */
     468           0 :                 *nhp_ary_ret = XCALLOC(MTYPE_TMP,
     469             :                                        nve_count * sizeof(struct in_addr *));
     470           0 :                 iap = *nh_ary_ret;
     471           0 :                 v = *nhp_ary_ret;
     472             : 
     473           0 :                 for (ln = listhead(nve_list); ln; ln = listnextnode(ln)) {
     474             : 
     475           0 :                         struct rfapi_descriptor *irfd;
     476           0 :                         struct prefix nhp;
     477             : 
     478           0 :                         irfd = listgetdata(ln);
     479             : 
     480           0 :                         if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
     481           0 :                                 continue;
     482             : 
     483           0 :                         *iap = nhp.u.prefix4;
     484           0 :                         *v = iap;
     485           0 :                         vnc_zlog_debug_verbose(
     486             :                                 "%s: ipadr: (%p)<-0x%x, ptr: (%p)<-%p",
     487             :                                 __func__, iap, nhp.u.prefix4.s_addr, v, iap);
     488             : 
     489           0 :                         ++iap;
     490           0 :                         ++v;
     491           0 :                         ++*nh_count_ret;
     492             :                 }
     493             : 
     494           0 :         } else if (family == AF_INET6) {
     495             : 
     496           0 :                 struct listnode *ln;
     497             : 
     498           0 :                 *nh_ary_ret =
     499           0 :                         XCALLOC(MTYPE_TMP, nve_count * sizeof(struct in6_addr));
     500             : 
     501           0 :                 *nhp_ary_ret = XCALLOC(MTYPE_TMP,
     502             :                                        nve_count * sizeof(struct in6_addr *));
     503             : 
     504           0 :                 for (ln = listhead(nve_list); ln; ln = listnextnode(ln)) {
     505             : 
     506           0 :                         struct rfapi_descriptor *irfd;
     507           0 :                         struct in6_addr *iap = *nh_ary_ret;
     508           0 :                         struct in6_addr **v = *nhp_ary_ret;
     509           0 :                         struct prefix nhp;
     510             : 
     511           0 :                         irfd = listgetdata(ln);
     512             : 
     513           0 :                         if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
     514           0 :                                 continue;
     515             : 
     516           0 :                         *iap = nhp.u.prefix6;
     517           0 :                         *v = iap;
     518             : 
     519           0 :                         ++iap;
     520           0 :                         ++v;
     521           0 :                         ++*nh_count_ret;
     522             :                 }
     523             :         }
     524             : }
     525             : 
     526           0 : static void import_table_to_nve_list_zebra(struct bgp *bgp,
     527             :                                            struct rfapi_import_table *it,
     528             :                                            struct list **nves, uint8_t family)
     529             : {
     530           0 :         struct listnode *node;
     531           0 :         struct rfapi_rfg_name *rfgn;
     532             : 
     533             :         /*
     534             :          * Loop over the list of NVE-Groups configured for
     535             :          * exporting to direct-bgp.
     536             :          *
     537             :          * Build a list of NVEs that use this import table
     538             :          */
     539           0 :         *nves = NULL;
     540           0 :         for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_zebra_l, node,
     541             :                                   rfgn)) {
     542             : 
     543             :                 /*
     544             :                  * If this NVE-Group's import table matches the current one
     545             :                  */
     546           0 :                 if (rfgn->rfg && rfgn->rfg->nves
     547           0 :                     && rfgn->rfg->rfapi_import_table == it) {
     548             : 
     549           0 :                         nve_group_to_nve_list(rfgn->rfg, nves, family);
     550             :                 }
     551             :         }
     552           0 : }
     553             : 
     554           0 : static void vnc_zebra_add_del_prefix(struct bgp *bgp,
     555             :                                      struct rfapi_import_table *import_table,
     556             :                                      struct agg_node *rn,
     557             :                                      int add) /* !0 = add, 0 = del */
     558             : {
     559           0 :         struct list *nves;
     560           0 :         const struct prefix *p = agg_node_get_prefix(rn);
     561           0 :         unsigned int nexthop_count = 0;
     562           0 :         void *nh_ary = NULL;
     563           0 :         void *nhp_ary = NULL;
     564             : 
     565           0 :         vnc_zlog_debug_verbose("%s: entry, add=%d", __func__, add);
     566             : 
     567           0 :         if (zclient_vnc->sock < 0)
     568           0 :                 return;
     569             : 
     570           0 :         if (p->family != AF_INET && p->family != AF_INET6) {
     571           0 :                 flog_err(EC_LIB_DEVELOPMENT,
     572             :                          "%s: invalid route node addr family", __func__);
     573           0 :                 return;
     574             :         }
     575             : 
     576           0 :         if (!vrf_bitmap_check(
     577           0 :                     zclient_vnc->redist[family2afi(p->family)][ZEBRA_ROUTE_VNC],
     578             :                     VRF_DEFAULT))
     579             :                 return;
     580             : 
     581           0 :         if (!bgp->rfapi_cfg) {
     582           0 :                 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
     583             :                                        __func__);
     584           0 :                 return;
     585             :         }
     586           0 :         if (!listcount(bgp->rfapi_cfg->rfg_export_zebra_l)) {
     587           0 :                 vnc_zlog_debug_verbose(
     588             :                         "%s: no zebra export nve group, skipping", __func__);
     589           0 :                 return;
     590             :         }
     591             : 
     592           0 :         import_table_to_nve_list_zebra(bgp, import_table, &nves, p->family);
     593             : 
     594           0 :         if (nves) {
     595           0 :                 nve_list_to_nh_array(p->family, nves, &nexthop_count, &nh_ary,
     596             :                                      &nhp_ary);
     597             : 
     598           0 :                 list_delete(&nves);
     599             : 
     600           0 :                 if (nexthop_count)
     601           0 :                         vnc_zebra_route_msg(p, nexthop_count, nhp_ary, add);
     602             :         }
     603             : 
     604           0 :         XFREE(MTYPE_TMP, nhp_ary);
     605           0 :         XFREE(MTYPE_TMP, nh_ary);
     606             : }
     607             : 
     608           0 : void vnc_zebra_add_prefix(struct bgp *bgp,
     609             :                           struct rfapi_import_table *import_table,
     610             :                           struct agg_node *rn)
     611             : {
     612           0 :         vnc_zebra_add_del_prefix(bgp, import_table, rn, 1);
     613           0 : }
     614             : 
     615           0 : void vnc_zebra_del_prefix(struct bgp *bgp,
     616             :                           struct rfapi_import_table *import_table,
     617             :                           struct agg_node *rn)
     618             : {
     619           0 :         vnc_zebra_add_del_prefix(bgp, import_table, rn, 0);
     620           0 : }
     621             : 
     622             : 
     623           0 : static void vnc_zebra_add_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd,
     624             :                                   int add) /* 0 = del, !0 = add */
     625             : {
     626           0 :         struct listnode *node;
     627           0 :         struct rfapi_rfg_name *rfgn;
     628           0 :         struct rfapi_nve_group_cfg *rfg = rfd->rfg;
     629           0 :         afi_t afi = family2afi(rfd->vn_addr.addr_family);
     630           0 :         struct prefix nhp;
     631           0 :         void *pAddr;
     632             : 
     633           0 :         vnc_zlog_debug_verbose("%s: entry, add=%d", __func__, add);
     634             : 
     635           0 :         if (zclient_vnc->sock < 0)
     636           0 :                 return;
     637             : 
     638           0 :         if (!vrf_bitmap_check(zclient_vnc->redist[afi][ZEBRA_ROUTE_VNC],
     639             :                               VRF_DEFAULT))
     640             :                 return;
     641             : 
     642           0 :         if (afi != AFI_IP && afi != AFI_IP6) {
     643           0 :                 flog_err(EC_LIB_DEVELOPMENT, "%s: invalid vn addr family",
     644             :                          __func__);
     645           0 :                 return;
     646             :         }
     647             : 
     648           0 :         if (!bgp)
     649             :                 return;
     650           0 :         if (!bgp->rfapi_cfg) {
     651           0 :                 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
     652             :                                        __func__);
     653           0 :                 return;
     654             :         }
     655             : 
     656           0 :         if (rfapiRaddr2Qprefix(&rfd->vn_addr, &nhp)) {
     657           0 :                 vnc_zlog_debug_verbose("%s: can't convert vn address, skipping",
     658             :                                        __func__);
     659           0 :                 return;
     660             :         }
     661             : 
     662           0 :         pAddr = &nhp.u.val;
     663             : 
     664             :         /*
     665             :          * Loop over the list of NVE-Groups configured for
     666             :          * exporting to zebra and see if this new NVE's
     667             :          * group is among them.
     668             :          */
     669           0 :         for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_zebra_l, node,
     670             :                                   rfgn)) {
     671             : 
     672             :                 /*
     673             :                  * Yes, this NVE's group is configured for export to zebra
     674             :                  */
     675           0 :                 if (rfgn->rfg == rfg) {
     676             : 
     677           0 :                         struct agg_table *rt = NULL;
     678           0 :                         struct agg_node *rn;
     679           0 :                         struct rfapi_import_table *import_table;
     680           0 :                         import_table = rfg->rfapi_import_table;
     681             : 
     682           0 :                         vnc_zlog_debug_verbose(
     683             :                                 "%s: this nve's group is in zebra export list",
     684             :                                 __func__);
     685             : 
     686           0 :                         rt = import_table->imported_vpn[afi];
     687             : 
     688             :                         /*
     689             :                          * Walk the NVE-Group's VNC Import table
     690             :                          */
     691           0 :                         for (rn = agg_route_top(rt); rn;
     692           0 :                              rn = agg_route_next(rn)) {
     693           0 :                                 if (!rn->info)
     694           0 :                                         continue;
     695             : 
     696           0 :                                 vnc_zlog_debug_verbose("%s: sending %s",
     697             :                                                        __func__,
     698             :                                                        (add ? "add" : "del"));
     699           0 :                                 vnc_zebra_route_msg(agg_node_get_prefix(rn), 1,
     700             :                                                     &pAddr, add);
     701             :                         }
     702             :                 }
     703             :         }
     704             : }
     705             : 
     706           0 : void vnc_zebra_add_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
     707             : {
     708           0 :         vnc_zebra_add_del_nve(bgp, rfd, 1);
     709           0 : }
     710             : 
     711           0 : void vnc_zebra_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
     712             : {
     713           0 :         vnc_zebra_add_del_nve(bgp, rfd, 0);
     714           0 : }
     715             : 
     716           0 : static void vnc_zebra_add_del_group_afi(struct bgp *bgp,
     717             :                                         struct rfapi_nve_group_cfg *rfg,
     718             :                                         afi_t afi, int add)
     719             : {
     720           0 :         struct agg_table *rt = NULL;
     721           0 :         struct agg_node *rn;
     722           0 :         struct rfapi_import_table *import_table;
     723           0 :         uint8_t family = afi2family(afi);
     724             : 
     725           0 :         struct list *nves = NULL;
     726           0 :         unsigned int nexthop_count = 0;
     727           0 :         void *nh_ary = NULL;
     728           0 :         void *nhp_ary = NULL;
     729             : 
     730           0 :         vnc_zlog_debug_verbose("%s: entry", __func__);
     731           0 :         import_table = rfg->rfapi_import_table;
     732           0 :         if (!import_table) {
     733           0 :                 vnc_zlog_debug_verbose(
     734             :                         "%s: import table not defined, returning", __func__);
     735           0 :                 return;
     736             :         }
     737             : 
     738           0 :         if (afi == AFI_IP || afi == AFI_IP6) {
     739           0 :                 rt = import_table->imported_vpn[afi];
     740             :         } else {
     741           0 :                 flog_err(EC_LIB_DEVELOPMENT, "%s: bad afi %d", __func__, afi);
     742           0 :                 return;
     743             :         }
     744             : 
     745           0 :         if (!family) {
     746           0 :                 flog_err(EC_LIB_DEVELOPMENT, "%s: computed bad family: %d",
     747             :                          __func__, family);
     748           0 :                 return;
     749             :         }
     750             : 
     751           0 :         if (!rfg->nves) {
     752             :                 /* avoid segfault below if list doesn't exist */
     753           0 :                 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__);
     754           0 :                 return;
     755             :         }
     756             : 
     757           0 :         nve_group_to_nve_list(rfg, &nves, family);
     758           0 :         if (nves) {
     759           0 :                 vnc_zlog_debug_verbose("%s: have nves", __func__);
     760           0 :                 nve_list_to_nh_array(family, nves, &nexthop_count, &nh_ary,
     761             :                                      &nhp_ary);
     762             : 
     763           0 :                 vnc_zlog_debug_verbose("%s: family: %d, nve count: %d",
     764             :                                        __func__, family, nexthop_count);
     765             : 
     766           0 :                 list_delete(&nves);
     767             : 
     768           0 :                 if (nexthop_count) {
     769             :                         /*
     770             :                          * Walk the NVE-Group's VNC Import table
     771             :                          */
     772           0 :                         for (rn = agg_route_top(rt); rn;
     773           0 :                              rn = agg_route_next(rn)) {
     774           0 :                                 if (rn->info) {
     775           0 :                                         vnc_zebra_route_msg(
     776             :                                                 agg_node_get_prefix(rn),
     777             :                                                 nexthop_count, nhp_ary, add);
     778             :                                 }
     779             :                         }
     780             :                 }
     781           0 :                 XFREE(MTYPE_TMP, nhp_ary);
     782           0 :                 XFREE(MTYPE_TMP, nh_ary);
     783             :         }
     784             : }
     785             : 
     786           0 : void vnc_zebra_add_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
     787             : {
     788           0 :         vnc_zebra_add_del_group_afi(bgp, rfg, AFI_IP, 1);
     789           0 :         vnc_zebra_add_del_group_afi(bgp, rfg, AFI_IP6, 1);
     790           0 : }
     791             : 
     792           0 : void vnc_zebra_del_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
     793             : {
     794           0 :         vnc_zlog_debug_verbose("%s: entry", __func__);
     795           0 :         vnc_zebra_add_del_group_afi(bgp, rfg, AFI_IP, 0);
     796           0 :         vnc_zebra_add_del_group_afi(bgp, rfg, AFI_IP6, 0);
     797           0 : }
     798             : 
     799           0 : void vnc_zebra_reexport_group_afi(struct bgp *bgp,
     800             :                                   struct rfapi_nve_group_cfg *rfg, afi_t afi)
     801             : {
     802           0 :         struct listnode *node;
     803           0 :         struct rfapi_rfg_name *rfgn;
     804             : 
     805           0 :         for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_zebra_l, node,
     806             :                                   rfgn)) {
     807             : 
     808           0 :                 if (rfgn->rfg == rfg) {
     809           0 :                         vnc_zebra_add_del_group_afi(bgp, rfg, afi, 0);
     810           0 :                         vnc_zebra_add_del_group_afi(bgp, rfg, afi, 1);
     811           0 :                         break;
     812             :                 }
     813             :         }
     814           0 : }
     815             : 
     816             : 
     817             : /***********************************************************************
     818             :  *                      CONTROL INTERFACE
     819             :  ***********************************************************************/
     820             : 
     821             : 
     822             : /* Other routes redistribution into BGP. */
     823           0 : int vnc_redistribute_set(struct bgp *bgp, afi_t afi, int type)
     824             : {
     825           0 :         if (!bgp->rfapi_cfg) {
     826             :                 return CMD_WARNING_CONFIG_FAILED;
     827             :         }
     828             : 
     829             :         /* Set flag to BGP instance. */
     830           0 :         bgp->rfapi_cfg->redist[afi][type] = 1;
     831             : 
     832             :         //  bgp->redist[afi][type] = 1;
     833             : 
     834             :         /* Return if already redistribute flag is set. */
     835           0 :         if (vrf_bitmap_check(zclient_vnc->redist[afi][type], VRF_DEFAULT))
     836             :                 return CMD_WARNING_CONFIG_FAILED;
     837             : 
     838           0 :         vrf_bitmap_set(zclient_vnc->redist[afi][type], VRF_DEFAULT);
     839             : 
     840             :         // vrf_bitmap_set(zclient_vnc->redist[afi][type], VRF_DEFAULT);
     841             : 
     842             :         /* Return if zebra connection is not established. */
     843           0 :         if (zclient_vnc->sock < 0)
     844             :                 return CMD_WARNING_CONFIG_FAILED;
     845             : 
     846           0 :         if (BGP_DEBUG(zebra, ZEBRA))
     847           0 :                 vnc_zlog_debug_verbose("Zebra send: redistribute add %s",
     848             :                                        zebra_route_string(type));
     849             : 
     850             :         /* Send distribute add message to zebra. */
     851           0 :         zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient_vnc, afi, type,
     852             :                                 0, VRF_DEFAULT);
     853             : 
     854           0 :         return CMD_SUCCESS;
     855             : }
     856             : 
     857             : /* Unset redistribution.  */
     858           0 : int vnc_redistribute_unset(struct bgp *bgp, afi_t afi, int type)
     859             : {
     860           0 :         vnc_zlog_debug_verbose("%s: type=%d entry", __func__, type);
     861             : 
     862           0 :         if (!bgp->rfapi_cfg) {
     863           0 :                 vnc_zlog_debug_verbose("%s: return (no rfapi_cfg)", __func__);
     864           0 :                 return CMD_WARNING_CONFIG_FAILED;
     865             :         }
     866             : 
     867             :         /* Unset flag from BGP instance. */
     868           0 :         bgp->rfapi_cfg->redist[afi][type] = 0;
     869             : 
     870             :         /* Return if zebra connection is disabled. */
     871           0 :         if (!vrf_bitmap_check(zclient_vnc->redist[afi][type], VRF_DEFAULT))
     872             :                 return CMD_WARNING_CONFIG_FAILED;
     873           0 :         vrf_bitmap_unset(zclient_vnc->redist[afi][type], VRF_DEFAULT);
     874             : 
     875           0 :         if (bgp->rfapi_cfg->redist[AFI_IP][type] == 0
     876           0 :             && bgp->rfapi_cfg->redist[AFI_IP6][type] == 0
     877           0 :             && zclient_vnc->sock >= 0) {
     878             :                 /* Send distribute delete message to zebra. */
     879           0 :                 if (BGP_DEBUG(zebra, ZEBRA))
     880           0 :                         vnc_zlog_debug_verbose(
     881             :                                 "Zebra send: redistribute delete %s",
     882             :                                 zebra_route_string(type));
     883           0 :                 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient_vnc,
     884             :                                         afi, type, 0, VRF_DEFAULT);
     885             :         }
     886             : 
     887             :         /* Withdraw redistributed routes from current BGP's routing table. */
     888           0 :         vnc_redistribute_withdraw(bgp, afi, type);
     889             : 
     890           0 :         vnc_zlog_debug_verbose("%s: return", __func__);
     891             : 
     892             :         return CMD_SUCCESS;
     893             : }
     894             : 
     895             : extern struct zebra_privs_t bgpd_privs;
     896             : 
     897             : static zclient_handler *const vnc_handlers[] = {
     898             :         [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = vnc_zebra_read_route,
     899             :         [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = vnc_zebra_read_route,
     900             : };
     901             : 
     902             : /*
     903             :  * Modeled after bgp_zebra.c'bgp_zebra_init()
     904             :  * Charriere asks, "Is it possible to carry two?"
     905             :  */
     906           2 : void vnc_zebra_init(struct thread_master *master)
     907             : {
     908             :         /* Set default values. */
     909           2 :         zclient_vnc = zclient_new(master, &zclient_options_default,
     910             :                                   vnc_handlers, array_size(vnc_handlers));
     911           2 :         zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0, &bgpd_privs);
     912           2 : }
     913             : 
     914           2 : void vnc_zebra_destroy(void)
     915             : {
     916           2 :         if (zclient_vnc == NULL)
     917             :                 return;
     918           2 :         zclient_stop(zclient_vnc);
     919           2 :         zclient_free(zclient_vnc);
     920           2 :         zclient_vnc = NULL;
     921             : }

Generated by: LCOV version v1.16-topotato