back to topotato report
topotato coverage report
Current view: top level - bgpd/rfapi - rfapi.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 28 1481 1.9 %
Date: 2023-02-24 19:38:44 Functions: 2 69 2.9 %

          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             : #include "lib/zebra.h"
      22             : #include "lib/prefix.h"
      23             : #include "lib/agg_table.h"
      24             : #include "lib/vty.h"
      25             : #include "lib/memory.h"
      26             : #include "lib/routemap.h"
      27             : #include "lib/log.h"
      28             : #include "lib/linklist.h"
      29             : #include "lib/command.h"
      30             : #include "lib/stream.h"
      31             : #include "lib/ringbuf.h"
      32             : #include "lib/lib_errors.h"
      33             : 
      34             : #include "bgpd/bgpd.h"
      35             : #include "bgpd/bgp_ecommunity.h"
      36             : #include "bgpd/bgp_attr.h"
      37             : 
      38             : #include "bgpd/rfapi/bgp_rfapi_cfg.h"
      39             : #include "bgpd/rfapi/rfapi.h"
      40             : #include "bgpd/rfapi/rfapi_backend.h"
      41             : 
      42             : #include "bgpd/bgp_route.h"
      43             : #include "bgpd/bgp_mplsvpn.h"
      44             : #include "bgpd/bgp_aspath.h"
      45             : #include "bgpd/bgp_advertise.h"
      46             : #include "bgpd/bgp_vnc_types.h"
      47             : #include "bgpd/bgp_zebra.h"
      48             : 
      49             : #include "bgpd/rfapi/rfapi_import.h"
      50             : #include "bgpd/rfapi/rfapi_private.h"
      51             : #include "bgpd/rfapi/rfapi_monitor.h"
      52             : #include "bgpd/rfapi/rfapi_vty.h"
      53             : #include "bgpd/rfapi/vnc_export_bgp.h"
      54             : #include "bgpd/rfapi/vnc_export_bgp_p.h"
      55             : #include "bgpd/rfapi/vnc_zebra.h"
      56             : #include "bgpd/rfapi/vnc_import_bgp.h"
      57             : #include "bgpd/rfapi/rfapi_rib.h"
      58             : #include "bgpd/rfapi/rfapi_ap.h"
      59             : #include "bgpd/rfapi/rfapi_encap_tlv.h"
      60             : #include "bgpd/rfapi/vnc_debug.h"
      61             : 
      62             : #ifdef HAVE_GLIBC_BACKTRACE
      63             : /* for backtrace and friends */
      64             : #include <execinfo.h>
      65             : #endif /* HAVE_GLIBC_BACKTRACE */
      66             : 
      67             : struct ethaddr rfapi_ethaddr0 = {{0}};
      68             : 
      69             : #define DEBUG_RFAPI_STR "RF API debugging/testing command\n"
      70             : 
      71           0 : const char *rfapi_error_str(int code)
      72             : {
      73           0 :         switch (code) {
      74             :         case 0:
      75             :                 return "Success";
      76           0 :         case ENXIO:
      77           0 :                 return "BGP or VNC not configured";
      78           0 :         case ENOENT:
      79           0 :                 return "No match";
      80           0 :         case EEXIST:
      81           0 :                 return "Handle already open";
      82           0 :         case ENOMSG:
      83           0 :                 return "Incomplete configuration";
      84           0 :         case EAFNOSUPPORT:
      85           0 :                 return "Invalid address family";
      86           0 :         case EDEADLK:
      87           0 :                 return "Called from within a callback procedure";
      88           0 :         case EBADF:
      89           0 :                 return "Invalid handle";
      90           0 :         case EINVAL:
      91           0 :                 return "Invalid argument";
      92           0 :         case ESTALE:
      93           0 :                 return "Stale descriptor";
      94           0 :         default:
      95           0 :                 return "Unknown error";
      96             :         }
      97             : }
      98             : 
      99             : /*------------------------------------------
     100             :  * rfapi_get_response_lifetime_default
     101             :  *
     102             :  * Returns the default lifetime for a response.
     103             :  *    rfp_start_val     value returned by rfp_start or
     104             :  *                      NULL (=use default instance)
     105             :  *
     106             :  * input:
     107             :  *    None
     108             :  *
     109             :  * output:
     110             :  *
     111             :  * return value: The bgp instance default lifetime for a response.
     112             :  --------------------------------------------*/
     113           0 : int rfapi_get_response_lifetime_default(void *rfp_start_val)
     114             : {
     115           0 :         struct bgp *bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
     116           0 :         if (bgp)
     117           0 :                 return bgp->rfapi_cfg->default_response_lifetime;
     118             :         return BGP_VNC_DEFAULT_RESPONSE_LIFETIME_DEFAULT;
     119             : }
     120             : 
     121             : /*------------------------------------------
     122             :  * rfapi_is_vnc_configured
     123             :  *
     124             :  * Returns if VNC is configured
     125             :  *
     126             :  * input:
     127             :  *    rfp_start_val     value returned by rfp_start or
     128             :  *                      NULL (=use default instance)
     129             :  *
     130             :  * output:
     131             :  *
     132             :  * return value: If VNC is configured for the bgpd instance
     133             :  *      0               Success
     134             :  *      ENXIO           VNC not configured
     135             :  --------------------------------------------*/
     136           0 : int rfapi_is_vnc_configured(void *rfp_start_val)
     137             : {
     138           0 :         struct bgp *bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
     139           0 :         if (bgp_rfapi_is_vnc_configured(bgp) == 0)
     140           0 :                 return 0;
     141             :         return ENXIO;
     142             : }
     143             : 
     144             : 
     145             : /*------------------------------------------
     146             :  * rfapi_get_vn_addr
     147             :  *
     148             :  * Get the virtual network address used by an NVE based on it's RFD
     149             :  *
     150             :  * input:
     151             :  *    rfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic
     152             :  *
     153             :  * output:
     154             :  *
     155             :  * return value:
     156             :  *      vn              NVE virtual network address
     157             :  *------------------------------------------*/
     158           0 : struct rfapi_ip_addr *rfapi_get_vn_addr(void *rfd)
     159             : {
     160           0 :         struct rfapi_descriptor *rrfd = (struct rfapi_descriptor *)rfd;
     161           0 :         return &rrfd->vn_addr;
     162             : }
     163             : 
     164             : /*------------------------------------------
     165             :  * rfapi_get_un_addr
     166             :  *
     167             :  * Get the underlay network address used by an NVE based on it's RFD
     168             :  *
     169             :  * input:
     170             :  *    rfd: rfapi descriptor returned by rfapi_open or rfapi_create_generic
     171             :  *
     172             :  * output:
     173             :  *
     174             :  * return value:
     175             :  *      un              NVE underlay network address
     176             :  *------------------------------------------*/
     177           0 : struct rfapi_ip_addr *rfapi_get_un_addr(void *rfd)
     178             : {
     179           0 :         struct rfapi_descriptor *rrfd = (struct rfapi_descriptor *)rfd;
     180           0 :         return &rrfd->un_addr;
     181             : }
     182             : 
     183           0 : int rfapi_ip_addr_cmp(struct rfapi_ip_addr *a1, struct rfapi_ip_addr *a2)
     184             : {
     185           0 :         if (a1->addr_family != a2->addr_family)
     186           0 :                 return a1->addr_family - a2->addr_family;
     187             : 
     188           0 :         if (a1->addr_family == AF_INET) {
     189           0 :                 return IPV4_ADDR_CMP(&a1->addr.v4, &a2->addr.v4);
     190             :         }
     191             : 
     192           0 :         if (a1->addr_family == AF_INET6) {
     193           0 :                 return IPV6_ADDR_CMP(&a1->addr.v6, &a2->addr.v6);
     194             :         }
     195             : 
     196             :         assert(1);
     197             :         /* NOTREACHED */
     198             :         return 1;
     199             : }
     200             : 
     201           0 : static int rfapi_find_node(struct bgp *bgp, struct rfapi_ip_addr *vn_addr,
     202             :                            struct rfapi_ip_addr *un_addr,
     203             :                            struct agg_node **node)
     204             : {
     205           0 :         struct rfapi *h;
     206           0 :         struct prefix p;
     207           0 :         struct agg_node *rn;
     208           0 :         int rc;
     209           0 :         afi_t afi;
     210             : 
     211           0 :         if (!bgp) {
     212             :                 return ENXIO;
     213             :         }
     214             : 
     215           0 :         h = bgp->rfapi;
     216           0 :         if (!h) {
     217             :                 return ENXIO;
     218             :         }
     219             : 
     220           0 :         afi = family2afi(un_addr->addr_family);
     221           0 :         if (!afi) {
     222             :                 return EAFNOSUPPORT;
     223             :         }
     224             : 
     225           0 :         if ((rc = rfapiRaddr2Qprefix(un_addr, &p)))
     226             :                 return rc;
     227             : 
     228           0 :         rn = agg_node_lookup(h->un[afi], &p);
     229             : 
     230           0 :         if (!rn)
     231             :                 return ENOENT;
     232             : 
     233           0 :         agg_unlock_node(rn);
     234             : 
     235           0 :         *node = rn;
     236             : 
     237           0 :         return 0;
     238             : }
     239             : 
     240             : 
     241           0 : int rfapi_find_rfd(struct bgp *bgp, struct rfapi_ip_addr *vn_addr,
     242             :                    struct rfapi_ip_addr *un_addr, struct rfapi_descriptor **rfd)
     243             : {
     244           0 :         struct agg_node *rn;
     245           0 :         int rc;
     246             : 
     247           0 :         rc = rfapi_find_node(bgp, vn_addr, un_addr, &rn);
     248             : 
     249           0 :         if (rc)
     250             :                 return rc;
     251             : 
     252           0 :         for (*rfd = (struct rfapi_descriptor *)(rn->info); *rfd;
     253           0 :              *rfd = (*rfd)->next) {
     254           0 :                 if (!rfapi_ip_addr_cmp(&(*rfd)->vn_addr, vn_addr))
     255             :                         break;
     256             :         }
     257             : 
     258           0 :         if (!*rfd)
     259           0 :                 return ENOENT;
     260             : 
     261             :         return 0;
     262             : }
     263             : 
     264             : /*------------------------------------------
     265             :  * rfapi_find_handle
     266             :  *
     267             :  * input:
     268             :  *      un              underlay network address
     269             :  *      vn              virtual network address
     270             :  *
     271             :  * output:
     272             :  *      pHandle         pointer to location to store handle
     273             :  *
     274             :  * return value:
     275             :  *      0               Success
     276             :  *      ENOENT          no matching handle
     277             :  *      ENXIO           BGP or VNC not configured
     278             :  *------------------------------------------*/
     279           0 : static int rfapi_find_handle(struct bgp *bgp, struct rfapi_ip_addr *vn_addr,
     280             :                              struct rfapi_ip_addr *un_addr,
     281             :                              rfapi_handle *handle)
     282             : {
     283           0 :         struct rfapi_descriptor **rfd;
     284             : 
     285           0 :         rfd = (struct rfapi_descriptor **)handle;
     286             : 
     287           0 :         return rfapi_find_rfd(bgp, vn_addr, un_addr, rfd);
     288             : }
     289             : 
     290           0 : static int rfapi_find_handle_vty(struct vty *vty, struct rfapi_ip_addr *vn_addr,
     291             :                                  struct rfapi_ip_addr *un_addr,
     292             :                                  rfapi_handle *handle)
     293             : {
     294           0 :         struct bgp *bgp;
     295           0 :         struct rfapi_descriptor **rfd;
     296             : 
     297           0 :         bgp = bgp_get_default(); /* assume 1 instance for now */
     298             : 
     299           0 :         rfd = (struct rfapi_descriptor **)handle;
     300             : 
     301           0 :         return rfapi_find_rfd(bgp, vn_addr, un_addr, rfd);
     302             : }
     303             : 
     304           0 : static int is_valid_rfd(struct rfapi_descriptor *rfd)
     305             : {
     306           0 :         rfapi_handle hh;
     307             : 
     308           0 :         if (!rfd || rfd->bgp == NULL)
     309             :                 return 0;
     310             : 
     311           0 :         if (CHECK_FLAG(
     312             :                     rfd->flags,
     313             :                     RFAPI_HD_FLAG_IS_VRF)) /* assume VRF/internal are valid */
     314             :                 return 1;
     315             : 
     316           0 :         if (rfapi_find_handle(rfd->bgp, &rfd->vn_addr, &rfd->un_addr, &hh))
     317             :                 return 0;
     318             : 
     319           0 :         if (rfd != hh)
     320             :                 return 0;
     321             : 
     322             :         return 1;
     323             : }
     324             : 
     325             : /*
     326             :  * check status of descriptor
     327             :  */
     328           0 : int rfapi_check(void *handle)
     329             : {
     330           0 :         struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
     331           0 :         rfapi_handle hh;
     332           0 :         int rc;
     333             : 
     334           0 :         if (!rfd || rfd->bgp == NULL)
     335             :                 return EINVAL;
     336             : 
     337           0 :         if (CHECK_FLAG(
     338             :                     rfd->flags,
     339             :                     RFAPI_HD_FLAG_IS_VRF)) /* assume VRF/internal are valid */
     340             :                 return 0;
     341             : 
     342           0 :         if ((rc = rfapi_find_handle(rfd->bgp, &rfd->vn_addr, &rfd->un_addr,
     343             :                                     &hh)))
     344             :                 return rc;
     345             : 
     346           0 :         if (rfd != hh)
     347             :                 return ENOENT;
     348             : 
     349           0 :         if (!rfd->rfg)
     350             :                 return ESTALE;
     351             : 
     352             :         return 0;
     353             : }
     354             : 
     355             : 
     356           0 : void del_vnc_route(struct rfapi_descriptor *rfd,
     357             :                    struct peer *peer, /* rfd->peer for RFP regs */
     358             :                    struct bgp *bgp, safi_t safi, const struct prefix *p,
     359             :                    struct prefix_rd *prd, uint8_t type, uint8_t sub_type,
     360             :                    struct rfapi_nexthop *lnh, int kill)
     361             : {
     362           0 :         afi_t afi; /* of the VN address */
     363           0 :         struct bgp_dest *bn;
     364           0 :         struct bgp_path_info *bpi;
     365           0 :         struct prefix_rd prd0;
     366             : 
     367           0 :         afi = family2afi(p->family);
     368           0 :         assert(afi == AFI_IP || afi == AFI_IP6);
     369             : 
     370           0 :         if (safi == SAFI_ENCAP) {
     371           0 :                 memset(&prd0, 0, sizeof(prd0));
     372           0 :                 prd0.family = AF_UNSPEC;
     373           0 :                 prd0.prefixlen = 64;
     374           0 :                 prd = &prd0;
     375             :         }
     376           0 :         bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
     377             : 
     378           0 :         vnc_zlog_debug_verbose(
     379             :                 "%s: peer=%p, prefix=%pFX, prd=%pRD afi=%d, safi=%d bn=%p, bn->info=%p",
     380             :                 __func__, peer, p, prd, afi, safi, bn,
     381             :                 (bn ? bgp_dest_get_bgp_path_info(bn) : NULL));
     382             : 
     383           0 :         for (bpi = (bn ? bgp_dest_get_bgp_path_info(bn) : NULL); bpi;
     384           0 :              bpi = bpi->next) {
     385             : 
     386           0 :                 vnc_zlog_debug_verbose(
     387             :                         "%s: trying bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p, local_pref=%" PRIu64,
     388             :                         __func__, bpi, bpi->peer, bpi->type, bpi->sub_type,
     389             :                         (bpi->extra ? bpi->extra->vnc.export.rfapi_handle
     390             :                                     : NULL),
     391             :                         CHECK_FLAG(bpi->attr->flag,
     392             :                                    ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)
     393             :                                    ? bpi->attr->local_pref : 0));
     394             : 
     395           0 :                 if (bpi->peer == peer && bpi->type == type
     396           0 :                     && bpi->sub_type == sub_type && bpi->extra
     397           0 :                     && bpi->extra->vnc.export.rfapi_handle == (void *)rfd) {
     398             : 
     399           0 :                         vnc_zlog_debug_verbose("%s: matched it", __func__);
     400             : 
     401             :                         break;
     402             :                 }
     403             :         }
     404             : 
     405           0 :         if (lnh) {
     406             :                 /*
     407             :                  * lnh set means to JUST delete the local nexthop from this
     408             :                  * route. Leave the route itself in place.
     409             :                  * TBD add return code reporting of success/failure
     410             :                  */
     411           0 :                 if (!bpi || !bpi->extra
     412           0 :                     || !bpi->extra->vnc.export.local_nexthops) {
     413             :                         /*
     414             :                          * no local nexthops
     415             :                          */
     416           0 :                         vnc_zlog_debug_verbose(
     417             :                                 "%s: lnh list already empty at prefix %pFX",
     418             :                                 __func__, p);
     419           0 :                         goto done;
     420             :                 }
     421             : 
     422             :                 /*
     423             :                  * look for it
     424             :                  */
     425           0 :                 struct listnode *node;
     426           0 :                 struct rfapi_nexthop *pLnh = NULL;
     427             : 
     428           0 :                 for (ALL_LIST_ELEMENTS_RO(bpi->extra->vnc.export.local_nexthops,
     429             :                                           node, pLnh)) {
     430             : 
     431           0 :                         if (prefix_same(&pLnh->addr, &lnh->addr)) {
     432             :                                 break;
     433             :                         }
     434             :                 }
     435             : 
     436           0 :                 if (pLnh) {
     437           0 :                         listnode_delete(bpi->extra->vnc.export.local_nexthops,
     438             :                                         pLnh);
     439             : 
     440             :                         /* silly rabbit, listnode_delete doesn't invoke
     441             :                          * list->del on data */
     442           0 :                         rfapi_nexthop_free(pLnh);
     443             :                 } else {
     444           0 :                         vnc_zlog_debug_verbose("%s: desired lnh not found %pFX",
     445             :                                                __func__, p);
     446             :                 }
     447           0 :                 goto done;
     448             :         }
     449             : 
     450             :         /*
     451             :          * loop back to import tables
     452             :          * Do this before removing from BGP RIB because rfapiProcessWithdraw
     453             :          * might refer to it
     454             :          */
     455           0 :         rfapiProcessWithdraw(peer, rfd, p, prd, NULL, afi, safi, type, kill);
     456             : 
     457           0 :         if (bpi) {
     458           0 :                 vnc_zlog_debug_verbose(
     459             :                         "%s: Found route (safi=%d) to delete at prefix %pFX",
     460             :                         __func__, safi, p);
     461             : 
     462           0 :                 if (safi == SAFI_MPLS_VPN) {
     463           0 :                         struct bgp_dest *pdest = NULL;
     464           0 :                         struct bgp_table *table = NULL;
     465             : 
     466           0 :                         pdest = bgp_node_get(bgp->rib[afi][safi],
     467             :                                              (struct prefix *)prd);
     468           0 :                         table = bgp_dest_get_bgp_table_info(pdest);
     469           0 :                         if (table)
     470           0 :                                 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
     471             :                                         bgp, prd, table, p, bpi);
     472           0 :                         bgp_dest_unlock_node(pdest);
     473             :                 }
     474             : 
     475             :                 /*
     476             :                  * Delete local_nexthops list
     477             :                  */
     478           0 :                 if (bpi->extra && bpi->extra->vnc.export.local_nexthops)
     479           0 :                         list_delete(&bpi->extra->vnc.export.local_nexthops);
     480             : 
     481           0 :                 bgp_aggregate_decrement(bgp, p, bpi, afi, safi);
     482           0 :                 bgp_path_info_delete(bn, bpi);
     483           0 :                 bgp_process(bgp, bn, afi, safi);
     484             :         } else {
     485           0 :                 vnc_zlog_debug_verbose(
     486             :                         "%s: Couldn't find route (safi=%d) at prefix %pFX",
     487             :                         __func__, safi, p);
     488             :         }
     489           0 : done:
     490           0 :         bgp_dest_unlock_node(bn);
     491           0 : }
     492             : 
     493           0 : struct rfapi_nexthop *rfapi_nexthop_new(struct rfapi_nexthop *copyme)
     494             : {
     495           0 :         struct rfapi_nexthop *new =
     496           0 :                 XCALLOC(MTYPE_RFAPI_NEXTHOP, sizeof(struct rfapi_nexthop));
     497           0 :         if (copyme)
     498           0 :                 *new = *copyme;
     499           0 :         return new;
     500             : }
     501             : 
     502           0 : void rfapi_nexthop_free(void *p)
     503             : {
     504           0 :         struct rfapi_nexthop *goner = p;
     505           0 :         XFREE(MTYPE_RFAPI_NEXTHOP, goner);
     506           0 : }
     507             : 
     508           0 : struct rfapi_vn_option *rfapi_vn_options_dup(struct rfapi_vn_option *existing)
     509             : {
     510           0 :         struct rfapi_vn_option *p;
     511           0 :         struct rfapi_vn_option *head = NULL;
     512           0 :         struct rfapi_vn_option *tail = NULL;
     513             : 
     514           0 :         for (p = existing; p; p = p->next) {
     515           0 :                 struct rfapi_vn_option *new;
     516             : 
     517           0 :                 new = XCALLOC(MTYPE_RFAPI_VN_OPTION,
     518             :                               sizeof(struct rfapi_vn_option));
     519           0 :                 *new = *p;
     520           0 :                 new->next = NULL;
     521           0 :                 if (tail)
     522           0 :                         (tail)->next = new;
     523           0 :                 tail = new;
     524           0 :                 if (!head) {
     525           0 :                         head = new;
     526             :                 }
     527             :         }
     528           0 :         return head;
     529             : }
     530             : 
     531           0 : void rfapi_un_options_free(struct rfapi_un_option *p)
     532             : {
     533           0 :         struct rfapi_un_option *next;
     534             : 
     535           0 :         while (p) {
     536           0 :                 next = p->next;
     537           0 :                 XFREE(MTYPE_RFAPI_UN_OPTION, p);
     538           0 :                 p = next;
     539             :         }
     540           0 : }
     541             : 
     542           0 : void rfapi_vn_options_free(struct rfapi_vn_option *p)
     543             : {
     544           0 :         struct rfapi_vn_option *next;
     545             : 
     546           0 :         while (p) {
     547           0 :                 next = p->next;
     548           0 :                 XFREE(MTYPE_RFAPI_VN_OPTION, p);
     549           0 :                 p = next;
     550             :         }
     551           0 : }
     552             : 
     553             : /* Based on bgp_redistribute_add() */
     554           0 : void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
     555             :                    struct bgp *bgp, int safi, const struct prefix *p,
     556             :                    struct prefix_rd *prd, struct rfapi_ip_addr *nexthop,
     557             :                    uint32_t *local_pref,
     558             :                    uint32_t *lifetime, /* NULL => dont send lifetime */
     559             :                    struct bgp_tea_options *rfp_options,
     560             :                    struct rfapi_un_option *options_un,
     561             :                    struct rfapi_vn_option *options_vn,
     562             :                    struct ecommunity *rt_export_list, /* Copied, not consumed */
     563             :                    uint32_t *med,                  /* NULL => don't set med */
     564             :                    uint32_t *label,                /* low order 3 bytes */
     565             :                    uint8_t type, uint8_t sub_type, /* RFP, NORMAL or REDIST */
     566             :                    int flags)
     567             : {
     568           0 :         afi_t afi; /* of the VN address */
     569           0 :         struct bgp_path_info *new;
     570           0 :         struct bgp_path_info *bpi;
     571           0 :         struct bgp_dest *bn;
     572             : 
     573           0 :         struct attr attr = {0};
     574           0 :         struct attr *new_attr;
     575           0 :         uint32_t label_val;
     576             : 
     577           0 :         struct bgp_attr_encap_subtlv *encaptlv;
     578           0 :         char buf[PREFIX_STRLEN];
     579             : 
     580           0 :         struct rfapi_nexthop *lnh = NULL; /* local nexthop */
     581           0 :         struct rfapi_vn_option *vo;
     582           0 :         struct rfapi_l2address_option *l2o = NULL;
     583           0 :         struct rfapi_ip_addr *un_addr = &rfd->un_addr;
     584             : 
     585           0 :         bgp_encap_types TunnelType = BGP_ENCAP_TYPE_RESERVED;
     586           0 :         struct bgp_redist *red;
     587             : 
     588           0 :         if (safi == SAFI_ENCAP
     589           0 :             && !(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_ADV_UN_METHOD_ENCAP)) {
     590             : 
     591             :                 /*
     592             :                  * Encap mode not enabled. UN addresses will be communicated
     593             :                  * via VNC Tunnel subtlv instead.
     594             :                  */
     595           0 :                 vnc_zlog_debug_verbose(
     596             :                         "%s: encap mode not enabled, not adding SAFI_ENCAP route",
     597             :                         __func__);
     598           0 :                 return;
     599             :         }
     600             : 
     601           0 :         for (vo = options_vn; vo; vo = vo->next) {
     602           0 :                 if (RFAPI_VN_OPTION_TYPE_L2ADDR == vo->type) {
     603           0 :                         l2o = &vo->v.l2addr;
     604           0 :                         if (RFAPI_0_ETHERADDR(&l2o->macaddr))
     605           0 :                                 l2o = NULL; /* not MAC resolution */
     606             :                 }
     607           0 :                 if (RFAPI_VN_OPTION_TYPE_LOCAL_NEXTHOP == vo->type) {
     608           0 :                         lnh = &vo->v.local_nexthop;
     609             :                 }
     610             :         }
     611             : 
     612           0 :         if (label)
     613           0 :                 label_val = *label;
     614             :         else
     615           0 :                 label_val = MPLS_LABEL_IMPLICIT_NULL;
     616             : 
     617           0 :         afi = family2afi(p->family);
     618           0 :         assert(afi == AFI_IP || afi == AFI_IP6);
     619             : 
     620           0 :         vnc_zlog_debug_verbose("%s: afi=%s, safi=%s", __func__, afi2str(afi),
     621             :                                safi2str(safi));
     622             : 
     623             :         /* Make default attribute. Produces already-interned attr.aspath */
     624             :         /* Cripes, the memory management of attributes is byzantine */
     625             : 
     626           0 :         bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
     627             : 
     628             :         /*
     629             :          * At this point:
     630             :          * attr: static
     631             :          *  extra: dynamically allocated, owned by attr
     632             :          *  aspath: points to interned hash from aspath hash table
     633             :          */
     634             : 
     635             : 
     636             :         /*
     637             :          * Route-specific un_options get added to the VPN SAFI
     638             :          * advertisement tunnel encap attribute.  (the per-NVE
     639             :          * "default" un_options are put into the 1-per-NVE ENCAP
     640             :          * SAFI advertisement). The VPN SAFI also gets the
     641             :          * default un_options if there are no route-specific options.
     642             :          */
     643           0 :         if (options_un) {
     644             :                 struct rfapi_un_option *uo;
     645             : 
     646           0 :                 for (uo = options_un; uo; uo = uo->next) {
     647           0 :                         if (RFAPI_UN_OPTION_TYPE_TUNNELTYPE == uo->type) {
     648           0 :                                 TunnelType = rfapi_tunneltype_option_to_tlv(
     649             :                                         bgp, un_addr, &uo->v.tunnel, &attr,
     650             :                                         l2o != NULL);
     651             :                         }
     652             :                 }
     653             :         } else {
     654             :                 /*
     655             :                  * Add encap attr
     656             :                  * These are the NVE-specific "default" un_options which are
     657             :                  * put into the 1-per-NVE ENCAP advertisement.
     658             :                  */
     659           0 :                 if (rfd->default_tunneltype_option.type) {
     660           0 :                         TunnelType = rfapi_tunneltype_option_to_tlv(
     661             :                                 bgp, un_addr, &rfd->default_tunneltype_option,
     662             :                                 &attr, l2o != NULL);
     663             :                 } else /* create default for local addse  */
     664           0 :                         if (type == ZEBRA_ROUTE_BGP
     665           0 :                             && sub_type == BGP_ROUTE_RFP)
     666           0 :                         TunnelType = rfapi_tunneltype_option_to_tlv(
     667             :                                 bgp, un_addr, NULL, &attr, l2o != NULL);
     668             :         }
     669             : 
     670           0 :         if (TunnelType == BGP_ENCAP_TYPE_MPLS) {
     671           0 :                 if (safi == SAFI_ENCAP) {
     672             :                         /* Encap SAFI not used with MPLS  */
     673           0 :                         vnc_zlog_debug_verbose(
     674             :                                 "%s: mpls tunnel type, encap safi omitted",
     675             :                                 __func__);
     676           0 :                         aspath_unintern(&attr.aspath); /* Unintern original. */
     677           0 :                         return;
     678             :                 }
     679             :         }
     680             : 
     681           0 :         if (local_pref) {
     682           0 :                 attr.local_pref = *local_pref;
     683           0 :                 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
     684             :         }
     685             : 
     686           0 :         if (med) {
     687           0 :                 attr.med = *med;
     688           0 :                 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
     689             :         }
     690             : 
     691             :         /* override default weight assigned by bgp_attr_default_set() */
     692           0 :         attr.weight = rfd->peer ? rfd->peer->weight[afi][safi] : 0;
     693             : 
     694             :         /*
     695             :          * NB: ticket 81: do not reset attr.aspath here because it would
     696             :          * cause iBGP peers to drop route
     697             :          */
     698             : 
     699             :         /*
     700             :          * Set originator ID for routes imported from BGP directly.
     701             :          * These routes could be synthetic, and therefore could
     702             :          * reuse the peer pointers of the routes they are derived
     703             :          * from. Setting the originator ID to "us" prevents the
     704             :          * wrong originator ID from being sent when this route is
     705             :          * sent from a route reflector.
     706             :          */
     707           0 :         if (type == ZEBRA_ROUTE_BGP_DIRECT
     708           0 :             || type == ZEBRA_ROUTE_BGP_DIRECT_EXT) {
     709           0 :                 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
     710           0 :                 attr.originator_id = bgp->router_id;
     711             :         }
     712             : 
     713             : 
     714             :         /* Set up vnc attribute (sub-tlv for Prefix Lifetime) */
     715           0 :         if (lifetime && *lifetime != RFAPI_INFINITE_LIFETIME) {
     716           0 :                 uint32_t lt;
     717             : 
     718           0 :                 encaptlv = XCALLOC(MTYPE_ENCAP_TLV,
     719             :                                    sizeof(struct bgp_attr_encap_subtlv) + 4);
     720           0 :                 encaptlv->type =
     721             :                         BGP_VNC_SUBTLV_TYPE_LIFETIME; /* prefix lifetime */
     722           0 :                 encaptlv->length = 4;
     723           0 :                 lt = htonl(*lifetime);
     724           0 :                 memcpy(encaptlv->value, &lt, 4);
     725           0 :                 bgp_attr_set_vnc_subtlvs(&attr, encaptlv);
     726           0 :                 vnc_zlog_debug_verbose(
     727             :                         "%s: set Encap Attr Prefix Lifetime to %d", __func__,
     728             :                         *lifetime);
     729             :         }
     730             : 
     731             :         /* add rfp options to vnc attr */
     732           0 :         if (rfp_options) {
     733             : 
     734           0 :                 if (flags & RFAPI_AHR_RFPOPT_IS_VNCTLV) {
     735           0 :                         struct bgp_attr_encap_subtlv *vnc_subtlvs =
     736           0 :                                 bgp_attr_get_vnc_subtlvs(&attr);
     737             :                         /*
     738             :                          * this flag means we're passing a pointer to an
     739             :                          * existing encap tlv chain which we should copy.
     740             :                          * It's a hack to avoid adding yet another argument
     741             :                          * to add_vnc_route()
     742             :                          */
     743           0 :                         encaptlv = encap_tlv_dup(
     744             :                                 (struct bgp_attr_encap_subtlv *)rfp_options);
     745           0 :                         if (vnc_subtlvs)
     746           0 :                                 vnc_subtlvs->next = encaptlv;
     747             :                         else
     748           0 :                                 bgp_attr_set_vnc_subtlvs(&attr, encaptlv);
     749             :                 } else {
     750           0 :                         struct bgp_tea_options *hop;
     751             :                         /* XXX max of one tlv present so far from above code */
     752           0 :                         struct bgp_attr_encap_subtlv *tail =
     753           0 :                                 bgp_attr_get_vnc_subtlvs(&attr);
     754             : 
     755           0 :                         for (hop = rfp_options; hop; hop = hop->next) {
     756             : 
     757             :                                 /*
     758             :                                  * Construct subtlv
     759             :                                  */
     760           0 :                                 encaptlv = XCALLOC(
     761             :                                         MTYPE_ENCAP_TLV,
     762             :                                         sizeof(struct bgp_attr_encap_subtlv) + 2
     763             :                                                 + hop->length);
     764           0 :                                 encaptlv->type =
     765             :                                         BGP_VNC_SUBTLV_TYPE_RFPOPTION; /* RFP
     766             :                                                                           option
     767             :                                                                           */
     768           0 :                                 encaptlv->length = 2 + hop->length;
     769           0 :                                 *((uint8_t *)(encaptlv->value) + 0) = hop->type;
     770           0 :                                 *((uint8_t *)(encaptlv->value) + 1) =
     771             :                                         hop->length;
     772           0 :                                 memcpy(((uint8_t *)encaptlv->value) + 2,
     773           0 :                                        hop->value, hop->length);
     774             : 
     775             :                                 /*
     776             :                                  * add to end of subtlv chain
     777             :                                  */
     778           0 :                                 if (tail)
     779           0 :                                         tail->next = encaptlv;
     780             :                                 else
     781           0 :                                         bgp_attr_set_vnc_subtlvs(&attr,
     782             :                                                                  encaptlv);
     783           0 :                                 tail = encaptlv;
     784             :                         }
     785             :                 }
     786             :         }
     787             : 
     788             :         /*
     789             :          * At this point:
     790             :          * attr: static
     791             :          *  extra: dynamically allocated, owned by attr
     792             :          *      vnc_subtlvs: dynamic chain, length 1
     793             :          *  aspath: points to interned hash from aspath hash table
     794             :          */
     795             : 
     796             : 
     797           0 :         bgp_attr_set_ecommunity(&attr, ecommunity_new());
     798           0 :         assert(bgp_attr_get_ecommunity(&attr));
     799             : 
     800           0 :         if (TunnelType != BGP_ENCAP_TYPE_MPLS
     801           0 :             && TunnelType != BGP_ENCAP_TYPE_RESERVED) {
     802             :                 /*
     803             :                  * Add BGP Encapsulation Extended Community. Format described in
     804             :                  * section 4.5 of RFC 5512.
     805             :                  * Always include when not MPLS type, to disambiguate this case.
     806             :                  */
     807           0 :                 struct ecommunity_val beec;
     808             : 
     809           0 :                 memset(&beec, 0, sizeof(beec));
     810           0 :                 beec.val[0] = ECOMMUNITY_ENCODE_OPAQUE;
     811           0 :                 beec.val[1] = ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP;
     812           0 :                 beec.val[6] = ((TunnelType) >> 8) & 0xff;
     813           0 :                 beec.val[7] = (TunnelType)&0xff;
     814           0 :                 ecommunity_add_val(bgp_attr_get_ecommunity(&attr), &beec, false,
     815             :                                    false);
     816             :         }
     817             : 
     818             :         /*
     819             :          * Add extended community attributes to match rt export list
     820             :          */
     821           0 :         if (rt_export_list) {
     822           0 :                 bgp_attr_set_ecommunity(
     823             :                         &attr, ecommunity_merge(bgp_attr_get_ecommunity(&attr),
     824             :                                                 rt_export_list));
     825             :         }
     826             : 
     827           0 :         struct ecommunity *ecomm = bgp_attr_get_ecommunity(&attr);
     828             : 
     829           0 :         if (!ecomm->size) {
     830           0 :                 ecommunity_free(&ecomm);
     831           0 :                 bgp_attr_set_ecommunity(&attr, NULL);
     832             :         }
     833           0 :         vnc_zlog_debug_verbose("%s: attr.ecommunity=%p", __func__, ecomm);
     834             : 
     835             : 
     836             :         /*
     837             :          * At this point:
     838             :          * attr: static
     839             :          *  extra: dynamically allocated, owned by attr
     840             :          *      vnc_subtlvs: dynamic chain, length 1
     841             :          *      ecommunity: dynamic 2-part
     842             :          *  aspath: points to interned hash from aspath hash table
     843             :          */
     844             : 
     845             :         /* stuff nexthop in attr_extra; which field depends on IPv4 or IPv6 */
     846           0 :         switch (nexthop->addr_family) {
     847           0 :         case AF_INET:
     848             :                 /*
     849             :                  * set this field to prevent bgp_route.c code from setting
     850             :                  * mp_nexthop_global_in to self
     851             :                  */
     852           0 :                 attr.nexthop.s_addr = nexthop->addr.v4.s_addr;
     853             : 
     854           0 :                 attr.mp_nexthop_global_in = nexthop->addr.v4;
     855           0 :                 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
     856           0 :                 break;
     857             : 
     858           0 :         case AF_INET6:
     859           0 :                 attr.mp_nexthop_global = nexthop->addr.v6;
     860           0 :                 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
     861           0 :                 break;
     862             : 
     863             :         default:
     864           0 :                 assert(0);
     865             :         }
     866             : 
     867             : 
     868           0 :         prefix2str(p, buf, sizeof(buf));
     869             : 
     870             :         /*
     871             :          * At this point:
     872             :          *
     873             :          * attr: static
     874             :          *  extra: dynamically allocated, owned by attr
     875             :          *      vnc_subtlvs: dynamic chain, length 1
     876             :          *      ecommunity: dynamic 2-part
     877             :          *  aspath: points to interned hash from aspath hash table
     878             :          */
     879             : 
     880           0 :         red = bgp_redist_lookup(bgp, afi, type, 0);
     881             : 
     882           0 :         if (red && red->redist_metric_flag) {
     883           0 :                 attr.med = red->redist_metric;
     884           0 :                 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
     885             :         }
     886             : 
     887           0 :         bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
     888             : 
     889             :         /*
     890             :          * bgp_attr_intern creates a new reference to a cached
     891             :          * attribute, but leaves the following bits of trash:
     892             :          * - old attr
     893             :          * - old attr->extra (free via bgp_attr_extra_free(attr))
     894             :          *
     895             :          * Note that it frees the original attr->extra->ecommunity
     896             :          * but leaves the new attribute pointing to the ORIGINAL
     897             :          * vnc options (which therefore we needn't free from the
     898             :          * static attr)
     899             :          */
     900           0 :         new_attr = bgp_attr_intern(&attr);
     901             : 
     902           0 :         aspath_unintern(&attr.aspath); /* Unintern original. */
     903             : 
     904             :         /*
     905             :          * At this point:
     906             :          *
     907             :          * attr: static
     908             :          *  extra: dynamically allocated, owned by attr
     909             :          *      vnc_subtlvs: dynamic chain, length 1
     910             :          *      ecommunity: POINTS TO INTERNED ecom, THIS REF NOT COUNTED
     911             :          *
     912             :          * new_attr: an attr that is part of the hash table, distinct
     913             :          *           from attr which is static.
     914             :          *  extra: dynamically allocated, owned by new_attr (in hash table)
     915             :          *      vnc_subtlvs: POINTS TO SAME dynamic chain AS attr
     916             :          *      ecommunity: POINTS TO interned/refcounted dynamic 2-part AS attr
     917             :          *  aspath: POINTS TO interned/refcounted hashed block
     918             :          */
     919           0 :         for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) {
     920             :                 /* probably only need to check
     921             :                  * bpi->extra->vnc.export.rfapi_handle */
     922           0 :                 if (bpi->peer == rfd->peer && bpi->type == type
     923           0 :                     && bpi->sub_type == sub_type && bpi->extra
     924           0 :                     && bpi->extra->vnc.export.rfapi_handle == (void *)rfd) {
     925             : 
     926             :                         break;
     927             :                 }
     928             :         }
     929             : 
     930           0 :         if (bpi) {
     931             : 
     932             :                 /*
     933             :                  * Adding new local_nexthop, which does not by itself change
     934             :                  * what is advertised via BGP
     935             :                  */
     936           0 :                 if (lnh) {
     937           0 :                         if (!bpi->extra->vnc.export.local_nexthops) {
     938             :                                 /* TBD make arrangements to free when needed */
     939           0 :                                 bpi->extra->vnc.export.local_nexthops =
     940           0 :                                         list_new();
     941           0 :                                 bpi->extra->vnc.export.local_nexthops->del =
     942             :                                         rfapi_nexthop_free;
     943             :                         }
     944             : 
     945             :                         /*
     946             :                          * already present?
     947             :                          */
     948           0 :                         struct listnode *node;
     949           0 :                         struct rfapi_nexthop *pLnh = NULL;
     950             : 
     951           0 :                         for (ALL_LIST_ELEMENTS_RO(
     952             :                                      bpi->extra->vnc.export.local_nexthops,
     953             :                                      node, pLnh)) {
     954             : 
     955           0 :                                 if (prefix_same(&pLnh->addr, &lnh->addr)) {
     956             :                                         break;
     957             :                                 }
     958             :                         }
     959             : 
     960             :                         /*
     961             :                          * Not present, add new one
     962             :                          */
     963           0 :                         if (!pLnh) {
     964           0 :                                 pLnh = rfapi_nexthop_new(lnh);
     965           0 :                                 listnode_add(
     966           0 :                                         bpi->extra->vnc.export.local_nexthops,
     967             :                                         pLnh);
     968             :                         }
     969             :                 }
     970             : 
     971           0 :                 if (attrhash_cmp(bpi->attr, new_attr)
     972           0 :                     && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
     973           0 :                         bgp_attr_unintern(&new_attr);
     974           0 :                         bgp_dest_unlock_node(bn);
     975             : 
     976           0 :                         vnc_zlog_debug_any(
     977             :                                 "%s: Found route (safi=%d) at prefix %s, no change",
     978             :                                 __func__, safi, buf);
     979             : 
     980           0 :                         goto done;
     981             :                 } else {
     982             :                         /* The attribute is changed. */
     983           0 :                         bgp_path_info_set_flag(bn, bpi, BGP_PATH_ATTR_CHANGED);
     984             : 
     985           0 :                         if (safi == SAFI_MPLS_VPN) {
     986           0 :                                 struct bgp_dest *pdest = NULL;
     987           0 :                                 struct bgp_table *table = NULL;
     988             : 
     989           0 :                                 pdest = bgp_node_get(bgp->rib[afi][safi],
     990             :                                                      (struct prefix *)prd);
     991           0 :                                 table = bgp_dest_get_bgp_table_info(pdest);
     992           0 :                                 if (table)
     993           0 :                                         vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
     994             :                                                 bgp, prd, table, p, bpi);
     995           0 :                                 bgp_dest_unlock_node(pdest);
     996             :                         }
     997             : 
     998             :                         /* Rewrite BGP route information. */
     999           0 :                         if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
    1000           0 :                                 bgp_path_info_restore(bn, bpi);
    1001             :                         else
    1002           0 :                                 bgp_aggregate_decrement(bgp, p, bpi, afi, safi);
    1003           0 :                         bgp_attr_unintern(&bpi->attr);
    1004           0 :                         bpi->attr = new_attr;
    1005           0 :                         bpi->uptime = monotime(NULL);
    1006             : 
    1007             : 
    1008           0 :                         if (safi == SAFI_MPLS_VPN) {
    1009           0 :                                 struct bgp_dest *pdest = NULL;
    1010           0 :                                 struct bgp_table *table = NULL;
    1011             : 
    1012           0 :                                 pdest = bgp_node_get(bgp->rib[afi][safi],
    1013             :                                                      (struct prefix *)prd);
    1014           0 :                                 table = bgp_dest_get_bgp_table_info(pdest);
    1015           0 :                                 if (table)
    1016           0 :                                         vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
    1017             :                                                 bgp, prd, table, p, bpi);
    1018           0 :                                 bgp_dest_unlock_node(pdest);
    1019             :                         }
    1020             : 
    1021             :                         /* Process change. */
    1022           0 :                         bgp_aggregate_increment(bgp, p, bpi, afi, safi);
    1023           0 :                         bgp_process(bgp, bn, afi, safi);
    1024           0 :                         bgp_dest_unlock_node(bn);
    1025             : 
    1026           0 :                         vnc_zlog_debug_any(
    1027             :                                 "%s: Found route (safi=%d) at prefix %s, changed attr",
    1028             :                                 __func__, safi, buf);
    1029             : 
    1030           0 :                         goto done;
    1031             :                 }
    1032             :         }
    1033             : 
    1034           0 :         new = info_make(type, sub_type, 0, rfd->peer, new_attr, NULL);
    1035           0 :         SET_FLAG(new->flags, BGP_PATH_VALID);
    1036             : 
    1037             :         /* save backref to rfapi handle */
    1038           0 :         bgp_path_info_extra_get(new);
    1039           0 :         new->extra->vnc.export.rfapi_handle = (void *)rfd;
    1040           0 :         encode_label(label_val, &new->extra->label[0]);
    1041             : 
    1042             :         /* debug */
    1043             : 
    1044           0 :         if (VNC_DEBUG(VERBOSE)) {
    1045           0 :                 vnc_zlog_debug_verbose("%s: printing BPI", __func__);
    1046           0 :                 rfapiPrintBi(NULL, new);
    1047             :         }
    1048             : 
    1049           0 :         bgp_aggregate_increment(bgp, p, new, afi, safi);
    1050           0 :         bgp_path_info_add(bn, new);
    1051             : 
    1052           0 :         if (safi == SAFI_MPLS_VPN) {
    1053           0 :                 struct bgp_dest *pdest = NULL;
    1054           0 :                 struct bgp_table *table = NULL;
    1055             : 
    1056           0 :                 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
    1057           0 :                 table = bgp_dest_get_bgp_table_info(pdest);
    1058           0 :                 if (table)
    1059           0 :                         vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
    1060             :                                 bgp, prd, table, p, new);
    1061           0 :                 bgp_dest_unlock_node(pdest);
    1062           0 :                 encode_label(label_val, &bn->local_label);
    1063             :         }
    1064             : 
    1065           0 :         bgp_dest_unlock_node(bn);
    1066           0 :         bgp_process(bgp, bn, afi, safi);
    1067             : 
    1068           0 :         vnc_zlog_debug_any(
    1069             :                 "%s: Added route (safi=%s) at prefix %s (bn=%p, prd=%pRD)",
    1070             :                 __func__, safi2str(safi), buf, bn, prd);
    1071             : 
    1072           0 : done:
    1073             :         /* Loop back to import tables */
    1074           0 :         rfapiProcessUpdate(rfd->peer, rfd, p, prd, new_attr, afi, safi, type,
    1075             :                            sub_type, &label_val);
    1076           0 :         vnc_zlog_debug_verbose("%s: looped back import route (safi=%d)",
    1077             :                                __func__, safi);
    1078             : }
    1079             : 
    1080           0 : uint32_t rfp_cost_to_localpref(uint8_t cost)
    1081             : {
    1082           0 :         return 255 - cost;
    1083             : }
    1084             : 
    1085           0 : static void rfapiTunnelRouteAnnounce(struct bgp *bgp,
    1086             :                                      struct rfapi_descriptor *rfd,
    1087             :                                      uint32_t *pLifetime)
    1088             : {
    1089           0 :         struct prefix_rd prd;
    1090           0 :         struct prefix pfx_vn;
    1091           0 :         int rc;
    1092           0 :         uint32_t local_pref = rfp_cost_to_localpref(0);
    1093             : 
    1094           0 :         rc = rfapiRaddr2Qprefix(&(rfd->vn_addr), &pfx_vn);
    1095           0 :         assert(!rc);
    1096             : 
    1097             :         /*
    1098             :          * Construct route distinguisher = 0
    1099             :          */
    1100           0 :         memset(&prd, 0, sizeof(prd));
    1101           0 :         prd.family = AF_UNSPEC;
    1102           0 :         prd.prefixlen = 64;
    1103             : 
    1104           0 :         add_vnc_route(rfd,      /* rfapi descr, for export list  & backref */
    1105             :                       bgp,      /* which bgp instance */
    1106             :                       SAFI_ENCAP, /* which SAFI */
    1107             :                       &pfx_vn,    /* prefix to advertise */
    1108             :                       &prd,       /* route distinguisher to use */
    1109             :                       &rfd->un_addr, /* nexthop */
    1110             :                       &local_pref,
    1111             :                       pLifetime, /* max lifetime of child VPN routes */
    1112             :                       NULL,      /* no rfp options  for ENCAP safi */
    1113             :                       NULL,      /* rfp un options */
    1114             :                       NULL,      /* rfp vn options */
    1115             :                       rfd->rt_export_list, NULL, /* med */
    1116             :                       NULL,                      /* label: default */
    1117             :                       ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, 0);
    1118           0 : }
    1119             : 
    1120             : 
    1121             : /***********************************************************************
    1122             :  *                      RFP processing behavior configuration
    1123             :  ***********************************************************************/
    1124             : 
    1125             : /*------------------------------------------
    1126             :  * rfapi_rfp_set_configuration
    1127             :  *
    1128             :  * This is used to change rfapi's processing behavior based on
    1129             :  * RFP requirements.
    1130             :  *
    1131             :  * input:
    1132             :  *    rfp_start_val     value returned by rfp_start
    1133             :  *    rfapi_rfp_cfg     Pointer to configuration structure
    1134             :  *
    1135             :  * output:
    1136             :  *    none
    1137             :  *
    1138             :  * return value:
    1139             :  *      0               Success
    1140             :  *      ENXIO           Unabled to locate configured BGP/VNC
    1141             : --------------------------------------------*/
    1142           0 : int rfapi_rfp_set_configuration(void *rfp_start_val, struct rfapi_rfp_cfg *new)
    1143             : {
    1144           0 :         struct rfapi_rfp_cfg *rcfg;
    1145           0 :         struct bgp *bgp;
    1146             : 
    1147           0 :         bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
    1148             : 
    1149           0 :         if (!new || !bgp || !bgp->rfapi_cfg)
    1150             :                 return ENXIO;
    1151             : 
    1152           0 :         rcfg = &bgp->rfapi_cfg->rfp_cfg;
    1153           0 :         rcfg->download_type = new->download_type;
    1154           0 :         rcfg->ftd_advertisement_interval = new->ftd_advertisement_interval;
    1155           0 :         rcfg->holddown_factor = new->holddown_factor;
    1156             : 
    1157           0 :         if (rcfg->use_updated_response != new->use_updated_response) {
    1158           0 :                 rcfg->use_updated_response = new->use_updated_response;
    1159           0 :                 if (rcfg->use_updated_response)
    1160           0 :                         rfapiMonitorCallbacksOn(bgp);
    1161             :                 else
    1162           0 :                         rfapiMonitorCallbacksOff(bgp);
    1163             :         }
    1164           0 :         if (rcfg->use_removes != new->use_removes) {
    1165           0 :                 rcfg->use_removes = new->use_removes;
    1166           0 :                 if (rcfg->use_removes)
    1167           0 :                         rfapiMonitorResponseRemovalOn(bgp);
    1168             :                 else
    1169           0 :                         rfapiMonitorResponseRemovalOff(bgp);
    1170             :         }
    1171             :         return 0;
    1172             : }
    1173             : 
    1174             : /*------------------------------------------
    1175             :  * rfapi_rfp_set_cb_methods
    1176             :  *
    1177             :  * Change registered callback functions for asynchronous notifications
    1178             :  * from RFAPI to the RFP client.
    1179             :  *
    1180             :  * input:
    1181             :  *    rfp_start_val     value returned by rfp_start
    1182             :  *    methods           Pointer to struct rfapi_rfp_cb_methods containing
    1183             :  *                      pointers to callback methods as described above
    1184             :  *
    1185             :  * return value:
    1186             :  *      0               Success
    1187             :  *      ENXIO           BGP or VNC not configured
    1188             :  *------------------------------------------*/
    1189           0 : int rfapi_rfp_set_cb_methods(void *rfp_start_val,
    1190             :                              struct rfapi_rfp_cb_methods *methods)
    1191             : {
    1192           0 :         struct rfapi *h;
    1193           0 :         struct bgp *bgp;
    1194             : 
    1195           0 :         bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
    1196           0 :         if (!bgp)
    1197             :                 return ENXIO;
    1198             : 
    1199           0 :         h = bgp->rfapi;
    1200           0 :         if (!h)
    1201             :                 return ENXIO;
    1202             : 
    1203           0 :         h->rfp_methods = *methods;
    1204             : 
    1205           0 :         return 0;
    1206             : }
    1207             : 
    1208             : /***********************************************************************
    1209             :  *                      NVE Sessions
    1210             :  ***********************************************************************/
    1211             : /*
    1212             :  * Caller must supply an already-allocated rfd with the "caller"
    1213             :  * fields already set (vn_addr, un_addr, callback, cookie)
    1214             :  * The advertised_prefixes[] array elements should be NULL to
    1215             :  * have this function set them to newly-allocated radix trees.
    1216             :  */
    1217           0 : static int rfapi_open_inner(struct rfapi_descriptor *rfd, struct bgp *bgp,
    1218             :                             struct rfapi *h, struct rfapi_nve_group_cfg *rfg)
    1219             : {
    1220           0 :         int ret;
    1221             : 
    1222           0 :         if (h->flags & RFAPI_INCALLBACK)
    1223             :                 return EDEADLK;
    1224             : 
    1225             :         /*
    1226             :          * Fill in configured fields
    1227             :          */
    1228             : 
    1229             :         /*
    1230             :          * If group's RD is specified as "auto", then fill in based
    1231             :          * on NVE's VN address
    1232             :          */
    1233           0 :         rfd->rd = rfg->rd;
    1234             : 
    1235           0 :         if (rfd->rd.family == AF_UNIX) {
    1236           0 :                 ret = rfapi_set_autord_from_vn(&rfd->rd, &rfd->vn_addr);
    1237           0 :                 if (ret != 0)
    1238             :                         return ret;
    1239             :         }
    1240           0 :         rfd->rt_export_list = (rfg->rt_export_list)
    1241           0 :                                       ? ecommunity_dup(rfg->rt_export_list)
    1242           0 :                                       : NULL;
    1243           0 :         rfd->response_lifetime = rfg->response_lifetime;
    1244           0 :         rfd->rfg = rfg;
    1245             : 
    1246             :         /*
    1247             :          * Fill in BGP peer structure
    1248             :          */
    1249           0 :         rfd->peer = peer_new(bgp);
    1250           0 :         rfd->peer->status = Established; /* keep bgp core happy */
    1251           0 :         bgp_sync_delete(rfd->peer);      /* don't need these */
    1252             : 
    1253             :         /*
    1254             :          * since this peer is not on the I/O thread, this lock is not strictly
    1255             :          * necessary, but serves as a reminder to those who may meddle...
    1256             :          */
    1257           0 :         frr_with_mutex (&rfd->peer->io_mtx) {
    1258             :                 // we don't need any I/O related facilities
    1259           0 :                 if (rfd->peer->ibuf)
    1260           0 :                         stream_fifo_free(rfd->peer->ibuf);
    1261           0 :                 if (rfd->peer->obuf)
    1262           0 :                         stream_fifo_free(rfd->peer->obuf);
    1263             : 
    1264           0 :                 if (rfd->peer->ibuf_work)
    1265           0 :                         ringbuf_del(rfd->peer->ibuf_work);
    1266           0 :                 if (rfd->peer->obuf_work)
    1267           0 :                         stream_free(rfd->peer->obuf_work);
    1268             : 
    1269           0 :                 rfd->peer->ibuf = NULL;
    1270           0 :                 rfd->peer->obuf = NULL;
    1271           0 :                 rfd->peer->obuf_work = NULL;
    1272           0 :                 rfd->peer->ibuf_work = NULL;
    1273             :         }
    1274             : 
    1275             :         { /* base code assumes have valid host pointer */
    1276           0 :                 char buf[INET6_ADDRSTRLEN];
    1277           0 :                 buf[0] = 0;
    1278             : 
    1279           0 :                 if (rfd->vn_addr.addr_family == AF_INET) {
    1280           0 :                         inet_ntop(AF_INET, &rfd->vn_addr.addr.v4, buf,
    1281             :                                   sizeof(buf));
    1282           0 :                 } else if (rfd->vn_addr.addr_family == AF_INET6) {
    1283           0 :                         inet_ntop(AF_INET6, &rfd->vn_addr.addr.v6, buf,
    1284             :                                   sizeof(buf));
    1285             :                 }
    1286           0 :                 rfd->peer->host = XSTRDUP(MTYPE_BGP_PEER_HOST, buf);
    1287             :         }
    1288             :         /* Mark peer as belonging to HD */
    1289           0 :         SET_FLAG(rfd->peer->flags, PEER_FLAG_IS_RFAPI_HD);
    1290             : 
    1291             :         /*
    1292             :          * Set min prefix lifetime to max value so it will get set
    1293             :          * upon first rfapi_register()
    1294             :          */
    1295           0 :         rfd->min_prefix_lifetime = UINT32_MAX;
    1296             : 
    1297             : /*
    1298             :  * Allocate response tables if needed
    1299             :  */
    1300             : #define RFD_RTINIT_AFI(rh, ary, afi)                                           \
    1301             :         do {                                                                   \
    1302             :                 if (!ary[afi]) {                                               \
    1303             :                         ary[afi] = agg_table_init();                           \
    1304             :                         agg_set_table_info(ary[afi], rh);                      \
    1305             :                 }                                                              \
    1306             :         } while (0)
    1307             : 
    1308             : #define RFD_RTINIT(rh, ary)                                                    \
    1309             :         do {                                                                   \
    1310             :                 RFD_RTINIT_AFI(rh, ary, AFI_IP);                               \
    1311             :                 RFD_RTINIT_AFI(rh, ary, AFI_IP6);                              \
    1312             :                 RFD_RTINIT_AFI(rh, ary, AFI_L2VPN);                            \
    1313             :         } while (0)
    1314             : 
    1315           0 :         RFD_RTINIT(rfd, rfd->rib);
    1316           0 :         RFD_RTINIT(rfd, rfd->rib_pending);
    1317           0 :         RFD_RTINIT(rfd, rfd->rsp_times);
    1318             : 
    1319             :         /*
    1320             :          * Link to Import Table
    1321             :          */
    1322           0 :         rfd->import_table = rfg->rfapi_import_table;
    1323           0 :         rfd->import_table->refcount += 1;
    1324             : 
    1325           0 :         rfapiApInit(&rfd->advertised);
    1326             : 
    1327             :         /*
    1328             :          * add this NVE descriptor to the list of NVEs in the NVE group
    1329             :          */
    1330           0 :         if (!rfg->nves) {
    1331           0 :                 rfg->nves = list_new();
    1332             :         }
    1333           0 :         listnode_add(rfg->nves, rfd);
    1334             : 
    1335           0 :         vnc_direct_bgp_add_nve(bgp, rfd);
    1336           0 :         vnc_zebra_add_nve(bgp, rfd);
    1337             : 
    1338           0 :         return 0;
    1339             : }
    1340             : 
    1341             : /* moved from rfapi_register */
    1342           0 : int rfapi_init_and_open(struct bgp *bgp, struct rfapi_descriptor *rfd,
    1343             :                         struct rfapi_nve_group_cfg *rfg)
    1344             : {
    1345           0 :         struct rfapi *h = bgp->rfapi;
    1346           0 :         char buf_vn[BUFSIZ];
    1347           0 :         char buf_un[BUFSIZ];
    1348           0 :         afi_t afi_vn, afi_un;
    1349           0 :         struct prefix pfx_un;
    1350           0 :         struct agg_node *rn;
    1351             : 
    1352           0 :         rfd->open_time = monotime(NULL);
    1353             : 
    1354           0 :         if (rfg->type == RFAPI_GROUP_CFG_VRF)
    1355           0 :                 SET_FLAG(rfd->flags, RFAPI_HD_FLAG_IS_VRF);
    1356             : 
    1357           0 :         rfapiRfapiIpAddr2Str(&rfd->vn_addr, buf_vn, BUFSIZ);
    1358           0 :         rfapiRfapiIpAddr2Str(&rfd->un_addr, buf_un, BUFSIZ);
    1359             : 
    1360           0 :         vnc_zlog_debug_verbose("%s: new RFD with VN=%s UN=%s cookie=%p",
    1361             :                                __func__, buf_vn, buf_un, rfd->cookie);
    1362             : 
    1363           0 :         if (rfg->type != RFAPI_GROUP_CFG_VRF) /* unclear if needed for VRF */
    1364             :         {
    1365           0 :                 listnode_add(&h->descriptors, rfd);
    1366           0 :                 if (h->descriptors.count > h->stat.max_descriptors) {
    1367           0 :                         h->stat.max_descriptors = h->descriptors.count;
    1368             :                 }
    1369             : 
    1370             :                 /*
    1371             :                  * attach to UN radix tree
    1372             :                  */
    1373           0 :                 afi_vn = family2afi(rfd->vn_addr.addr_family);
    1374           0 :                 afi_un = family2afi(rfd->un_addr.addr_family);
    1375           0 :                 assert(afi_vn && afi_un);
    1376           0 :                 assert(!rfapiRaddr2Qprefix(&rfd->un_addr, &pfx_un));
    1377             : 
    1378           0 :                 rn = agg_node_get(h->un[afi_un], &pfx_un);
    1379           0 :                 assert(rn);
    1380           0 :                 rfd->next = rn->info;
    1381           0 :                 rn->info = rfd;
    1382           0 :                 rfd->un_node = rn;
    1383             :         }
    1384           0 :         return rfapi_open_inner(rfd, bgp, h, rfg);
    1385             : }
    1386             : 
    1387           0 : struct rfapi_vn_option *rfapiVnOptionsDup(struct rfapi_vn_option *orig)
    1388             : {
    1389           0 :         struct rfapi_vn_option *head = NULL;
    1390           0 :         struct rfapi_vn_option *tail = NULL;
    1391           0 :         struct rfapi_vn_option *vo = NULL;
    1392             : 
    1393           0 :         for (vo = orig; vo; vo = vo->next) {
    1394           0 :                 struct rfapi_vn_option *new;
    1395             : 
    1396           0 :                 new = XCALLOC(MTYPE_RFAPI_VN_OPTION,
    1397             :                               sizeof(struct rfapi_vn_option));
    1398           0 :                 memcpy(new, vo, sizeof(struct rfapi_vn_option));
    1399           0 :                 new->next = NULL;
    1400             : 
    1401           0 :                 if (tail) {
    1402           0 :                         tail->next = new;
    1403             :                 } else {
    1404             :                         head = tail = new;
    1405             :                 }
    1406             :         }
    1407           0 :         return head;
    1408             : }
    1409             : 
    1410           0 : struct rfapi_un_option *rfapiUnOptionsDup(struct rfapi_un_option *orig)
    1411             : {
    1412           0 :         struct rfapi_un_option *head = NULL;
    1413           0 :         struct rfapi_un_option *tail = NULL;
    1414           0 :         struct rfapi_un_option *uo = NULL;
    1415             : 
    1416           0 :         for (uo = orig; uo; uo = uo->next) {
    1417           0 :                 struct rfapi_un_option *new;
    1418             : 
    1419           0 :                 new = XCALLOC(MTYPE_RFAPI_UN_OPTION,
    1420             :                               sizeof(struct rfapi_un_option));
    1421           0 :                 memcpy(new, uo, sizeof(struct rfapi_un_option));
    1422           0 :                 new->next = NULL;
    1423             : 
    1424           0 :                 if (tail) {
    1425           0 :                         tail->next = new;
    1426             :                 } else {
    1427             :                         head = tail = new;
    1428             :                 }
    1429             :         }
    1430           0 :         return head;
    1431             : }
    1432             : 
    1433           0 : struct bgp_tea_options *rfapiOptionsDup(struct bgp_tea_options *orig)
    1434             : {
    1435           0 :         struct bgp_tea_options *head = NULL;
    1436           0 :         struct bgp_tea_options *tail = NULL;
    1437           0 :         struct bgp_tea_options *hop = NULL;
    1438             : 
    1439           0 :         for (hop = orig; hop; hop = hop->next) {
    1440           0 :                 struct bgp_tea_options *new;
    1441             : 
    1442           0 :                 new = XCALLOC(MTYPE_BGP_TEA_OPTIONS,
    1443             :                               sizeof(struct bgp_tea_options));
    1444           0 :                 memcpy(new, hop, sizeof(struct bgp_tea_options));
    1445           0 :                 new->next = NULL;
    1446           0 :                 if (hop->value) {
    1447           0 :                         new->value = XCALLOC(MTYPE_BGP_TEA_OPTIONS_VALUE,
    1448             :                                              hop->length);
    1449           0 :                         memcpy(new->value, hop->value, hop->length);
    1450             :                 }
    1451           0 :                 if (tail) {
    1452           0 :                         tail->next = new;
    1453             :                 } else {
    1454             :                         head = tail = new;
    1455             :                 }
    1456             :         }
    1457           0 :         return head;
    1458             : }
    1459             : 
    1460           0 : void rfapiFreeBgpTeaOptionChain(struct bgp_tea_options *p)
    1461             : {
    1462           0 :         struct bgp_tea_options *next;
    1463             : 
    1464           0 :         while (p) {
    1465           0 :                 next = p->next;
    1466             : 
    1467           0 :                 XFREE(MTYPE_BGP_TEA_OPTIONS_VALUE, p->value);
    1468           0 :                 XFREE(MTYPE_BGP_TEA_OPTIONS, p);
    1469             : 
    1470           0 :                 p = next;
    1471             :         }
    1472           0 : }
    1473             : 
    1474           0 : void rfapiAdbFree(struct rfapi_adb *adb)
    1475             : {
    1476           0 :         XFREE(MTYPE_RFAPI_ADB, adb);
    1477           0 : }
    1478             : 
    1479             : static int
    1480           0 : rfapi_query_inner(void *handle, struct rfapi_ip_addr *target,
    1481             :                   struct rfapi_l2address_option *l2o, /* may be NULL */
    1482             :                   struct rfapi_next_hop_entry **ppNextHopEntry)
    1483             : {
    1484           0 :         afi_t afi;
    1485           0 :         struct prefix p;
    1486           0 :         struct prefix p_original;
    1487           0 :         struct agg_node *rn;
    1488           0 :         struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
    1489           0 :         struct bgp *bgp = rfd->bgp;
    1490           0 :         struct rfapi_next_hop_entry *pNHE = NULL;
    1491           0 :         struct rfapi_ip_addr *self_vn_addr = NULL;
    1492           0 :         int eth_is_0 = 0;
    1493           0 :         int use_eth_resolution = 0;
    1494           0 :         struct rfapi_next_hop_entry *i_nhe;
    1495             : 
    1496             :         /* preemptive */
    1497           0 :         if (!bgp) {
    1498           0 :                 vnc_zlog_debug_verbose("%s: No BGP instance, returning ENXIO",
    1499             :                                        __func__);
    1500           0 :                 return ENXIO;
    1501             :         }
    1502           0 :         if (!bgp->rfapi) {
    1503           0 :                 vnc_zlog_debug_verbose("%s: No RFAPI instance, returning ENXIO",
    1504             :                                        __func__);
    1505           0 :                 return ENXIO;
    1506             :         }
    1507           0 :         if (bgp->rfapi->flags & RFAPI_INCALLBACK) {
    1508           0 :                 vnc_zlog_debug_verbose(
    1509             :                         "%s: Called during calback, returning EDEADLK",
    1510             :                         __func__);
    1511           0 :                 return EDEADLK;
    1512             :         }
    1513             : 
    1514           0 :         if (!is_valid_rfd(rfd)) {
    1515           0 :                 vnc_zlog_debug_verbose("%s: invalid handle, returning EBADF",
    1516             :                                        __func__);
    1517           0 :                 return EBADF;
    1518             :         }
    1519             : 
    1520           0 :         rfd->rsp_counter++;            /* dedup: identify this generation */
    1521           0 :         rfd->rsp_time = monotime(NULL);        /* response content dedup */
    1522           0 :         rfd->ftd_last_allowed_time =
    1523           0 :                 monotime(NULL) -
    1524           0 :                 bgp->rfapi_cfg->rfp_cfg.ftd_advertisement_interval;
    1525             : 
    1526           0 :         if (l2o) {
    1527           0 :                 if (!memcmp(l2o->macaddr.octet, rfapi_ethaddr0.octet,
    1528             :                             ETH_ALEN)) {
    1529           0 :                         eth_is_0 = 1;
    1530             :                 }
    1531             :                 /* per t/c Paul/Lou 151022 */
    1532           0 :                 if (!eth_is_0 || l2o->logical_net_id) {
    1533             :                         use_eth_resolution = 1;
    1534             :                 }
    1535             :         }
    1536             : 
    1537           0 :         if (ppNextHopEntry)
    1538           0 :                 *ppNextHopEntry = NULL;
    1539             : 
    1540             :         /*
    1541             :          * Save original target in prefix form. In case of L2-based queries,
    1542             :          * p_original will be modified to reflect the L2 target
    1543             :          */
    1544           0 :         assert(!rfapiRaddr2Qprefix(target, &p_original));
    1545             : 
    1546           0 :         if (bgp->rfapi_cfg->rfp_cfg.download_type == RFAPI_RFP_DOWNLOAD_FULL) {
    1547             :                 /* convert query to 0/0 when full-table download is enabled */
    1548           0 :                 memset((char *)&p, 0, sizeof(p));
    1549           0 :                 p.family = target->addr_family;
    1550             :         } else {
    1551           0 :                 p = p_original;
    1552             :         }
    1553             : 
    1554             :         {
    1555           0 :                 char *s;
    1556             : 
    1557           0 :                 vnc_zlog_debug_verbose("%s(rfd=%p, target=%pFX, ppNextHop=%p)",
    1558             :                                        __func__, rfd, &p, ppNextHopEntry);
    1559             : 
    1560           0 :                 s = ecommunity_ecom2str(rfd->import_table->rt_import_list,
    1561             :                                         ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
    1562           0 :                 vnc_zlog_debug_verbose(
    1563             :                         "%s rfd->import_table=%p, rfd->import_table->rt_import_list: %s",
    1564             :                         __func__, rfd->import_table, s);
    1565           0 :                 XFREE(MTYPE_ECOMMUNITY_STR, s);
    1566             :         }
    1567             : 
    1568           0 :         afi = family2afi(p.family);
    1569           0 :         assert(afi);
    1570             : 
    1571           0 :         if (CHECK_FLAG(bgp->rfapi_cfg->flags,
    1572             :                        BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP)) {
    1573           0 :                 self_vn_addr = &rfd->vn_addr;
    1574             :         }
    1575             : 
    1576           0 :         if (use_eth_resolution) {
    1577           0 :                 uint32_t logical_net_id = l2o->logical_net_id;
    1578           0 :                 struct ecommunity *l2com;
    1579             : 
    1580             :                 /*
    1581             :                  * fix up p_original to contain L2 address
    1582             :                  */
    1583           0 :                 rfapiL2o2Qprefix(l2o, &p_original);
    1584             : 
    1585           0 :                 l2com = bgp_rfapi_get_ecommunity_by_lni_label(
    1586             :                         bgp, 1, logical_net_id, l2o->label);
    1587           0 :                 if (l2com) {
    1588           0 :                         uint8_t *v = l2com->val;
    1589           0 :                         logical_net_id = (v[5] << 16) + (v[6] << 8) + (v[7]);
    1590             :                 }
    1591             :                 /*
    1592             :                  * Ethernet/L2-based lookup
    1593             :                  *
    1594             :                  * Always returns IT node corresponding to route
    1595             :                  */
    1596             : 
    1597           0 :                 if (RFAPI_RFP_DOWNLOAD_FULL
    1598           0 :                     == bgp->rfapi_cfg->rfp_cfg.download_type) {
    1599             :                         eth_is_0 = 1;
    1600             :                 }
    1601             : 
    1602           0 :                 rn = rfapiMonitorEthAdd(
    1603             :                         bgp, rfd, (eth_is_0 ? &rfapi_ethaddr0 : &l2o->macaddr),
    1604             :                         logical_net_id);
    1605             : 
    1606           0 :                 if (eth_is_0) {
    1607           0 :                         struct rfapi_ip_prefix rprefix;
    1608             : 
    1609           0 :                         memset(&rprefix, 0, sizeof(rprefix));
    1610           0 :                         rprefix.prefix.addr_family = target->addr_family;
    1611           0 :                         if (target->addr_family == AF_INET) {
    1612           0 :                                 rprefix.length = IPV4_MAX_BITLEN;
    1613             :                         } else {
    1614           0 :                                 rprefix.length = IPV6_MAX_BITLEN;
    1615             :                         }
    1616             : 
    1617           0 :                         pNHE = rfapiEthRouteTable2NextHopList(
    1618             :                                 logical_net_id, &rprefix,
    1619             :                                 rfd->response_lifetime, self_vn_addr,
    1620             :                                 rfd->rib[afi], &p_original);
    1621           0 :                         goto done;
    1622             :                 }
    1623             : 
    1624             :         } else {
    1625             : 
    1626             :                 /*
    1627             :                  * IP-based lookup
    1628             :                  */
    1629             : 
    1630           0 :                 rn = rfapiMonitorAdd(bgp, rfd, &p);
    1631             : 
    1632             :                 /*
    1633             :                  * If target address is 0, this request is special: means to
    1634             :                  * return ALL routes in the table
    1635             :                  *
    1636             :                  * Monitors for All-Routes queries get put on a special list,
    1637             :                  * not in the VPN tree
    1638             :                  */
    1639           0 :                 if (RFAPI_0_PREFIX(&p)) {
    1640             : 
    1641           0 :                         vnc_zlog_debug_verbose("%s: 0-prefix", __func__);
    1642             : 
    1643             :                         /*
    1644             :                          * Generate nexthop list for caller
    1645             :                          */
    1646           0 :                         pNHE = rfapiRouteTable2NextHopList(
    1647           0 :                                 rfd->import_table->imported_vpn[afi],
    1648             :                                 rfd->response_lifetime, self_vn_addr,
    1649             :                                 rfd->rib[afi], &p_original);
    1650           0 :                         goto done;
    1651             :                 }
    1652             : 
    1653           0 :                 if (rn) {
    1654           0 :                         agg_lock_node(rn); /* so we can unlock below */
    1655             :                 } else {
    1656             :                         /*
    1657             :                          * returns locked node. Don't unlock yet because the
    1658             :                          * unlock
    1659             :                          * might free it before we're done with it. This
    1660             :                          * situation
    1661             :                          * could occur when rfapiMonitorGetAttachNode() returns
    1662             :                          * a
    1663             :                          * newly-created default node.
    1664             :                          */
    1665           0 :                         rn = rfapiMonitorGetAttachNode(rfd, &p);
    1666             :                 }
    1667             :         }
    1668             : 
    1669           0 :         assert(rn);
    1670           0 :         if (!rn->info) {
    1671           0 :                 agg_unlock_node(rn);
    1672           0 :                 vnc_zlog_debug_verbose(
    1673             :                         "%s: VPN route not found, returning ENOENT", __func__);
    1674           0 :                 return ENOENT;
    1675             :         }
    1676             : 
    1677           0 :         if (VNC_DEBUG(RFAPI_QUERY)) {
    1678           0 :                 rfapiShowImportTable(NULL, "query",
    1679           0 :                                      rfd->import_table->imported_vpn[afi], 1);
    1680             :         }
    1681             : 
    1682           0 :         if (use_eth_resolution) {
    1683             : 
    1684           0 :                 struct rfapi_ip_prefix rprefix;
    1685             : 
    1686           0 :                 memset(&rprefix, 0, sizeof(rprefix));
    1687           0 :                 rprefix.prefix.addr_family = target->addr_family;
    1688           0 :                 if (target->addr_family == AF_INET) {
    1689           0 :                         rprefix.length = IPV4_MAX_BITLEN;
    1690             :                 } else {
    1691           0 :                         rprefix.length = IPV6_MAX_BITLEN;
    1692             :                 }
    1693             : 
    1694           0 :                 pNHE = rfapiEthRouteNode2NextHopList(
    1695             :                         rn, &rprefix, rfd->response_lifetime, self_vn_addr,
    1696             :                         rfd->rib[afi], &p_original);
    1697             : 
    1698             : 
    1699             :         } else {
    1700             :                 /*
    1701             :                  * Generate answer to query
    1702             :                  */
    1703           0 :                 pNHE = rfapiRouteNode2NextHopList(rn, rfd->response_lifetime,
    1704             :                                                   self_vn_addr, rfd->rib[afi],
    1705             :                                                   &p_original);
    1706             :         }
    1707             : 
    1708           0 :         agg_unlock_node(rn);
    1709             : 
    1710           0 : done:
    1711           0 :         if (ppNextHopEntry) {
    1712             :                 /* only count if caller gets it */
    1713           0 :                 ++bgp->rfapi->response_immediate_count;
    1714             :         }
    1715             : 
    1716           0 :         if (!pNHE) {
    1717           0 :                 vnc_zlog_debug_verbose("%s: NO NHEs, returning ENOENT",
    1718             :                                        __func__);
    1719           0 :                 return ENOENT;
    1720             :         }
    1721             : 
    1722             :         /*
    1723             :          * count nexthops for statistics
    1724             :          */
    1725           0 :         for (i_nhe = pNHE; i_nhe; i_nhe = i_nhe->next) {
    1726           0 :                 ++rfd->stat_count_nh_reachable;
    1727             :         }
    1728             : 
    1729           0 :         if (ppNextHopEntry) {
    1730           0 :                 *ppNextHopEntry = pNHE;
    1731             :         } else {
    1732           0 :                 rfapi_free_next_hop_list(pNHE);
    1733             :         }
    1734             : 
    1735           0 :         vnc_zlog_debug_verbose("%s: success", __func__);
    1736             :         return 0;
    1737             : }
    1738             : 
    1739             : /*
    1740             :  * support on-the-fly reassignment of an already-open nve to a new
    1741             :  * nve-group in the event that its original nve-group is
    1742             :  * administratively deleted.
    1743             :  */
    1744           0 : static int rfapi_open_rfd(struct rfapi_descriptor *rfd, struct bgp *bgp)
    1745             : {
    1746           0 :         struct prefix pfx_vn;
    1747           0 :         struct prefix pfx_un;
    1748           0 :         struct rfapi_nve_group_cfg *rfg;
    1749           0 :         struct rfapi *h;
    1750           0 :         struct rfapi_cfg *hc;
    1751           0 :         int rc;
    1752             : 
    1753           0 :         h = bgp->rfapi;
    1754           0 :         if (!h)
    1755             :                 return ENXIO;
    1756             : 
    1757           0 :         hc = bgp->rfapi_cfg;
    1758           0 :         if (!hc)
    1759             :                 return ENXIO;
    1760             : 
    1761           0 :         rc = rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx_vn);
    1762           0 :         assert(!rc);
    1763             : 
    1764           0 :         rc = rfapiRaddr2Qprefix(&rfd->un_addr, &pfx_un);
    1765           0 :         assert(!rc);
    1766             : 
    1767             :         /*
    1768             :          * Find the matching nve group config block
    1769             :          */
    1770           0 :         rfg = bgp_rfapi_cfg_match_group(hc, &pfx_vn, &pfx_un);
    1771           0 :         if (!rfg) {
    1772             :                 return ENOENT;
    1773             :         }
    1774             : 
    1775             :         /*
    1776             :          * check nve group config block for required values
    1777             :          */
    1778           0 :         if (!rfg->rt_export_list || !rfg->rfapi_import_table) {
    1779             : 
    1780             :                 return ENOMSG;
    1781             :         }
    1782             : 
    1783           0 :         rc = rfapi_open_inner(rfd, bgp, h, rfg);
    1784           0 :         if (rc) {
    1785             :                 return rc;
    1786             :         }
    1787             : 
    1788             :         /*
    1789             :          * re-advertise registered routes, this time as part of new NVE-group
    1790             :          */
    1791           0 :         rfapiApReadvertiseAll(bgp, rfd);
    1792             : 
    1793             :         /*
    1794             :          * re-attach callbacks to import table
    1795             :          */
    1796           0 :         if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)) {
    1797           0 :                 rfapiMonitorAttachImportHd(rfd);
    1798             :         }
    1799             : 
    1800             :         return 0;
    1801             : }
    1802             : 
    1803             : /*------------------------------------------
    1804             :  * rfapi_open
    1805             :  *
    1806             :  * This function initializes a NVE record and associates it with
    1807             :  * the specified VN and underlay network addresses
    1808             :  *
    1809             :  * input:
    1810             :  *      rfp_start_val   value returned by rfp_start
    1811             :  *      vn              NVE virtual network address
    1812             :  *
    1813             :  *      un              NVE underlay network address
    1814             :  *
    1815             :  *      default_options Default options to use on registrations.
    1816             :  *                      For now only tunnel type is supported.
    1817             :  *                      May be overridden per-prefix in rfapi_register().
    1818             :  *                      Caller owns (rfapi_open() does not free)
    1819             :  *
    1820             :  *      response_cb     Pointer to next hop list update callback function or
    1821             :  *                      NULL when no callbacks are desired.
    1822             :  *
    1823             :  *      userdata        Passed to subsequent response_cb invocations.
    1824             :  *
    1825             :  * output:
    1826             :  *      response_lifetime The length of time that responses sent to this
    1827             :  *                      NVE are valid.
    1828             :  *
    1829             :  *      pHandle         pointer to location to store rfapi handle. The
    1830             :  *                      handle must be passed on subsequent rfapi_ calls.
    1831             :  *
    1832             :  *
    1833             :  * return value:
    1834             :  *      0               Success
    1835             :  *      EEXIST          NVE with this {vn,un} already open
    1836             :  *      ENOENT          No matching nve group config
    1837             :  *      ENOMSG          Matched nve group config was incomplete
    1838             :  *      ENXIO           BGP or VNC not configured
    1839             :  *      EAFNOSUPPORT    Matched nve group specifies auto-assignment of RD,
    1840             :  *                      but underlay network address is not IPv4
    1841             :  *      EDEADLK         Called from within a callback procedure
    1842             :  *------------------------------------------*/
    1843           0 : int rfapi_open(void *rfp_start_val, struct rfapi_ip_addr *vn,
    1844             :                struct rfapi_ip_addr *un,
    1845             :                struct rfapi_un_option *default_options,
    1846             :                uint32_t *response_lifetime,
    1847             :                void *userdata, /* callback cookie */
    1848             :                rfapi_handle *pHandle)
    1849             : {
    1850           0 :         struct bgp *bgp;
    1851           0 :         struct rfapi *h;
    1852           0 :         struct rfapi_descriptor *rfd;
    1853           0 :         struct rfapi_cfg *hc;
    1854           0 :         struct rfapi_nve_group_cfg *rfg;
    1855             : 
    1856           0 :         struct prefix pfx_vn;
    1857           0 :         struct prefix pfx_un;
    1858             : 
    1859           0 :         int rc;
    1860           0 :         rfapi_handle hh = NULL;
    1861           0 :         int reusing_provisional = 0;
    1862             : 
    1863             :         {
    1864           0 :                 char buf[2][INET_ADDRSTRLEN];
    1865           0 :                 vnc_zlog_debug_verbose(
    1866             :                         "%s: VN=%s UN=%s", __func__,
    1867             :                         rfapiRfapiIpAddr2Str(vn, buf[0], INET_ADDRSTRLEN),
    1868             :                         rfapiRfapiIpAddr2Str(un, buf[1], INET_ADDRSTRLEN));
    1869             :         }
    1870             : 
    1871           0 :         assert(pHandle);
    1872           0 :         *pHandle = NULL;
    1873             : 
    1874           0 :         bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
    1875           0 :         if (!bgp)
    1876             :                 return ENXIO;
    1877             : 
    1878           0 :         h = bgp->rfapi;
    1879           0 :         if (!h)
    1880             :                 return ENXIO;
    1881             : 
    1882           0 :         hc = bgp->rfapi_cfg;
    1883           0 :         if (!hc)
    1884             :                 return ENXIO;
    1885             : 
    1886           0 :         if (h->flags & RFAPI_INCALLBACK)
    1887             :                 return EDEADLK;
    1888             : 
    1889           0 :         rc = rfapiRaddr2Qprefix(vn, &pfx_vn);
    1890           0 :         assert(!rc);
    1891             : 
    1892           0 :         rc = rfapiRaddr2Qprefix(un, &pfx_un);
    1893           0 :         assert(!rc);
    1894             : 
    1895             :         /*
    1896             :          * already have a descriptor with VN and UN?
    1897             :          */
    1898           0 :         if (!rfapi_find_handle(bgp, vn, un, &hh)) {
    1899             :                 /*
    1900             :                  * we might have set up a handle for static routes before
    1901             :                  * this NVE was opened. In that case, reuse the handle
    1902             :                  */
    1903           0 :                 rfd = hh;
    1904           0 :                 if (!CHECK_FLAG(rfd->flags, RFAPI_HD_FLAG_PROVISIONAL)) {
    1905             :                         return EEXIST;
    1906             :                 }
    1907             : 
    1908             :                 /*
    1909             :                  * reuse provisional descriptor
    1910             :                  * hh is not NULL
    1911             :                  */
    1912             :                 reusing_provisional = 1;
    1913             :         }
    1914             : 
    1915             :         /*
    1916             :          * Find the matching nve group config block
    1917             :          */
    1918           0 :         rfg = bgp_rfapi_cfg_match_group(hc, &pfx_vn, &pfx_un);
    1919           0 :         if (!rfg) {
    1920           0 :                 ++h->stat.count_unknown_nves;
    1921             :                 {
    1922           0 :                         char buf[2][INET_ADDRSTRLEN];
    1923           0 :                         zlog_notice("%s: no matching group VN=%s UN=%s",
    1924             :                                     __func__,
    1925             :                                     rfapiRfapiIpAddr2Str(vn, buf[0],
    1926             :                                                          INET_ADDRSTRLEN),
    1927             :                                     rfapiRfapiIpAddr2Str(un, buf[1],
    1928             :                                                          INET_ADDRSTRLEN));
    1929             :                 }
    1930           0 :                 return ENOENT;
    1931             :         }
    1932             : 
    1933             :         /*
    1934             :          * check nve group config block for required values
    1935             :          */
    1936           0 :         if (!rfg->rt_export_list || !rfg->rfapi_import_table) {
    1937             : 
    1938           0 :                 ++h->stat.count_unknown_nves;
    1939           0 :                 return ENOMSG;
    1940             :         }
    1941             : 
    1942             :         /*
    1943             :          * If group config specifies auto-rd assignment, check that
    1944             :          * VN address is IPv4|v6 so we don't fail in rfapi_open_inner().
    1945             :          * Check here so we don't need to unwind memory allocations, &c.
    1946             :          */
    1947           0 :         if ((rfg->rd.family == AF_UNIX) && (vn->addr_family != AF_INET)
    1948           0 :             && (vn->addr_family != AF_INET6)) {
    1949             :                 return EAFNOSUPPORT;
    1950             :         }
    1951             : 
    1952           0 :         if (hh) {
    1953             :                 /*
    1954             :                  * reusing provisional rfd
    1955             :                  */
    1956             :                 rfd = hh;
    1957             :         } else {
    1958           0 :                 rfd = XCALLOC(MTYPE_RFAPI_DESC,
    1959             :                               sizeof(struct rfapi_descriptor));
    1960             :         }
    1961             : 
    1962           0 :         rfd->bgp = bgp;
    1963           0 :         if (default_options) {
    1964             :                 struct rfapi_un_option *p;
    1965             : 
    1966           0 :                 for (p = default_options; p; p = p->next) {
    1967           0 :                         if ((RFAPI_UN_OPTION_TYPE_PROVISIONAL == p->type)) {
    1968           0 :                                 rfd->flags |= RFAPI_HD_FLAG_PROVISIONAL;
    1969             :                         }
    1970           0 :                         if ((RFAPI_UN_OPTION_TYPE_TUNNELTYPE == p->type)) {
    1971           0 :                                 rfd->default_tunneltype_option = p->v.tunnel;
    1972             :                         }
    1973             :                 }
    1974             :         }
    1975             : 
    1976             :         /*
    1977             :          * Fill in caller fields
    1978             :          */
    1979           0 :         rfd->vn_addr = *vn;
    1980           0 :         rfd->un_addr = *un;
    1981           0 :         rfd->cookie = userdata;
    1982             : 
    1983           0 :         if (!reusing_provisional) {
    1984           0 :                 rc = rfapi_init_and_open(bgp, rfd, rfg);
    1985             :                 /*
    1986             :                  * This can fail only if the VN address is IPv6 and the group
    1987             :                  * specified auto-assignment of RDs, which only works for v4,
    1988             :                  * and the check above should catch it.
    1989             :                  *
    1990             :                  * Another failure possibility is that we were called
    1991             :                  * during an rfapi callback. Also checked above.
    1992             :                  */
    1993           0 :                 assert(!rc);
    1994             :         }
    1995             : 
    1996           0 :         if (response_lifetime)
    1997           0 :                 *response_lifetime = rfd->response_lifetime;
    1998           0 :         *pHandle = rfd;
    1999           0 :         return 0;
    2000             : }
    2001             : 
    2002             : /*
    2003             :  * For use with debug functions
    2004             :  */
    2005           0 : static int rfapi_set_response_cb(struct rfapi_descriptor *rfd,
    2006             :                                  rfapi_response_cb_t *response_cb)
    2007             : {
    2008           0 :         if (!is_valid_rfd(rfd))
    2009             :                 return EBADF;
    2010           0 :         rfd->response_cb = response_cb;
    2011           0 :         return 0;
    2012             : }
    2013             : 
    2014             : /*
    2015             :  * rfapi_close_inner
    2016             :  *
    2017             :  * Does almost all the work of rfapi_close, except:
    2018             :  *      1. preserves the descriptor (doesn't free it)
    2019             :  *      2. preserves the prefix query list (i.e., rfd->mon list)
    2020             :  *      3. preserves the advertised prefix list (rfd->advertised)
    2021             :  *      4. preserves the rib and rib_pending tables
    2022             :  *
    2023             :  * The purpose of organizing it this way is to support on-the-fly
    2024             :  * reassignment of an already-open nve to a new nve-group in the
    2025             :  * event that its original nve-group is administratively deleted.
    2026             :  */
    2027           0 : static int rfapi_close_inner(struct rfapi_descriptor *rfd, struct bgp *bgp)
    2028             : {
    2029           0 :         int rc;
    2030           0 :         struct prefix pfx_vn;
    2031           0 :         struct prefix_rd prd; /* currently always 0 for VN->UN */
    2032             : 
    2033           0 :         if (!is_valid_rfd(rfd))
    2034             :                 return EBADF;
    2035             : 
    2036           0 :         rc = rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx_vn);
    2037           0 :         assert(!rc); /* should never have bad AF in stored vn address */
    2038             : 
    2039             :         /*
    2040             :          * update exported routes to reflect disappearance of this NVE as
    2041             :          * nexthop
    2042             :          */
    2043           0 :         vnc_direct_bgp_del_nve(bgp, rfd);
    2044           0 :         vnc_zebra_del_nve(bgp, rfd);
    2045             : 
    2046             :         /*
    2047             :          * unlink this HD's monitors from import table
    2048             :          */
    2049           0 :         rfapiMonitorDetachImportHd(rfd);
    2050             : 
    2051             :         /*
    2052             :          * Unlink from Import Table
    2053             :          * NB rfd->import_table will be NULL if we are closing a stale
    2054             :          * descriptor
    2055             :          */
    2056           0 :         if (rfd->import_table)
    2057           0 :                 rfapiImportTableRefDelByIt(bgp, rfd->import_table);
    2058           0 :         rfd->import_table = NULL;
    2059             : 
    2060             :         /*
    2061             :          * Construct route distinguisher
    2062             :          */
    2063           0 :         memset(&prd, 0, sizeof(prd));
    2064           0 :         prd = rfd->rd;
    2065           0 :         prd.family = AF_UNSPEC;
    2066           0 :         prd.prefixlen = 64;
    2067             : 
    2068             :         /*
    2069             :          * withdraw tunnel
    2070             :          */
    2071           0 :         del_vnc_route(rfd, rfd->peer, bgp, SAFI_ENCAP,
    2072             :                       &pfx_vn, /* prefix being advertised */
    2073             :                       &prd,    /* route distinguisher to use (0 for ENCAP) */
    2074             :                       ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, NULL, 0); /* no kill */
    2075             : 
    2076             :         /*
    2077             :          * Construct route distinguisher for VPN routes
    2078             :          */
    2079           0 :         prd = rfd->rd;
    2080           0 :         prd.family = AF_UNSPEC;
    2081           0 :         prd.prefixlen = 64;
    2082             : 
    2083             :         /*
    2084             :          * find all VPN routes associated with this rfd and delete them, too
    2085             :          */
    2086           0 :         rfapiApWithdrawAll(bgp, rfd);
    2087             : 
    2088             :         /*
    2089             :          * remove this nve descriptor from the list of nves
    2090             :          * associated with the nve group
    2091             :          */
    2092           0 :         if (rfd->rfg) {
    2093           0 :                 listnode_delete(rfd->rfg->nves, rfd);
    2094           0 :                 rfd->rfg = NULL; /* XXX mark as orphaned/stale */
    2095             :         }
    2096             : 
    2097           0 :         if (rfd->rt_export_list)
    2098           0 :                 ecommunity_free(&rfd->rt_export_list);
    2099           0 :         rfd->rt_export_list = NULL;
    2100             : 
    2101             :         /*
    2102             :          * free peer structure (possibly delayed until its
    2103             :          * refcount reaches zero)
    2104             :          */
    2105           0 :         if (rfd->peer) {
    2106           0 :                 vnc_zlog_debug_verbose("%s: calling peer_delete(%p), #%d",
    2107             :                                        __func__, rfd->peer, rfd->peer->lock);
    2108           0 :                 peer_delete(rfd->peer);
    2109             :         }
    2110           0 :         rfd->peer = NULL;
    2111             : 
    2112           0 :         return 0;
    2113             : }
    2114             : 
    2115           0 : int rfapi_close(void *handle)
    2116             : {
    2117           0 :         struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
    2118           0 :         int rc;
    2119           0 :         struct agg_node *node;
    2120           0 :         struct bgp *bgp;
    2121           0 :         struct rfapi *h;
    2122             : 
    2123           0 :         vnc_zlog_debug_verbose("%s: rfd=%p", __func__, rfd);
    2124             : 
    2125             : #ifdef RFAPI_WHO_IS_CALLING_ME
    2126             : #ifdef HAVE_GLIBC_BACKTRACE
    2127             : #define RFAPI_DEBUG_BACKTRACE_NENTRIES 5
    2128             :         {
    2129             :                 void *buf[RFAPI_DEBUG_BACKTRACE_NENTRIES];
    2130             :                 char **syms;
    2131             :                 int i;
    2132             :                 size_t size;
    2133             : 
    2134             :                 size = backtrace(buf, RFAPI_DEBUG_BACKTRACE_NENTRIES);
    2135             :                 syms = backtrace_symbols(buf, size);
    2136             :                 for (i = 0; i < size && i < RFAPI_DEBUG_BACKTRACE_NENTRIES;
    2137             :                      ++i) {
    2138             :                         vnc_zlog_debug_verbose("backtrace[%2d]: %s", i,
    2139             :                                                syms[i]);
    2140             :                 }
    2141             :                 free(syms);
    2142             :         }
    2143             : #endif
    2144             : #endif
    2145             : 
    2146           0 :         bgp = rfd->bgp;
    2147           0 :         if (!bgp)
    2148             :                 return ENXIO;
    2149             : 
    2150           0 :         h = bgp->rfapi;
    2151           0 :         if (!h)
    2152             :                 return ENXIO;
    2153             : 
    2154           0 :         if (!is_valid_rfd(rfd))
    2155             :                 return EBADF;
    2156             : 
    2157           0 :         if (h->flags & RFAPI_INCALLBACK) {
    2158             :                 /*
    2159             :                  * Queue these close requests for processing after callback
    2160             :                  * is finished
    2161             :                  */
    2162           0 :                 if (!CHECK_FLAG(rfd->flags,
    2163             :                                 RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY)) {
    2164           0 :                         work_queue_add(h->deferred_close_q, handle);
    2165           0 :                         vnc_zlog_debug_verbose(
    2166             :                                 "%s: added handle %p to deferred close queue",
    2167             :                                 __func__, handle);
    2168             :                 }
    2169           0 :                 return 0;
    2170             :         }
    2171             : 
    2172           0 :         if (CHECK_FLAG(rfd->flags, RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY)) {
    2173             : 
    2174           0 :                 vnc_zlog_debug_verbose("%s administrative close rfd=%p",
    2175             :                                        __func__, rfd);
    2176             : 
    2177           0 :                 if (h->rfp_methods.close_cb) {
    2178           0 :                         vnc_zlog_debug_verbose(
    2179             :                                 "%s calling close callback rfd=%p", __func__,
    2180             :                                 rfd);
    2181             : 
    2182             :                         /*
    2183             :                          * call the callback fairly early so that it can still
    2184             :                          * lookup un/vn
    2185             :                          * from handle, etc.
    2186             :                          *
    2187             :                          * NB RFAPI_INCALLBACK is tested above, so if we reach
    2188             :                          * this point
    2189             :                          * we are not already in the context of a callback.
    2190             :                          */
    2191           0 :                         h->flags |= RFAPI_INCALLBACK;
    2192           0 :                         (*h->rfp_methods.close_cb)(handle, EIDRM);
    2193           0 :                         h->flags &= ~RFAPI_INCALLBACK;
    2194             :                 }
    2195             :         }
    2196             : 
    2197           0 :         if (rfd->rfg) {
    2198             :                 /*
    2199             :                  * Orphaned descriptors have already done this part, so do
    2200             :                  * only for non-orphaned descriptors.
    2201             :                  */
    2202           0 :                 if ((rc = rfapi_close_inner(rfd, bgp)))
    2203             :                         return rc;
    2204             :         }
    2205             : 
    2206             :         /*
    2207             :          * Remove descriptor from UN index
    2208             :          * (remove from chain at node)
    2209             :          */
    2210           0 :         rc = rfapi_find_node(bgp, &rfd->vn_addr, &rfd->un_addr, &node);
    2211           0 :         if (!rc) {
    2212           0 :                 struct rfapi_descriptor *hh;
    2213             : 
    2214           0 :                 if (node->info == rfd) {
    2215           0 :                         node->info = rfd->next;
    2216             :                 } else {
    2217             : 
    2218           0 :                         for (hh = node->info; hh; hh = hh->next) {
    2219           0 :                                 if (hh->next == rfd) {
    2220           0 :                                         hh->next = rfd->next;
    2221           0 :                                         break;
    2222             :                                 }
    2223             :                         }
    2224             :                 }
    2225           0 :                 agg_unlock_node(node);
    2226             :         }
    2227             : 
    2228             :         /*
    2229             :          * remove from descriptor list
    2230             :          */
    2231           0 :         listnode_delete(&h->descriptors, rfd);
    2232             : 
    2233             :         /*
    2234             :          * Delete monitor list items and free monitor structures
    2235             :          */
    2236           0 :         (void)rfapiMonitorDelHd(rfd);
    2237             : 
    2238             :         /*
    2239             :          * release advertised prefix data
    2240             :          */
    2241           0 :         rfapiApRelease(&rfd->advertised);
    2242             : 
    2243             :         /*
    2244             :          * Release RFP callback RIB
    2245             :          */
    2246           0 :         rfapiRibFree(rfd);
    2247             : 
    2248             :         /*
    2249             :          * free descriptor
    2250             :          */
    2251           0 :         memset(rfd, 0, sizeof(struct rfapi_descriptor));
    2252           0 :         XFREE(MTYPE_RFAPI_DESC, rfd);
    2253             : 
    2254           0 :         return 0;
    2255             : }
    2256             : 
    2257             : /*
    2258             :  * Reopen a nve descriptor. If the descriptor's NVE-group
    2259             :  * does not exist (e.g., if it has been administratively removed),
    2260             :  * reassignment to a new NVE-group is attempted.
    2261             :  *
    2262             :  * If NVE-group reassignment fails, the descriptor becomes "stale"
    2263             :  * (rfd->rfg == NULL implies "stale:). The only permissible API operation
    2264             :  * on a stale descriptor is rfapi_close(). Any other rfapi_* API operation
    2265             :  * on the descriptor will return ESTALE.
    2266             :  *
    2267             :  * Reopening a descriptor is a potentially expensive operation, because
    2268             :  * it involves withdrawing any routes advertised by the NVE, withdrawing
    2269             :  * the NVE's route queries, and then re-adding them all after a new
    2270             :  * NVE-group is assigned. There are also possible route-export affects
    2271             :  * caused by deleting and then adding the NVE: advertised prefixes
    2272             :  * and nexthop lists for exported routes can turn over.
    2273             :  */
    2274           0 : int rfapi_reopen(struct rfapi_descriptor *rfd, struct bgp *bgp)
    2275             : {
    2276           0 :         struct rfapi *h;
    2277           0 :         int rc;
    2278             : 
    2279           0 :         if ((rc = rfapi_close_inner(rfd, bgp))) {
    2280             :                 return rc;
    2281             :         }
    2282           0 :         if ((rc = rfapi_open_rfd(rfd, bgp))) {
    2283             : 
    2284           0 :                 h = bgp->rfapi;
    2285             : 
    2286           0 :                 assert(h != NULL && !CHECK_FLAG(h->flags, RFAPI_INCALLBACK));
    2287             : 
    2288           0 :                 if (CHECK_FLAG(rfd->flags,
    2289             :                                RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY)
    2290           0 :                     && h && h->rfp_methods.close_cb) {
    2291             : 
    2292             :                         /*
    2293             :                          * NB RFAPI_INCALLBACK is tested above, so if we reach
    2294             :                          * this point
    2295             :                          * we are not already in the context of a callback.
    2296             :                          */
    2297           0 :                         h->flags |= RFAPI_INCALLBACK;
    2298           0 :                         (*h->rfp_methods.close_cb)((rfapi_handle)rfd, ESTALE);
    2299           0 :                         h->flags &= ~RFAPI_INCALLBACK;
    2300             :                 }
    2301           0 :                 return rc;
    2302             :         }
    2303             :         return 0;
    2304             : }
    2305             : 
    2306             : /***********************************************************************
    2307             :  *                      NVE Routes
    2308             :  ***********************************************************************/
    2309             : /*
    2310             :  * Announce reachability to this prefix via the NVE
    2311             :  */
    2312           0 : int rfapi_register(void *handle, struct rfapi_ip_prefix *prefix,
    2313             :                    uint32_t lifetime, /* host byte order */
    2314             :                    struct rfapi_un_option *options_un,
    2315             :                    struct rfapi_vn_option *options_vn,
    2316             :                    rfapi_register_action action)
    2317             : {
    2318           0 :         struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
    2319           0 :         struct bgp *bgp;
    2320           0 :         struct prefix p;
    2321           0 :         struct prefix *pfx_ip = NULL;
    2322           0 :         struct prefix_rd prd;
    2323           0 :         afi_t afi;
    2324           0 :         struct prefix pfx_mac_buf;
    2325           0 :         struct prefix *pfx_mac = NULL;
    2326           0 :         struct prefix pfx_vn_buf;
    2327           0 :         const char *action_str = NULL;
    2328           0 :         uint32_t *label = NULL;
    2329           0 :         struct rfapi_vn_option *vo;
    2330           0 :         struct rfapi_l2address_option *l2o = NULL;
    2331           0 :         struct prefix_rd *prd_override = NULL;
    2332             : 
    2333           0 :         switch (action) {
    2334             :         case RFAPI_REGISTER_ADD:
    2335             :                 action_str = "add";
    2336             :                 break;
    2337           0 :         case RFAPI_REGISTER_WITHDRAW:
    2338           0 :                 action_str = "withdraw";
    2339           0 :                 break;
    2340           0 :         case RFAPI_REGISTER_KILL:
    2341           0 :                 action_str = "kill";
    2342           0 :                 break;
    2343             :         default:
    2344           0 :                 assert(0);
    2345             :                 break;
    2346             :         }
    2347             : 
    2348             :         /*
    2349             :          * Inspect VN options
    2350             :          */
    2351           0 :         for (vo = options_vn; vo; vo = vo->next) {
    2352           0 :                 if (RFAPI_VN_OPTION_TYPE_L2ADDR == vo->type) {
    2353           0 :                         l2o = &vo->v.l2addr;
    2354             :                 }
    2355           0 :                 if (RFAPI_VN_OPTION_TYPE_INTERNAL_RD == vo->type) {
    2356           0 :                         prd_override = &vo->v.internal_rd;
    2357             :                 }
    2358             :         }
    2359             : 
    2360             :         /*********************************************************************
    2361             :          *                      advertise prefix
    2362             :          *********************************************************************/
    2363             : 
    2364             :         /*
    2365             :          * set <p> based on <prefix>
    2366             :          */
    2367           0 :         assert(!rfapiRprefix2Qprefix(prefix, &p));
    2368             : 
    2369           0 :         afi = family2afi(prefix->prefix.addr_family);
    2370           0 :         assert(afi);
    2371             : 
    2372           0 :         vnc_zlog_debug_verbose(
    2373             :                 "%s(rfd=%p, pfx=%pFX, lifetime=%d, opts_un=%p, opts_vn=%p, action=%s)",
    2374             :                 __func__, rfd, &p, lifetime, options_un, options_vn,
    2375             :                 action_str);
    2376             : 
    2377             :         /*
    2378             :          * These tests come after the prefix conversion so that we can
    2379             :          * print the prefix in a debug message before failing
    2380             :          */
    2381             : 
    2382           0 :         bgp = rfd->bgp;
    2383           0 :         if (!bgp) {
    2384           0 :                 vnc_zlog_debug_verbose("%s: no BGP instance: returning ENXIO",
    2385             :                                        __func__);
    2386           0 :                 return ENXIO;
    2387             :         }
    2388           0 :         if (!bgp->rfapi) {
    2389           0 :                 vnc_zlog_debug_verbose("%s: no RFAPI instance: returning ENXIO",
    2390             :                                        __func__);
    2391           0 :                 return ENXIO;
    2392             :         }
    2393           0 :         if (!rfd->rfg) {
    2394           0 :                 if (RFAPI_REGISTER_ADD == action) {
    2395           0 :                         ++bgp->rfapi->stat.count_registrations_failed;
    2396             :                 }
    2397           0 :                 vnc_zlog_debug_verbose(
    2398             :                         "%s: rfd=%p, no RF GRP instance: returning ESTALE",
    2399             :                         __func__, rfd);
    2400           0 :                 return ESTALE;
    2401             :         }
    2402             : 
    2403           0 :         if (bgp->rfapi->flags & RFAPI_INCALLBACK) {
    2404           0 :                 if (RFAPI_REGISTER_ADD == action) {
    2405           0 :                         ++bgp->rfapi->stat.count_registrations_failed;
    2406             :                 }
    2407           0 :                 vnc_zlog_debug_verbose("%s: in callback: returning EDEADLK",
    2408             :                                        __func__);
    2409           0 :                 return EDEADLK;
    2410             :         }
    2411             : 
    2412           0 :         if (!is_valid_rfd(rfd)) {
    2413           0 :                 if (RFAPI_REGISTER_ADD == action) {
    2414           0 :                         ++bgp->rfapi->stat.count_registrations_failed;
    2415             :                 }
    2416           0 :                 vnc_zlog_debug_verbose("%s: invalid handle: returning EBADF",
    2417             :                                        __func__);
    2418           0 :                 return EBADF;
    2419             :         }
    2420             : 
    2421             :         /*
    2422             :          * Is there a MAC address in this registration?
    2423             :          */
    2424           0 :         if (l2o && !RFAPI_0_ETHERADDR(&l2o->macaddr)) {
    2425           0 :                 rfapiL2o2Qprefix(l2o, &pfx_mac_buf);
    2426           0 :                 pfx_mac = &pfx_mac_buf;
    2427             :         }
    2428             : 
    2429             :         /*
    2430             :          * Is there an IP prefix in this registration?
    2431             :          */
    2432           0 :         if (!(RFAPI_0_PREFIX(&p) && RFAPI_HOST_PREFIX(&p))) {
    2433             :                 pfx_ip = &p;
    2434             :         } else {
    2435           0 :                 if (!pfx_mac) {
    2436           0 :                         vnc_zlog_debug_verbose(
    2437             :                                 "%s: missing mac addr that is required for host 0 pfx",
    2438             :                                 __func__);
    2439           0 :                         if (RFAPI_REGISTER_ADD == action) {
    2440           0 :                                 ++bgp->rfapi->stat.count_registrations_failed;
    2441             :                         }
    2442           0 :                         return EINVAL;
    2443             :                 }
    2444           0 :                 if (rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx_vn_buf)) {
    2445           0 :                         vnc_zlog_debug_verbose(
    2446             :                                 "%s: handle has bad vn_addr: returning EBADF",
    2447             :                                 __func__);
    2448           0 :                         if (RFAPI_REGISTER_ADD == action) {
    2449           0 :                                 ++bgp->rfapi->stat.count_registrations_failed;
    2450             :                         }
    2451           0 :                         return EBADF;
    2452             :                 }
    2453             :         }
    2454             : 
    2455           0 :         if (RFAPI_REGISTER_ADD == action) {
    2456           0 :                 ++bgp->rfapi->stat.count_registrations;
    2457             :         }
    2458             : 
    2459             :         /*
    2460             :          * Figure out if this registration is missing an IP address
    2461             :          *
    2462             :          * MAC-addr based:
    2463             :          *
    2464             :          *  In RFAPI, we use prefixes in family AF_LINK to store
    2465             :          *  the MAC addresses. These prefixes are used for the
    2466             :          *  list of advertised prefixes and in the RFAPI import
    2467             :          *  tables.
    2468             :          *
    2469             :          *  In BGP proper, we use the prefix matching the NVE's
    2470             :          *  VN address with a host prefix-length (i.e., 32 or 128).
    2471             :          *
    2472             :          */
    2473           0 :         if (l2o && l2o->logical_net_id && RFAPI_0_PREFIX(&p)
    2474           0 :             && RFAPI_HOST_PREFIX(&p)) {
    2475             : 
    2476           0 :                 rfapiL2o2Qprefix(l2o, &pfx_mac_buf);
    2477           0 :                 pfx_mac = &pfx_mac_buf;
    2478             :         }
    2479             : 
    2480             :         /*
    2481             :          * Construct route distinguisher
    2482             :          */
    2483           0 :         if (prd_override) {
    2484           0 :                 prd = *prd_override;
    2485             :         } else {
    2486           0 :                 memset(&prd, 0, sizeof(prd));
    2487           0 :                 if (pfx_mac) {
    2488           0 :                         prd.family = AF_UNSPEC;
    2489           0 :                         prd.prefixlen = 64;
    2490           0 :                         encode_rd_type(RD_TYPE_VNC_ETH, prd.val);
    2491           0 :                         if (l2o->local_nve_id
    2492           0 :                             || !(rfd->rfg->flags & RFAPI_RFG_L2RD)) {
    2493             :                                 /*
    2494             :                                  * If Local NVE ID is specified in message, use
    2495             :                                  * it.
    2496             :                                  * (if no local default configured, also use it
    2497             :                                  * even if 0)
    2498             :                                  */
    2499           0 :                                 prd.val[1] = l2o->local_nve_id;
    2500             :                         } else {
    2501           0 :                                 if (rfd->rfg->l2rd) {
    2502             :                                         /*
    2503             :                                          * locally-configured literal value
    2504             :                                          */
    2505           0 :                                         prd.val[1] = rfd->rfg->l2rd;
    2506             :                                 } else {
    2507             :                                         /*
    2508             :                                          * 0 means auto:vn, which means use LSB
    2509             :                                          * of VN addr
    2510             :                                          */
    2511           0 :                                         if (rfd->vn_addr.addr_family
    2512             :                                             == AF_INET) {
    2513           0 :                                                 prd.val[1] =
    2514           0 :                                                         *(((char *)&rfd->vn_addr
    2515             :                                                                    .addr.v4
    2516             :                                                                    .s_addr)
    2517             :                                                           + 3);
    2518             :                                         } else {
    2519           0 :                                                 prd.val[1] =
    2520           0 :                                                         *(((char *)&rfd->vn_addr
    2521             :                                                                    .addr.v6
    2522             :                                                                    .s6_addr)
    2523             :                                                           + 15);
    2524             :                                         }
    2525             :                                 }
    2526             :                         }
    2527           0 :                         memcpy(prd.val + 2, pfx_mac->u.prefix_eth.octet, 6);
    2528             :                 } else {
    2529           0 :                         prd = rfd->rd;
    2530           0 :                         prd.family = AF_UNSPEC;
    2531           0 :                         prd.prefixlen = 64;
    2532             :                 }
    2533             :         }
    2534             : 
    2535             : 
    2536           0 :         if (action == RFAPI_REGISTER_WITHDRAW
    2537           0 :             || action == RFAPI_REGISTER_KILL) {
    2538             : 
    2539           0 :                 int adv_tunnel = 0;
    2540             : 
    2541             :                 /*
    2542             :                  * withdraw previous advertisement
    2543             :                  */
    2544           0 :                 del_vnc_route(
    2545             :                         rfd, rfd->peer, bgp, SAFI_MPLS_VPN,
    2546             :                         pfx_ip ? pfx_ip
    2547             :                                : &pfx_vn_buf, /* prefix being advertised */
    2548             :                         &prd, /* route distinguisher (0 for ENCAP) */
    2549             :                         ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, NULL,
    2550             :                         action == RFAPI_REGISTER_KILL);
    2551             : 
    2552           0 :                 if (0 == rfapiApDelete(bgp, rfd, &p, pfx_mac, &prd,
    2553             :                                        &adv_tunnel)) {
    2554           0 :                         if (adv_tunnel)
    2555           0 :                                 rfapiTunnelRouteAnnounce(
    2556             :                                         bgp, rfd, &rfd->max_prefix_lifetime);
    2557             :                 }
    2558             : 
    2559             :         } else {
    2560             : 
    2561           0 :                 int adv_tunnel = 0;
    2562           0 :                 uint32_t local_pref;
    2563           0 :                 struct ecommunity *rtlist = NULL;
    2564           0 :                 struct ecommunity_val ecom_value;
    2565             : 
    2566           0 :                 if (!rfapiApCount(rfd)) {
    2567             :                         /*
    2568             :                          * make sure we advertise tunnel route upon adding the
    2569             :                          * first VPN route
    2570             :                          */
    2571           0 :                         adv_tunnel = 1;
    2572             :                 }
    2573             : 
    2574           0 :                 if (rfapiApAdd(bgp, rfd, &p, pfx_mac, &prd, lifetime,
    2575           0 :                                prefix->cost, l2o)) {
    2576           0 :                         adv_tunnel = 1;
    2577             :                 }
    2578             : 
    2579           0 :                 vnc_zlog_debug_verbose("%s: adv_tunnel = %d", __func__,
    2580             :                                        adv_tunnel);
    2581           0 :                 if (adv_tunnel) {
    2582           0 :                         vnc_zlog_debug_verbose("%s: announcing tunnel route",
    2583             :                                                __func__);
    2584           0 :                         rfapiTunnelRouteAnnounce(bgp, rfd,
    2585             :                                                  &rfd->max_prefix_lifetime);
    2586             :                 }
    2587             : 
    2588           0 :                 vnc_zlog_debug_verbose("%s: calling add_vnc_route", __func__);
    2589             : 
    2590           0 :                 local_pref = rfp_cost_to_localpref(prefix->cost);
    2591             : 
    2592           0 :                 if (l2o && l2o->label)
    2593           0 :                         label = &l2o->label;
    2594             : 
    2595           0 :                 if (pfx_mac) {
    2596           0 :                         struct ecommunity *l2com = NULL;
    2597             : 
    2598           0 :                         if (label) {
    2599           0 :                                 l2com = bgp_rfapi_get_ecommunity_by_lni_label(
    2600             :                                         bgp, 1, l2o->logical_net_id, *label);
    2601             :                         }
    2602           0 :                         if (l2com) {
    2603           0 :                                 rtlist = ecommunity_dup(l2com);
    2604             :                         } else {
    2605             :                                 /*
    2606             :                                  * If mac address is set, add an RT based on the
    2607             :                                  * registered LNI
    2608             :                                  */
    2609           0 :                                 memset((char *)&ecom_value, 0,
    2610             :                                        sizeof(ecom_value));
    2611           0 :                                 ecom_value.val[1] = ECOMMUNITY_ROUTE_TARGET;
    2612           0 :                                 ecom_value.val[5] =
    2613           0 :                                         (l2o->logical_net_id >> 16) & 0xff;
    2614           0 :                                 ecom_value.val[6] =
    2615           0 :                                         (l2o->logical_net_id >> 8) & 0xff;
    2616           0 :                                 ecom_value.val[7] =
    2617             :                                         (l2o->logical_net_id >> 0) & 0xff;
    2618           0 :                                 rtlist = ecommunity_new();
    2619           0 :                                 ecommunity_add_val(rtlist, &ecom_value,
    2620             :                                                    false, false);
    2621             :                         }
    2622           0 :                         if (l2o->tag_id) {
    2623           0 :                                 as_t as = bgp->as;
    2624           0 :                                 uint16_t val = l2o->tag_id;
    2625           0 :                                 memset((char *)&ecom_value, 0,
    2626             :                                        sizeof(ecom_value));
    2627           0 :                                 ecom_value.val[1] = ECOMMUNITY_ROUTE_TARGET;
    2628           0 :                                 if (as > BGP_AS_MAX) {
    2629           0 :                                         ecom_value.val[0] =
    2630             :                                                 ECOMMUNITY_ENCODE_AS4;
    2631           0 :                                         ecom_value.val[2] = (as >> 24) & 0xff;
    2632           0 :                                         ecom_value.val[3] = (as >> 16) & 0xff;
    2633           0 :                                         ecom_value.val[4] = (as >> 8) & 0xff;
    2634           0 :                                         ecom_value.val[5] = as & 0xff;
    2635             :                                 } else {
    2636           0 :                                         ecom_value.val[0] =
    2637             :                                                 ECOMMUNITY_ENCODE_AS;
    2638           0 :                                         ecom_value.val[2] = (as >> 8) & 0xff;
    2639           0 :                                         ecom_value.val[3] = as & 0xff;
    2640             :                                 }
    2641           0 :                                 ecom_value.val[6] = (val >> 8) & 0xff;
    2642           0 :                                 ecom_value.val[7] = val & 0xff;
    2643           0 :                                 if (rtlist == NULL)
    2644           0 :                                         rtlist = ecommunity_new();
    2645           0 :                                 ecommunity_add_val(rtlist, &ecom_value,
    2646             :                                                    false, false);
    2647             :                         }
    2648             :                 }
    2649             : 
    2650             :                 /*
    2651             :                  * advertise prefix via tunnel endpoint
    2652             :                  */
    2653           0 :                 add_vnc_route(
    2654             :                         rfd, /* rfapi descr, for export list & backref */
    2655             :                         bgp, /* which bgp instance */
    2656             :                         SAFI_MPLS_VPN, /* which SAFI */
    2657             :                         (pfx_ip ? pfx_ip
    2658             :                                 : &pfx_vn_buf), /* prefix being advertised */
    2659             :                         &prd, /* route distinguisher to use (0 for ENCAP) */
    2660             :                         &rfd->vn_addr, /* nexthop */
    2661             :                         &local_pref,
    2662             :                         &lifetime, /* prefix lifetime -> Tunnel Encap attr */
    2663             :                         NULL, options_un, /* rfapi un options */
    2664             :                         options_vn,       /* rfapi vn options */
    2665           0 :                         (rtlist ? rtlist : rfd->rt_export_list), NULL, /* med */
    2666             :                         label, /* label: default */
    2667             :                         ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, 0);
    2668             : 
    2669           0 :                 if (rtlist)
    2670           0 :                         ecommunity_free(&rtlist); /* sets rtlist = NULL */
    2671             :         }
    2672             : 
    2673           0 :         vnc_zlog_debug_verbose("%s: success", __func__);
    2674             :         return 0;
    2675             : }
    2676             : 
    2677           0 : int rfapi_query(void *handle, struct rfapi_ip_addr *target,
    2678             :                 struct rfapi_l2address_option *l2o, /* may be NULL */
    2679             :                 struct rfapi_next_hop_entry **ppNextHopEntry)
    2680             : {
    2681           0 :         struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
    2682           0 :         struct bgp *bgp = rfd->bgp;
    2683           0 :         int rc;
    2684             : 
    2685           0 :         assert(ppNextHopEntry);
    2686           0 :         *ppNextHopEntry = NULL;
    2687             : 
    2688           0 :         if (bgp && bgp->rfapi) {
    2689           0 :                 bgp->rfapi->stat.count_queries++;
    2690             :         }
    2691             : 
    2692           0 :         if (!rfd->rfg) {
    2693           0 :                 if (bgp && bgp->rfapi)
    2694           0 :                         ++bgp->rfapi->stat.count_queries_failed;
    2695           0 :                 return ESTALE;
    2696             :         }
    2697             : 
    2698           0 :         if ((rc = rfapi_query_inner(handle, target, l2o, ppNextHopEntry))) {
    2699           0 :                 if (bgp && bgp->rfapi)
    2700           0 :                         ++bgp->rfapi->stat.count_queries_failed;
    2701             :         }
    2702             :         return rc;
    2703             : }
    2704             : 
    2705           0 : int rfapi_query_done(rfapi_handle handle, struct rfapi_ip_addr *target)
    2706             : {
    2707           0 :         struct prefix p;
    2708           0 :         int rc;
    2709           0 :         struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
    2710           0 :         struct bgp *bgp = rfd->bgp;
    2711             : 
    2712           0 :         if (!rfd->rfg)
    2713             :                 return ESTALE;
    2714             : 
    2715           0 :         assert(target);
    2716           0 :         rc = rfapiRaddr2Qprefix(target, &p);
    2717           0 :         assert(!rc);
    2718             : 
    2719           0 :         if (!is_valid_rfd(rfd))
    2720             :                 return EBADF;
    2721             : 
    2722             :         /* preemptive */
    2723           0 :         if (!bgp || !bgp->rfapi)
    2724             :                 return ENXIO;
    2725             : 
    2726           0 :         if (bgp->rfapi->flags & RFAPI_INCALLBACK)
    2727             :                 return EDEADLK;
    2728             : 
    2729           0 :         rfapiMonitorDel(bgp, rfd, &p);
    2730             : 
    2731           0 :         return 0;
    2732             : }
    2733             : 
    2734           0 : int rfapi_query_done_all(rfapi_handle handle, int *count)
    2735             : {
    2736           0 :         struct rfapi_descriptor *rfd = (struct rfapi_descriptor *)handle;
    2737           0 :         struct bgp *bgp = rfd->bgp;
    2738           0 :         ;
    2739           0 :         int num;
    2740             : 
    2741           0 :         if (!rfd->rfg)
    2742             :                 return ESTALE;
    2743             : 
    2744           0 :         if (!is_valid_rfd(rfd))
    2745             :                 return EBADF;
    2746             : 
    2747             :         /* preemptive */
    2748           0 :         if (!bgp || !bgp->rfapi)
    2749             :                 return ENXIO;
    2750             : 
    2751           0 :         if (bgp->rfapi->flags & RFAPI_INCALLBACK)
    2752             :                 return EDEADLK;
    2753             : 
    2754           0 :         num = rfapiMonitorDelHd(rfd);
    2755             : 
    2756           0 :         if (count)
    2757           0 :                 *count = num;
    2758             : 
    2759             :         return 0;
    2760             : }
    2761             : 
    2762           0 : void rfapi_free_next_hop_list(struct rfapi_next_hop_entry *list)
    2763             : {
    2764           0 :         struct rfapi_next_hop_entry *nh;
    2765           0 :         struct rfapi_next_hop_entry *next;
    2766             : 
    2767           0 :         for (nh = list; nh; nh = next) {
    2768           0 :                 next = nh->next;
    2769           0 :                 rfapi_un_options_free(nh->un_options);
    2770           0 :                 nh->un_options = NULL;
    2771           0 :                 rfapi_vn_options_free(nh->vn_options);
    2772           0 :                 nh->vn_options = NULL;
    2773           0 :                 XFREE(MTYPE_RFAPI_NEXTHOP, nh);
    2774             :         }
    2775           0 : }
    2776             : 
    2777             : /*
    2778             :  * NULL handle => return total count across all nves
    2779             :  */
    2780           0 : uint32_t rfapi_monitor_count(void *handle)
    2781             : {
    2782           0 :         struct bgp *bgp = bgp_get_default();
    2783           0 :         uint32_t count;
    2784             : 
    2785           0 :         if (handle) {
    2786           0 :                 struct rfapi_descriptor *rfd =
    2787             :                         (struct rfapi_descriptor *)handle;
    2788           0 :                 count = rfd->monitor_count;
    2789             :         } else {
    2790             : 
    2791           0 :                 if (!bgp || !bgp->rfapi)
    2792             :                         return 0;
    2793             : 
    2794           0 :                 count = bgp->rfapi->monitor_count;
    2795             :         }
    2796             : 
    2797             :         return count;
    2798             : }
    2799             : 
    2800             : /***********************************************************************
    2801             :  *                      CLI/CONFIG
    2802             :  ***********************************************************************/
    2803             : 
    2804           0 : DEFUN (debug_rfapi_show_nves,
    2805             :        debug_rfapi_show_nves_cmd,
    2806             :        "debug rfapi-dev show nves",
    2807             :        DEBUG_STR
    2808             :        DEBUG_RFAPI_STR
    2809             :        SHOW_STR
    2810             :        "NVE Information\n")
    2811             : {
    2812           0 :         rfapiPrintMatchingDescriptors(vty, NULL, NULL);
    2813           0 :         return CMD_SUCCESS;
    2814             : }
    2815             : 
    2816           0 : DEFUN (
    2817             :   debug_rfapi_show_nves_vn_un,
    2818             :   debug_rfapi_show_nves_vn_un_cmd,
    2819             :   "debug rfapi-dev show nves <vn|un> <A.B.C.D|X:X::X:X>", /* prefix also ok */
    2820             :   DEBUG_STR
    2821             :   DEBUG_RFAPI_STR
    2822             :   SHOW_STR
    2823             :   "NVE Information\n"
    2824             :   "Specify virtual network\n"
    2825             :   "Specify underlay network interface\n"
    2826             :   "IPv4 address\n"
    2827             :   "IPv6 address\n")
    2828             : {
    2829           0 :         struct prefix pfx;
    2830             : 
    2831           0 :         if (!str2prefix(argv[5]->arg, &pfx)) {
    2832           0 :                 vty_out(vty, "Malformed address \"%s\"\n", argv[5]->arg);
    2833           0 :                 return CMD_WARNING_CONFIG_FAILED;
    2834             :         }
    2835           0 :         if (pfx.family != AF_INET && pfx.family != AF_INET6) {
    2836           0 :                 vty_out(vty, "Invalid address \"%s\"\n", argv[5]->arg);
    2837           0 :                 return CMD_WARNING_CONFIG_FAILED;
    2838             :         }
    2839             : 
    2840           0 :         if (argv[4]->arg[0] == 'u') {
    2841           0 :                 rfapiPrintMatchingDescriptors(vty, NULL, &pfx);
    2842             :         } else {
    2843           0 :                 rfapiPrintMatchingDescriptors(vty, &pfx, NULL);
    2844             :         }
    2845             :         return CMD_SUCCESS;
    2846             : }
    2847             : 
    2848             : /*
    2849             :  * Note: this function does not flush vty output, so if it is called
    2850             :  * with a stream pointing to a vty, the user will have to type something
    2851             :  * before the callback output shows up
    2852             :  */
    2853           0 : static void test_nexthops_callback(
    2854             :         //    struct rfapi_ip_addr        *target,
    2855             :         struct rfapi_next_hop_entry *next_hops, void *userdata)
    2856             : {
    2857           0 :         void *stream = userdata;
    2858             : 
    2859           0 :         int (*fp)(void *, const char *, ...);
    2860           0 :         struct vty *vty;
    2861           0 :         void *out;
    2862           0 :         const char *vty_newline;
    2863             : 
    2864           0 :         if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
    2865           0 :                 return;
    2866             : 
    2867           0 :         fp(out, "Nexthops Callback, Target=(");
    2868             :         // rfapiPrintRfapiIpAddr(stream, target);
    2869           0 :         fp(out, ")\n");
    2870             : 
    2871           0 :         rfapiPrintNhl(stream, next_hops);
    2872             : 
    2873           0 :         fp(out, "\n");
    2874             : 
    2875           0 :         rfapi_free_next_hop_list(next_hops);
    2876             : }
    2877             : 
    2878           0 : DEFUN (debug_rfapi_open,
    2879             :        debug_rfapi_open_cmd,
    2880             :        "debug rfapi-dev open vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
    2881             :        DEBUG_STR
    2882             :        DEBUG_RFAPI_STR
    2883             :        "rfapi_open\n"
    2884             :        "indicate vn addr follows\n"
    2885             :        "virtual network interface IPv4 address\n"
    2886             :        "virtual network interface IPv6 address\n"
    2887             :        "indicate xt addr follows\n"
    2888             :        "underlay network interface IPv4 address\n"
    2889             :        "underlay network interface IPv6 address\n")
    2890             : {
    2891           0 :         struct rfapi_ip_addr vn;
    2892           0 :         struct rfapi_ip_addr un;
    2893           0 :         uint32_t lifetime = 0;
    2894           0 :         int rc;
    2895           0 :         rfapi_handle handle;
    2896             : 
    2897             :         /*
    2898             :          * Get VN addr
    2899             :          */
    2900           0 :         if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
    2901             :                 return rc;
    2902             : 
    2903             :         /*
    2904             :          * Get UN addr
    2905             :          */
    2906           0 :         if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
    2907             :                 return rc;
    2908             : 
    2909           0 :         rc = rfapi_open(rfapi_get_rfp_start_val_by_bgp(bgp_get_default()), &vn,
    2910             :                         &un, /*&uo */ NULL, &lifetime, NULL, &handle);
    2911             : 
    2912           0 :         vty_out(vty, "rfapi_open: status %d, handle %p, lifetime %d\n", rc,
    2913             :                 handle, lifetime);
    2914             : 
    2915           0 :         rc = rfapi_set_response_cb(handle, test_nexthops_callback);
    2916             : 
    2917           0 :         vty_out(vty, "rfapi_set_response_cb: status %d\n", rc);
    2918             : 
    2919           0 :         return CMD_SUCCESS;
    2920             : }
    2921             : 
    2922             : 
    2923           0 : DEFUN (debug_rfapi_close_vn_un,
    2924             :        debug_rfapi_close_vn_un_cmd,
    2925             :        "debug rfapi-dev close vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
    2926             :        DEBUG_STR
    2927             :        DEBUG_RFAPI_STR
    2928             :        "rfapi_close\n"
    2929             :        "indicate vn addr follows\n"
    2930             :        "virtual network interface IPv4 address\n"
    2931             :        "virtual network interface IPv6 address\n"
    2932             :        "indicate xt addr follows\n"
    2933             :        "underlay network interface IPv4 address\n"
    2934             :        "underlay network interface IPv6 address\n")
    2935             : {
    2936           0 :         struct rfapi_ip_addr vn;
    2937           0 :         struct rfapi_ip_addr un;
    2938           0 :         rfapi_handle handle;
    2939           0 :         int rc;
    2940             : 
    2941             :         /*
    2942             :          * Get VN addr
    2943             :          */
    2944           0 :         if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
    2945             :                 return rc;
    2946             : 
    2947             : 
    2948             :         /*
    2949             :          * Get UN addr
    2950             :          */
    2951           0 :         if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
    2952             :                 return rc;
    2953             : 
    2954             : 
    2955           0 :         if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
    2956           0 :                 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
    2957           0 :                         argv[4]->arg, argv[6]->arg);
    2958           0 :                 return CMD_WARNING_CONFIG_FAILED;
    2959             :         }
    2960             : 
    2961           0 :         rc = rfapi_close(handle);
    2962             : 
    2963           0 :         vty_out(vty, "rfapi_close(handle=%p): status %d\n", handle, rc);
    2964             : 
    2965           0 :         return CMD_SUCCESS;
    2966             : }
    2967             : 
    2968           0 : DEFUN (debug_rfapi_close_rfd,
    2969             :        debug_rfapi_close_rfd_cmd,
    2970             :        "debug rfapi-dev close rfd HANDLE",
    2971             :        DEBUG_STR
    2972             :        DEBUG_RFAPI_STR
    2973             :        "rfapi_close\n"
    2974             :        "indicate handle follows\n" "rfapi handle in hexadecimal\n")
    2975             : {
    2976           0 :         rfapi_handle handle;
    2977           0 :         int rc;
    2978           0 :         char *endptr = NULL;
    2979             : 
    2980           0 :         handle = (rfapi_handle)(uintptr_t)(strtoull(argv[4]->arg, &endptr, 16));
    2981             : 
    2982           0 :         if (*endptr != '\0' || (uintptr_t)handle == UINTPTR_MAX) {
    2983           0 :                 vty_out(vty, "Invalid value: %s\n", argv[4]->arg);
    2984           0 :                 return CMD_WARNING_CONFIG_FAILED;
    2985             :         }
    2986             : 
    2987           0 :         rc = rfapi_close(handle);
    2988             : 
    2989           0 :         vty_out(vty, "rfapi_close(handle=%p): status %d\n", handle, rc);
    2990             : 
    2991           0 :         return CMD_SUCCESS;
    2992             : }
    2993             : 
    2994           0 : DEFUN (debug_rfapi_register_vn_un,
    2995             :        debug_rfapi_register_vn_un_cmd,
    2996             :        "debug rfapi-dev register vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M> lifetime SECONDS [cost (0-255)]",
    2997             :        DEBUG_STR
    2998             :        DEBUG_RFAPI_STR
    2999             :        "rfapi_register\n"
    3000             :        "indicate vn addr follows\n"
    3001             :        "virtual network IPv4 interface address\n"
    3002             :        "virtual network IPv6 interface address\n"
    3003             :        "indicate un addr follows\n"
    3004             :        "underlay network IPv4 interface address\n"
    3005             :        "underlay network IPv6 interface address\n"
    3006             :        "indicate prefix follows\n"
    3007             :        "IPv4 prefix\n"
    3008             :        "IPv6 prefix\n"
    3009             :        "indicate lifetime follows\n"
    3010             :        "lifetime\n"
    3011             :        "Cost (localpref = 255-cost)\n"
    3012             :        "0-255\n")
    3013             : {
    3014           0 :         struct rfapi_ip_addr vn;
    3015           0 :         struct rfapi_ip_addr un;
    3016           0 :         rfapi_handle handle;
    3017           0 :         struct prefix pfx;
    3018           0 :         uint32_t lifetime;
    3019           0 :         struct rfapi_ip_prefix hpfx;
    3020           0 :         int rc;
    3021           0 :         uint8_t cost = 100;
    3022             : 
    3023             :         /*
    3024             :          * Get VN addr
    3025             :          */
    3026           0 :         if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
    3027             :                 return rc;
    3028             : 
    3029             : 
    3030             :         /*
    3031             :          * Get UN addr
    3032             :          */
    3033           0 :         if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
    3034             :                 return rc;
    3035             : 
    3036             : 
    3037           0 :         if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
    3038           0 :                 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
    3039           0 :                         argv[4]->arg, argv[6]->arg);
    3040           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3041             :         }
    3042             : 
    3043             :         /*
    3044             :          * Get prefix to advertise
    3045             :          */
    3046           0 :         if (!str2prefix(argv[8]->arg, &pfx)) {
    3047           0 :                 vty_out(vty, "Malformed prefix \"%s\"\n", argv[8]->arg);
    3048           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3049             :         }
    3050           0 :         if (pfx.family != AF_INET && pfx.family != AF_INET6) {
    3051           0 :                 vty_out(vty, "Bad family for prefix \"%s\"\n", argv[8]->arg);
    3052           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3053             :         }
    3054           0 :         rfapiQprefix2Rprefix(&pfx, &hpfx);
    3055             : 
    3056           0 :         if (strmatch(argv[10]->text, "infinite")) {
    3057             :                 lifetime = RFAPI_INFINITE_LIFETIME;
    3058             :         } else {
    3059           0 :                 lifetime = strtoul(argv[10]->arg, NULL, 10);
    3060             :         }
    3061             : 
    3062           0 :         if (argc >= 13)
    3063           0 :                 cost = (uint8_t) strtoul(argv[12]->arg, NULL, 10);
    3064           0 :         hpfx.cost = cost;
    3065             : 
    3066           0 :         rc = rfapi_register(handle, &hpfx, lifetime, NULL, NULL,
    3067             :                             RFAPI_REGISTER_ADD);
    3068           0 :         if (rc) {
    3069           0 :                 vty_out(vty, "rfapi_register failed with rc=%d (%s)\n", rc,
    3070             :                         strerror(rc));
    3071             :         }
    3072             : 
    3073             :         return CMD_SUCCESS;
    3074             : }
    3075             : 
    3076           0 : DEFUN (debug_rfapi_register_vn_un_l2o,
    3077             :        debug_rfapi_register_vn_un_l2o_cmd,
    3078             :        "debug rfapi-dev register vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M> lifetime SECONDS macaddr X:X:X:X:X:X lni (0-16777215)",
    3079             :        DEBUG_STR
    3080             :        DEBUG_RFAPI_STR
    3081             :        "rfapi_register\n"
    3082             :        "indicate vn addr follows\n"
    3083             :        "virtual network IPv4 interface address\n"
    3084             :        "virtual network IPv6 interface address\n"
    3085             :        "indicate un addr follows\n"
    3086             :        "underlay network IPv4 interface address\n"
    3087             :        "underlay network IPv6 interface address\n"
    3088             :        "indicate prefix follows\n"
    3089             :        "IPv4 prefix\n"
    3090             :        "IPv6 prefix\n"
    3091             :        "indicate lifetime follows\n"
    3092             :        "Seconds of lifetime\n"
    3093             :        "indicate MAC address follows\n"
    3094             :        "MAC address\n"
    3095             :        "indicate lni follows\n"
    3096             :        "lni value range\n")
    3097             : {
    3098           0 :         struct rfapi_ip_addr vn;
    3099           0 :         struct rfapi_ip_addr un;
    3100           0 :         rfapi_handle handle;
    3101           0 :         struct prefix pfx;
    3102           0 :         uint32_t lifetime;
    3103           0 :         struct rfapi_ip_prefix hpfx;
    3104           0 :         int rc;
    3105           0 :         struct rfapi_vn_option optary[10]; /* XXX must be big enough */
    3106           0 :         struct rfapi_vn_option *opt = NULL;
    3107           0 :         int opt_next = 0;
    3108             : 
    3109             :         /*
    3110             :          * Get VN addr
    3111             :          */
    3112           0 :         if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
    3113             :                 return rc;
    3114             : 
    3115             : 
    3116             :         /*
    3117             :          * Get UN addr
    3118             :          */
    3119           0 :         if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
    3120             :                 return rc;
    3121             : 
    3122             : 
    3123           0 :         if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
    3124           0 :                 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
    3125           0 :                         argv[4]->arg, argv[6]->arg);
    3126           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3127             :         }
    3128             : 
    3129             :         /*
    3130             :          * Get prefix to advertise
    3131             :          */
    3132           0 :         if (!str2prefix(argv[8]->arg, &pfx)) {
    3133           0 :                 vty_out(vty, "Malformed prefix \"%s\"\n", argv[8]->arg);
    3134           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3135             :         }
    3136           0 :         if (pfx.family != AF_INET && pfx.family != AF_INET6) {
    3137           0 :                 vty_out(vty, "Bad family for prefix \"%s\"\n", argv[8]->arg);
    3138           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3139             :         }
    3140           0 :         rfapiQprefix2Rprefix(&pfx, &hpfx);
    3141             : 
    3142           0 :         if (strmatch(argv[10]->text, "infinite")) {
    3143             :                 lifetime = RFAPI_INFINITE_LIFETIME;
    3144             :         } else {
    3145           0 :                 lifetime = strtoul(argv[10]->arg, NULL, 10);
    3146             :         }
    3147             : 
    3148             :         /* L2 option parsing START */
    3149           0 :         memset(optary, 0, sizeof(optary));
    3150           0 :         optary[opt_next].v.l2addr.logical_net_id =
    3151           0 :                 strtoul(argv[14]->arg, NULL, 10);
    3152           0 :         if (rfapiStr2EthAddr(argv[12]->arg,
    3153             :                              &optary[opt_next].v.l2addr.macaddr)) {
    3154           0 :                 vty_out(vty, "Bad mac address \"%s\"\n", argv[12]->arg);
    3155           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3156             :         }
    3157           0 :         optary[opt_next].type = RFAPI_VN_OPTION_TYPE_L2ADDR;
    3158           0 :         opt = optary;
    3159             : 
    3160             :         /* L2 option parsing END */
    3161             : 
    3162             :         /* TBD fixme */
    3163           0 :         rc = rfapi_register(handle, &hpfx, lifetime, NULL /* &uo */, opt,
    3164             :                             RFAPI_REGISTER_ADD);
    3165           0 :         if (rc) {
    3166           0 :                 vty_out(vty, "rfapi_register failed with rc=%d (%s)\n", rc,
    3167             :                         strerror(rc));
    3168             :         }
    3169             : 
    3170             :         return CMD_SUCCESS;
    3171             : }
    3172             : 
    3173             : 
    3174           0 : DEFUN (debug_rfapi_unregister_vn_un,
    3175             :        debug_rfapi_unregister_vn_un_cmd,
    3176             :        "debug rfapi-dev unregister vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> prefix <A.B.C.D/M|X:X::X:X/M> [kill]",
    3177             :        DEBUG_STR
    3178             :        DEBUG_RFAPI_STR
    3179             :        "rfapi_unregister\n"
    3180             :        "indicate vn addr follows\n"
    3181             :        "virtual network interface address\n"
    3182             :        "virtual network interface address\n"
    3183             :        "indicate xt addr follows\n"
    3184             :        "underlay network interface address\n"
    3185             :        "underlay network interface address\n"
    3186             :        "prefix to remove\n"
    3187             :        "prefix to remove\n"
    3188             :        "prefix to remove\n"
    3189             :        "Remove without holddown\n")
    3190             : {
    3191           0 :         struct rfapi_ip_addr vn;
    3192           0 :         struct rfapi_ip_addr un;
    3193           0 :         rfapi_handle handle;
    3194           0 :         struct prefix pfx;
    3195           0 :         struct rfapi_ip_prefix hpfx;
    3196           0 :         int rc;
    3197             : 
    3198             :         /*
    3199             :          * Get VN addr
    3200             :          */
    3201           0 :         if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
    3202             :                 return rc;
    3203             : 
    3204             :         /*
    3205             :          * Get UN addr
    3206             :          */
    3207           0 :         if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
    3208             :                 return rc;
    3209             : 
    3210             : 
    3211           0 :         if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
    3212           0 :                 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
    3213           0 :                         argv[4]->arg, argv[6]->arg);
    3214           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3215             :         }
    3216             : 
    3217             :         /*
    3218             :          * Get prefix to advertise
    3219             :          */
    3220           0 :         if (!str2prefix(argv[8]->arg, &pfx)) {
    3221           0 :                 vty_out(vty, "Malformed prefix \"%s\"\n", argv[8]->arg);
    3222           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3223             :         }
    3224           0 :         if (pfx.family != AF_INET && pfx.family != AF_INET6) {
    3225           0 :                 vty_out(vty, "Bad family for prefix \"%s\"\n", argv[8]->arg);
    3226           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3227             :         }
    3228           0 :         rfapiQprefix2Rprefix(&pfx, &hpfx);
    3229             : 
    3230           0 :         rfapi_register(handle, &hpfx, 0, NULL, NULL,
    3231             :                        (argc == 10 ?
    3232             :                         RFAPI_REGISTER_KILL : RFAPI_REGISTER_WITHDRAW));
    3233             : 
    3234           0 :         return CMD_SUCCESS;
    3235             : }
    3236             : 
    3237           0 : DEFUN (debug_rfapi_query_vn_un,
    3238             :        debug_rfapi_query_vn_un_cmd,
    3239             :        "debug rfapi-dev query vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> target <A.B.C.D|X:X::X:X>",
    3240             :        DEBUG_STR
    3241             :        DEBUG_RFAPI_STR
    3242             :        "rfapi_query\n"
    3243             :        "indicate vn addr follows\n"
    3244             :        "virtual network interface IPv4 address\n"
    3245             :        "virtual network interface IPv6 address\n"
    3246             :        "indicate un addr follows\n"
    3247             :        "IPv4 un address\n"
    3248             :        "IPv6 un address\n"
    3249             :        "indicate target follows\n"
    3250             :        "target IPv4 address\n"
    3251             :        "target IPv6 address\n")
    3252             : {
    3253           0 :         struct rfapi_ip_addr vn;
    3254           0 :         struct rfapi_ip_addr un;
    3255           0 :         struct rfapi_ip_addr target;
    3256           0 :         rfapi_handle handle;
    3257           0 :         int rc;
    3258           0 :         struct rfapi_next_hop_entry *pNextHopEntry;
    3259             : 
    3260             :         /*
    3261             :          * Get VN addr
    3262             :          */
    3263           0 :         if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
    3264             :                 return rc;
    3265             : 
    3266             : 
    3267             :         /*
    3268             :          * Get UN addr
    3269             :          */
    3270           0 :         if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
    3271             :                 return rc;
    3272             : 
    3273             : 
    3274             :         /*
    3275             :          * Get target addr
    3276             :          */
    3277           0 :         if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[8]->arg, &target)))
    3278             :                 return rc;
    3279             : 
    3280             : 
    3281           0 :         if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
    3282           0 :                 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
    3283           0 :                         argv[4]->arg, argv[6]->arg);
    3284           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3285             :         }
    3286             : 
    3287             :         /*
    3288             :          * options parameter not used? Set to NULL for now
    3289             :          */
    3290           0 :         rc = rfapi_query(handle, &target, NULL, &pNextHopEntry);
    3291             : 
    3292           0 :         if (rc) {
    3293           0 :                 vty_out(vty, "rfapi_query failed with rc=%d (%s)\n", rc,
    3294             :                         strerror(rc));
    3295             :         } else {
    3296             :                 /*
    3297             :                  * print nexthop list
    3298             :                  */
    3299           0 :                 test_nexthops_callback(/*&target, */ pNextHopEntry,
    3300             :                                        vty); /* frees nh list! */
    3301             :         }
    3302             : 
    3303             :         return CMD_SUCCESS;
    3304             : }
    3305             : 
    3306             : 
    3307           0 : DEFUN (debug_rfapi_query_vn_un_l2o,
    3308             :        debug_rfapi_query_vn_un_l2o_cmd,
    3309             :        "debug rfapi-dev query vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> lni LNI target X:X:X:X:X:X",
    3310             :        DEBUG_STR
    3311             :        DEBUG_RFAPI_STR
    3312             :        "rfapi_query\n"
    3313             :        "indicate vn addr follows\n"
    3314             :        "virtual network interface IPv4 address\n"
    3315             :        "virtual network interface IPv6 address\n"
    3316             :        "indicate xt addr follows\n"
    3317             :        "underlay network interface IPv4 address\n"
    3318             :        "underlay network interface IPv6 address\n"
    3319             :        "logical network ID follows\n"
    3320             :        "logical network ID\n"
    3321             :        "indicate target MAC addr follows\n"
    3322             :        "target MAC addr\n")
    3323             : {
    3324           0 :         struct rfapi_ip_addr vn;
    3325           0 :         struct rfapi_ip_addr un;
    3326           0 :         int rc;
    3327             : 
    3328             :         /*
    3329             :          * Get VN addr
    3330             :          */
    3331           0 :         if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[4]->arg, &vn)))
    3332             :                 return rc;
    3333             : 
    3334             : 
    3335             :         /*
    3336             :          * Get UN addr
    3337             :          */
    3338           0 :         if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[6]->arg, &un)))
    3339             :                 return rc;
    3340             : 
    3341           0 :         vty_out(vty, "%% This command is broken.\n");
    3342           0 :         return CMD_WARNING_CONFIG_FAILED;
    3343             : }
    3344             : 
    3345             : 
    3346           0 : DEFUN (debug_rfapi_query_done_vn_un,
    3347             :        debug_rfapi_query_vn_un_done_cmd,
    3348             :        "debug rfapi-dev query done vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X> target <A.B.C.D|X:X::X:X>",
    3349             :        DEBUG_STR
    3350             :        DEBUG_RFAPI_STR
    3351             :        "rfapi_query_done\n"
    3352             :        "rfapi_query_done\n"
    3353             :        "indicate vn addr follows\n"
    3354             :        "virtual network interface IPv4 address\n"
    3355             :        "virtual network interface IPv6 address\n"
    3356             :        "indicate xt addr follows\n"
    3357             :        "underlay network interface IPv4 address\n"
    3358             :        "underlay network interface IPv6 address\n"
    3359             :        "indicate target follows\n"
    3360             :        "Target IPv4 address\n"
    3361             :        "Target IPv6 address\n")
    3362             : {
    3363           0 :         struct rfapi_ip_addr vn;
    3364           0 :         struct rfapi_ip_addr un;
    3365           0 :         struct rfapi_ip_addr target;
    3366           0 :         rfapi_handle handle;
    3367           0 :         int rc;
    3368             : 
    3369             :         /*
    3370             :          * Get VN addr
    3371             :          */
    3372           0 :         if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[5]->arg, &vn)))
    3373             :                 return rc;
    3374             : 
    3375             : 
    3376             :         /*
    3377             :          * Get UN addr
    3378             :          */
    3379           0 :         if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[7]->arg, &un)))
    3380             :                 return rc;
    3381             : 
    3382             : 
    3383             :         /*
    3384             :          * Get target addr
    3385             :          */
    3386           0 :         if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[9]->arg, &target)))
    3387             :                 return rc;
    3388             : 
    3389             : 
    3390           0 :         if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
    3391           0 :                 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
    3392           0 :                         argv[5]->arg, argv[7]->arg);
    3393           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3394             :         }
    3395             : 
    3396             :         /*
    3397             :          * options parameter not used? Set to NULL for now
    3398             :          */
    3399           0 :         rc = rfapi_query_done(handle, &target);
    3400             : 
    3401           0 :         vty_out(vty, "rfapi_query_done returned %d\n", rc);
    3402             : 
    3403           0 :         return CMD_SUCCESS;
    3404             : }
    3405             : 
    3406           0 : DEFUN (debug_rfapi_show_import,
    3407             :        debug_rfapi_show_import_cmd,
    3408             :        "debug rfapi-dev show import",
    3409             :        DEBUG_STR
    3410             :        DEBUG_RFAPI_STR
    3411             :        SHOW_STR
    3412             :        "import\n")
    3413             : {
    3414           0 :         struct bgp *bgp;
    3415           0 :         struct rfapi *h;
    3416           0 :         struct rfapi_import_table *it;
    3417           0 :         char *s;
    3418           0 :         int first_l2 = 1;
    3419             : 
    3420             :         /*
    3421             :          * Show all import tables
    3422             :          */
    3423             : 
    3424           0 :         bgp = bgp_get_default(); /* assume 1 instance for now */
    3425           0 :         if (!bgp) {
    3426           0 :                 vty_out(vty, "No BGP instance\n");
    3427           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3428             :         }
    3429             : 
    3430           0 :         h = bgp->rfapi;
    3431           0 :         if (!h) {
    3432           0 :                 vty_out(vty, "No RFAPI instance\n");
    3433           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3434             :         }
    3435             : 
    3436             :         /*
    3437             :          * Iterate over all import tables; do a filtered import
    3438             :          * for the afi/safi combination
    3439             :          */
    3440             : 
    3441             : 
    3442           0 :         for (it = h->imports; it; it = it->next) {
    3443           0 :                 s = ecommunity_ecom2str(it->rt_import_list,
    3444             :                                         ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
    3445           0 :                 vty_out(vty, "Import Table %p, RTs: %s\n", it, s);
    3446           0 :                 XFREE(MTYPE_ECOMMUNITY_STR, s);
    3447             : 
    3448           0 :                 rfapiShowImportTable(vty, "IP VPN", it->imported_vpn[AFI_IP],
    3449             :                                      1);
    3450           0 :                 rfapiShowImportTable(vty, "IP ENCAP",
    3451           0 :                                      it->imported_encap[AFI_IP], 0);
    3452           0 :                 rfapiShowImportTable(vty, "IP6 VPN", it->imported_vpn[AFI_IP6],
    3453             :                                      1);
    3454           0 :                 rfapiShowImportTable(vty, "IP6 ENCAP",
    3455           0 :                                      it->imported_encap[AFI_IP6], 0);
    3456             :         }
    3457             : 
    3458           0 :         if (h->import_mac) {
    3459           0 :                 void *cursor = NULL;
    3460           0 :                 uint32_t lni;
    3461           0 :                 uintptr_t lni_as_ptr;
    3462           0 :                 int rc;
    3463           0 :                 char buf[BUFSIZ];
    3464             : 
    3465           0 :                 for (rc = skiplist_next(h->import_mac, (void **)&lni_as_ptr,
    3466             :                                         (void **)&it, &cursor);
    3467           0 :                      !rc;
    3468           0 :                      rc = skiplist_next(h->import_mac, (void **)&lni_as_ptr,
    3469             :                                         (void **)&it, &cursor)) {
    3470             : 
    3471           0 :                         if (it->imported_vpn[AFI_L2VPN]) {
    3472           0 :                                 lni = lni_as_ptr;
    3473           0 :                                 if (first_l2) {
    3474           0 :                                         vty_out(vty,
    3475             :                                                 "\nLNI-based Ethernet Tables:\n");
    3476           0 :                                         first_l2 = 0;
    3477             :                                 }
    3478           0 :                                 snprintf(buf, sizeof(buf), "L2VPN LNI=%u", lni);
    3479           0 :                                 rfapiShowImportTable(
    3480           0 :                                         vty, buf, it->imported_vpn[AFI_L2VPN],
    3481             :                                         1);
    3482             :                         }
    3483             :                 }
    3484             :         }
    3485             : 
    3486           0 :         rfapiShowImportTable(vty, "CE IT - IP VPN",
    3487           0 :                              h->it_ce->imported_vpn[AFI_IP], 1);
    3488             : 
    3489           0 :         return CMD_SUCCESS;
    3490             : }
    3491             : 
    3492           0 : DEFUN (debug_rfapi_show_import_vn_un,
    3493             :        debug_rfapi_show_import_vn_un_cmd,
    3494             :        "debug rfapi-dev show import vn <A.B.C.D|X:X::X:X> un <A.B.C.D|X:X::X:X>",
    3495             :        DEBUG_STR
    3496             :        DEBUG_RFAPI_STR
    3497             :        SHOW_STR
    3498             :        "import\n"
    3499             :        "indicate vn addr follows\n"
    3500             :        "virtual network interface IPv4 address\n"
    3501             :        "virtual network interface IPv6 address\n"
    3502             :        "indicate xt addr follows\n"
    3503             :        "underlay network interface IPv4 address\n"
    3504             :        "underlay network interface IPv6 address\n")
    3505             : {
    3506           0 :         struct rfapi_ip_addr vn;
    3507           0 :         struct rfapi_ip_addr un;
    3508           0 :         rfapi_handle handle;
    3509           0 :         int rc;
    3510           0 :         struct rfapi_descriptor *rfd;
    3511             : 
    3512             :         /*
    3513             :          * Get VN addr
    3514             :          */
    3515           0 :         if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[5]->arg, &vn)))
    3516             :                 return rc;
    3517             : 
    3518             : 
    3519             :         /*
    3520             :          * Get UN addr
    3521             :          */
    3522           0 :         if ((rc = rfapiCliGetRfapiIpAddr(vty, argv[7]->arg, &un)))
    3523             :                 return rc;
    3524             : 
    3525             : 
    3526           0 :         if (rfapi_find_handle_vty(vty, &vn, &un, &handle)) {
    3527           0 :                 vty_out(vty, "can't locate handle matching vn=%s, un=%s\n",
    3528           0 :                         argv[5]->arg, argv[7]->arg);
    3529           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3530             :         }
    3531             : 
    3532           0 :         rfd = (struct rfapi_descriptor *)handle;
    3533             : 
    3534           0 :         rfapiShowImportTable(vty, "IP VPN",
    3535           0 :                              rfd->import_table->imported_vpn[AFI_IP], 1);
    3536           0 :         rfapiShowImportTable(vty, "IP ENCAP",
    3537           0 :                              rfd->import_table->imported_encap[AFI_IP], 0);
    3538           0 :         rfapiShowImportTable(vty, "IP6 VPN",
    3539           0 :                              rfd->import_table->imported_vpn[AFI_IP6], 1);
    3540           0 :         rfapiShowImportTable(vty, "IP6 ENCAP",
    3541           0 :                              rfd->import_table->imported_encap[AFI_IP6], 0);
    3542             : 
    3543           0 :         return CMD_SUCCESS;
    3544             : }
    3545             : 
    3546           0 : DEFUN (debug_rfapi_response_omit_self,
    3547             :        debug_rfapi_response_omit_self_cmd,
    3548             :        "debug rfapi-dev response-omit-self <on|off>",
    3549             :        DEBUG_STR
    3550             :        DEBUG_RFAPI_STR
    3551             :        "Omit self in RFP responses\n"
    3552             :        "filter out self from responses\n" "leave self in responses\n")
    3553             : {
    3554           0 :         struct bgp *bgp = bgp_get_default();
    3555             : 
    3556           0 :         if (!bgp) {
    3557           0 :                 vty_out(vty, "No BGP process is configured\n");
    3558           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3559             :         }
    3560           0 :         if (!bgp->rfapi_cfg) {
    3561           0 :                 vty_out(vty, "VNC not configured\n");
    3562           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3563             :         }
    3564             : 
    3565           0 :         if (strmatch(argv[3]->text, "on"))
    3566           0 :                 SET_FLAG(bgp->rfapi_cfg->flags,
    3567             :                          BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP);
    3568             :         else
    3569           0 :                 UNSET_FLAG(bgp->rfapi_cfg->flags,
    3570             :                            BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP);
    3571             : 
    3572             :         return CMD_SUCCESS;
    3573             : }
    3574             : 
    3575             : 
    3576             : #ifdef RFAPI_DEBUG_SKIPLIST_CLI
    3577             : 
    3578             : #include "lib/skiplist.h"
    3579             : DEFUN (skiplist_test_cli,
    3580             :        skiplist_test_cli_cmd,
    3581             :        "skiplist test",
    3582             :        "skiplist command\n"
    3583             :        "test\n")
    3584             : {
    3585             :         skiplist_test(vty);
    3586             : 
    3587             :         return CMD_SUCCESS;
    3588             : }
    3589             : 
    3590             : DEFUN (skiplist_debug_cli,
    3591             :        skiplist_debug_cli_cmd,
    3592             :        "skiplist debug",
    3593             :        "skiplist command\n"
    3594             :        "debug\n")
    3595             : {
    3596             :         skiplist_debug(vty, NULL);
    3597             :         return CMD_SUCCESS;
    3598             : }
    3599             : 
    3600             : #endif /* RFAPI_DEBUG_SKIPLIST_CLI */
    3601             : 
    3602          48 : void rfapi_init(void)
    3603             : {
    3604          48 :         bgp_rfapi_cfg_init();
    3605          48 :         vnc_debug_init();
    3606             : 
    3607          48 :         install_element(ENABLE_NODE, &debug_rfapi_show_import_cmd);
    3608          48 :         install_element(ENABLE_NODE, &debug_rfapi_show_import_vn_un_cmd);
    3609             : 
    3610          48 :         install_element(ENABLE_NODE, &debug_rfapi_open_cmd);
    3611          48 :         install_element(ENABLE_NODE, &debug_rfapi_close_vn_un_cmd);
    3612          48 :         install_element(ENABLE_NODE, &debug_rfapi_close_rfd_cmd);
    3613          48 :         install_element(ENABLE_NODE, &debug_rfapi_register_vn_un_cmd);
    3614          48 :         install_element(ENABLE_NODE, &debug_rfapi_unregister_vn_un_cmd);
    3615          48 :         install_element(ENABLE_NODE, &debug_rfapi_query_vn_un_cmd);
    3616          48 :         install_element(ENABLE_NODE, &debug_rfapi_query_vn_un_done_cmd);
    3617          48 :         install_element(ENABLE_NODE, &debug_rfapi_query_vn_un_l2o_cmd);
    3618             : 
    3619          48 :         install_element(ENABLE_NODE, &debug_rfapi_response_omit_self_cmd);
    3620             : 
    3621             :         /* Need the following show commands for gpz test scripts */
    3622          48 :         install_element(ENABLE_NODE, &debug_rfapi_show_nves_cmd);
    3623          48 :         install_element(ENABLE_NODE, &debug_rfapi_show_nves_vn_un_cmd);
    3624          48 :         install_element(ENABLE_NODE, &debug_rfapi_register_vn_un_l2o_cmd);
    3625             : 
    3626             : #ifdef RFAPI_DEBUG_SKIPLIST_CLI
    3627             :         install_element(ENABLE_NODE, &skiplist_test_cli_cmd);
    3628             :         install_element(ENABLE_NODE, &skiplist_debug_cli_cmd);
    3629             : #endif
    3630             : 
    3631          48 :         rfapi_vty_init();
    3632          48 : }
    3633             : 
    3634             : #ifdef DEBUG_RFAPI
    3635             : static void rfapi_print_exported(struct bgp *bgp)
    3636             : {
    3637             :         struct bgp_dest *destn;
    3638             :         struct bgp_dest *dest;
    3639             :         struct bgp_path_info *bpi;
    3640             : 
    3641             :         if (!bgp)
    3642             :                 return;
    3643             : 
    3644             :         for (destn = bgp_table_top(bgp->rib[AFI_IP][SAFI_MPLS_VPN]); destn;
    3645             :              destn = bgp_route_next(destn)) {
    3646             :                 struct bgp_table *table;
    3647             : 
    3648             :                 table = bgp_dest_get_bgp_table_info(destn);
    3649             :                 if (!table)
    3650             :                         continue;
    3651             :                 fprintf(stderr, "%s: vpn destn=%p\n", __func__, destn);
    3652             :                 for (dest = bgp_table_top(table); dest;
    3653             :                      dest = bgp_route_next(dest)) {
    3654             :                         bpi = bgp_dest_get_bgp_path_info(dest);
    3655             : 
    3656             :                         if (!bpi)
    3657             :                                 continue;
    3658             :                         fprintf(stderr, "%s: dest=%p\n", __func__, dest);
    3659             :                         for (; bpi; bpi = bpi->next) {
    3660             :                                 rfapiPrintBi((void *)2, bpi); /* 2 => stderr */
    3661             :                         }
    3662             :                 }
    3663             :         }
    3664             :         for (destn = bgp_table_top(bgp->rib[AFI_IP][SAFI_ENCAP]); destn;
    3665             :              destn = bgp_route_next(destn)) {
    3666             :                 struct bgp_table *table;
    3667             : 
    3668             :                 table = bgp_dest_get_bgp_table_info(destn);
    3669             :                 if (!table)
    3670             :                         continue;
    3671             :                 fprintf(stderr, "%s: encap destn=%p\n", __func__, destn);
    3672             :                 for (dest = bgp_table_top(table); dest;
    3673             :                      dest = bgp_route_next(dest)) {
    3674             :                         bpi = bgp_dest_get_bgp_path_info(dest);
    3675             :                         if (!bpi)
    3676             :                                 continue;
    3677             :                         fprintf(stderr, "%s: dest=%p\n", __func__, dest);
    3678             :                         for (; bpi; bpi = bpi->next) {
    3679             :                                 rfapiPrintBi((void *)2, bpi); /* 2 => stderr */
    3680             :                         }
    3681             :                 }
    3682             :         }
    3683             : }
    3684             : #endif /* defined(DEBUG_RFAPI) */
    3685             : 
    3686             : /*
    3687             :  * Free all memory to prepare for clean exit as seen by valgrind memcheck
    3688             :  */
    3689          45 : void rfapi_delete(struct bgp *bgp)
    3690             : {
    3691          45 :         extern void rfp_clear_vnc_nve_all(void); /* can't fix correctly yet */
    3692             : 
    3693             :         /*
    3694             :          * This clears queries and registered routes, and closes nves
    3695             :          */
    3696          45 :         if (bgp->rfapi)
    3697          45 :                 rfp_clear_vnc_nve_all();
    3698          45 :         bgp_rfapi_cfg_destroy(bgp, bgp->rfapi_cfg);
    3699          45 :         bgp->rfapi_cfg = NULL;
    3700          45 :         bgp_rfapi_destroy(bgp, bgp->rfapi);
    3701          45 :         bgp->rfapi = NULL;
    3702             : #ifdef DEBUG_RFAPI
    3703             :         /*
    3704             :          * show what's left in the BGP MPLSVPN RIB
    3705             :          */
    3706             :         rfapi_print_exported(bgp);
    3707             : #endif
    3708          45 : }
    3709             : 
    3710           0 : int rfapi_set_autord_from_vn(struct prefix_rd *rd, struct rfapi_ip_addr *vn)
    3711             : {
    3712           0 :         vnc_zlog_debug_verbose("%s: auto-assigning RD", __func__);
    3713           0 :         if (vn->addr_family != AF_INET && vn->addr_family != AF_INET6) {
    3714           0 :                 vnc_zlog_debug_verbose(
    3715             :                         "%s: can't auto-assign RD, VN addr family is not IPv4|v6",
    3716             :                         __func__);
    3717           0 :                 return EAFNOSUPPORT;
    3718             :         }
    3719           0 :         rd->family = AF_UNSPEC;
    3720           0 :         rd->prefixlen = 64;
    3721           0 :         rd->val[1] = RD_TYPE_IP;
    3722           0 :         if (vn->addr_family == AF_INET) {
    3723           0 :                 memcpy(rd->val + 2, &vn->addr.v4.s_addr, 4);
    3724             :         } else { /* is v6 */
    3725           0 :                 memcpy(rd->val + 2, &vn->addr.v6.s6_addr32[3],
    3726             :                        4); /* low order 4 bytes */
    3727             :         }
    3728           0 :         vnc_zlog_debug_verbose("%s: auto-RD is set to %pRD", __func__, rd);
    3729             :         return 0;
    3730             : }
    3731             : 
    3732             : /*------------------------------------------
    3733             :  * rfapi_bgp_lookup_by_rfp
    3734             :  *
    3735             :  * Find bgp instance pointer based on value returned by rfp_start
    3736             :  *
    3737             :  * input:
    3738             :  *      rfp_start_val     value returned by rfp_startor
    3739             :  *                        NULL (=get default instance)
    3740             :  *
    3741             :  * output:
    3742             :  *      none
    3743             :  *
    3744             :  * return value:
    3745             :  *      bgp             bgp instance pointer
    3746             :  *      NULL = not found
    3747             :  *
    3748             :  --------------------------------------------*/
    3749           0 : struct bgp *rfapi_bgp_lookup_by_rfp(void *rfp_start_val)
    3750             : {
    3751           0 :         struct bgp *bgp = NULL;
    3752           0 :         struct listnode *node, *nnode;
    3753             : 
    3754           0 :         if (rfp_start_val == NULL)
    3755           0 :                 bgp = bgp_get_default();
    3756             :         else
    3757           0 :                 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
    3758           0 :                         if (bgp->rfapi != NULL
    3759           0 :                             && bgp->rfapi->rfp == rfp_start_val)
    3760           0 :                                 return bgp;
    3761             :         return bgp;
    3762             : }
    3763             : 
    3764             : /*------------------------------------------
    3765             :  * rfapi_get_rfp_start_val_by_bgp
    3766             :  *
    3767             :  * Find bgp instance pointer based on value returned by rfp_start
    3768             :  *
    3769             :  * input:
    3770             :  *      bgp             bgp instance pointer
    3771             :  *
    3772             :  * output:
    3773             :  *      none
    3774             :  *
    3775             :  * return value:
    3776             :  *      rfp_start_val
    3777             :  *      NULL = not found
    3778             :  *
    3779             :  --------------------------------------------*/
    3780           0 : void *rfapi_get_rfp_start_val_by_bgp(struct bgp *bgp)
    3781             : {
    3782           0 :         if (!bgp || !bgp->rfapi)
    3783             :                 return NULL;
    3784           0 :         return bgp->rfapi->rfp;
    3785             : }
    3786             : 
    3787             : /***********************************************************************
    3788             :  *               RFP group specific configuration
    3789             :  ***********************************************************************/
    3790           0 : static void *rfapi_rfp_get_or_init_group_config_default(struct rfapi_cfg *rfc,
    3791             :                                                         struct vty *vty,
    3792             :                                                         uint32_t size)
    3793             : {
    3794           0 :         if (rfc->default_rfp_cfg == NULL && size > 0) {
    3795           0 :                 rfc->default_rfp_cfg = XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG, size);
    3796           0 :                 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__,
    3797             :                                        size);
    3798             :         }
    3799           0 :         return rfc->default_rfp_cfg;
    3800             : }
    3801             : 
    3802           0 : static void *rfapi_rfp_get_or_init_group_config_nve(struct rfapi_cfg *rfc,
    3803             :                                                     struct vty *vty,
    3804             :                                                     uint32_t size)
    3805             : {
    3806           0 :         struct rfapi_nve_group_cfg *rfg =
    3807           0 :                 VTY_GET_CONTEXT_SUB(rfapi_nve_group_cfg);
    3808             : 
    3809             :         /* make sure group is still in list */
    3810           0 :         if (!rfg || !listnode_lookup(rfc->nve_groups_sequential, rfg)) {
    3811             :                 /* Not in list anymore */
    3812           0 :                 vty_out(vty, "Current NVE group no longer exists\n");
    3813           0 :                 return NULL;
    3814             :         }
    3815             : 
    3816           0 :         if (rfg->rfp_cfg == NULL && size > 0) {
    3817           0 :                 rfg->rfp_cfg = XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG, size);
    3818           0 :                 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__,
    3819             :                                        size);
    3820             :         }
    3821           0 :         return rfg->rfp_cfg;
    3822             : }
    3823             : 
    3824           0 : static void *rfapi_rfp_get_or_init_group_config_l2(struct rfapi_cfg *rfc,
    3825             :                                                    struct vty *vty,
    3826             :                                                    uint32_t size)
    3827             : {
    3828           0 :         struct rfapi_l2_group_cfg *rfg =
    3829           0 :                 VTY_GET_CONTEXT_SUB(rfapi_l2_group_cfg);
    3830             : 
    3831             :         /* make sure group is still in list */
    3832           0 :         if (!rfg || !listnode_lookup(rfc->l2_groups, rfg)) {
    3833             :                 /* Not in list anymore */
    3834           0 :                 vty_out(vty, "Current L2 group no longer exists\n");
    3835           0 :                 return NULL;
    3836             :         }
    3837           0 :         if (rfg->rfp_cfg == NULL && size > 0) {
    3838           0 :                 rfg->rfp_cfg = XCALLOC(MTYPE_RFAPI_RFP_GROUP_CFG, size);
    3839           0 :                 vnc_zlog_debug_verbose("%s: allocated, size=%d", __func__,
    3840             :                                        size);
    3841             :         }
    3842           0 :         return rfg->rfp_cfg;
    3843             : }
    3844             : 
    3845             : /*------------------------------------------
    3846             :  * rfapi_rfp_init_group_config_ptr_vty
    3847             :  *
    3848             :  * This is used to init or return a previously init'ed group specific
    3849             :  * configuration pointer. Group is identified by vty context.
    3850             :  * NOTE: size is ignored when a previously init'ed value is returned.
    3851             :  * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
    3852             :  * bgp restart or shutdown.
    3853             :  *
    3854             :  * input:
    3855             :  *    rfp_start_val     value returned by rfp_start
    3856             :  *    type              group type
    3857             :  *    vty               quagga vty context
    3858             :  *    size              number of bytes to allocation
    3859             :  *
    3860             :  * output:
    3861             :  *    none
    3862             :  *
    3863             :  * return value:
    3864             :  *    rfp_cfg_group     NULL or Pointer to configuration structure
    3865             : --------------------------------------------*/
    3866           0 : void *rfapi_rfp_init_group_config_ptr_vty(void *rfp_start_val,
    3867             :                                           rfapi_rfp_cfg_group_type type,
    3868             :                                           struct vty *vty, uint32_t size)
    3869             : {
    3870           0 :         struct bgp *bgp;
    3871           0 :         void *ret = NULL;
    3872             : 
    3873           0 :         if (rfp_start_val == NULL || vty == NULL)
    3874             :                 return NULL;
    3875             : 
    3876           0 :         bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
    3877           0 :         if (!bgp || !bgp->rfapi_cfg)
    3878             :                 return NULL;
    3879             : 
    3880           0 :         switch (type) {
    3881           0 :         case RFAPI_RFP_CFG_GROUP_DEFAULT:
    3882           0 :                 ret = rfapi_rfp_get_or_init_group_config_default(bgp->rfapi_cfg,
    3883             :                                                                  vty, size);
    3884           0 :                 break;
    3885           0 :         case RFAPI_RFP_CFG_GROUP_NVE:
    3886           0 :                 ret = rfapi_rfp_get_or_init_group_config_nve(bgp->rfapi_cfg,
    3887             :                                                              vty, size);
    3888           0 :                 break;
    3889           0 :         case RFAPI_RFP_CFG_GROUP_L2:
    3890           0 :                 ret = rfapi_rfp_get_or_init_group_config_l2(bgp->rfapi_cfg, vty,
    3891             :                                                             size);
    3892           0 :                 break;
    3893           0 :         default:
    3894           0 :                 flog_err(EC_LIB_DEVELOPMENT, "%s: Unknown group type=%d",
    3895             :                          __func__, type);
    3896             :                 /* should never happen */
    3897           0 :                 assert("Unknown type" == NULL);
    3898             :                 break;
    3899             :         }
    3900             :         return ret;
    3901             : }
    3902             : 
    3903             : /*------------------------------------------
    3904             :  * rfapi_rfp_get_group_config_ptr_vty
    3905             :  *
    3906             :  * This is used to get group specific configuration pointer.
    3907             :  * Group is identified by type and vty context.
    3908             :  * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
    3909             :  * bgp restart or shutdown.
    3910             :  *
    3911             :  * input:
    3912             :  *    rfp_start_val     value returned by rfp_start
    3913             :  *    type              group type
    3914             :  *    vty               quagga vty context
    3915             :  *
    3916             :  * output:
    3917             :  *    none
    3918             :  *
    3919             :  * return value:
    3920             :  *    rfp_cfg_group     Pointer to configuration structure
    3921             : --------------------------------------------*/
    3922           0 : void *rfapi_rfp_get_group_config_ptr_vty(void *rfp_start_val,
    3923             :                                          rfapi_rfp_cfg_group_type type,
    3924             :                                          struct vty *vty)
    3925             : {
    3926           0 :         return rfapi_rfp_init_group_config_ptr_vty(rfp_start_val, type, vty, 0);
    3927             : }
    3928             : 
    3929             : static void *
    3930           0 : rfapi_rfp_get_group_config_name_nve(struct rfapi_cfg *rfc, const char *name,
    3931             :                                     void *criteria,
    3932             :                                     rfp_group_config_search_cb_t *search_cb)
    3933             : {
    3934           0 :         struct rfapi_nve_group_cfg *rfg;
    3935           0 :         struct listnode *node;
    3936             : 
    3937           0 :         for (ALL_LIST_ELEMENTS_RO(rfc->nve_groups_sequential, node, rfg)) {
    3938           0 :                 if (!strcmp(rfg->name, name) && /* name match */
    3939           0 :                     (search_cb == NULL || !search_cb(criteria, rfg->rfp_cfg)))
    3940           0 :                         return rfg->rfp_cfg;
    3941             :         }
    3942             :         return NULL;
    3943             : }
    3944             : 
    3945             : static void *
    3946           0 : rfapi_rfp_get_group_config_name_l2(struct rfapi_cfg *rfc, const char *name,
    3947             :                                    void *criteria,
    3948             :                                    rfp_group_config_search_cb_t *search_cb)
    3949             : {
    3950           0 :         struct rfapi_l2_group_cfg *rfg;
    3951           0 :         struct listnode *node;
    3952             : 
    3953           0 :         for (ALL_LIST_ELEMENTS_RO(rfc->l2_groups, node, rfg)) {
    3954           0 :                 if (!strcmp(rfg->name, name) && /* name match */
    3955           0 :                     (search_cb == NULL || !search_cb(criteria, rfg->rfp_cfg)))
    3956           0 :                         return rfg->rfp_cfg;
    3957             :         }
    3958             :         return NULL;
    3959             : }
    3960             : 
    3961             : /*------------------------------------------
    3962             :  * rfapi_rfp_get_group_config_ptr_name
    3963             :  *
    3964             :  * This is used to get group specific configuration pointer.
    3965             :  * Group is identified by type and name context.
    3966             :  * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
    3967             :  * bgp restart or shutdown.
    3968             :  *
    3969             :  * input:
    3970             :  *    rfp_start_val     value returned by rfp_start
    3971             :  *    type              group type
    3972             :  *    name              group name
    3973             :  *    criteria          RFAPI caller provided search criteria
    3974             :  *    search_cb         optional rfp_group_config_search_cb_t
    3975             :  *
    3976             :  * output:
    3977             :  *    none
    3978             :  *
    3979             :  * return value:
    3980             :  *    rfp_cfg_group     Pointer to configuration structure
    3981             : --------------------------------------------*/
    3982           0 : void *rfapi_rfp_get_group_config_ptr_name(
    3983             :         void *rfp_start_val, rfapi_rfp_cfg_group_type type, const char *name,
    3984             :         void *criteria, rfp_group_config_search_cb_t *search_cb)
    3985             : {
    3986           0 :         struct bgp *bgp;
    3987           0 :         void *ret = NULL;
    3988             : 
    3989           0 :         if (rfp_start_val == NULL || name == NULL)
    3990             :                 return NULL;
    3991             : 
    3992           0 :         bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
    3993           0 :         if (!bgp || !bgp->rfapi_cfg)
    3994             :                 return NULL;
    3995             : 
    3996           0 :         switch (type) {
    3997           0 :         case RFAPI_RFP_CFG_GROUP_DEFAULT:
    3998           0 :                 ret = bgp->rfapi_cfg->default_rfp_cfg;
    3999           0 :                 break;
    4000           0 :         case RFAPI_RFP_CFG_GROUP_NVE:
    4001           0 :                 ret = rfapi_rfp_get_group_config_name_nve(bgp->rfapi_cfg, name,
    4002             :                                                           criteria, search_cb);
    4003           0 :                 break;
    4004           0 :         case RFAPI_RFP_CFG_GROUP_L2:
    4005           0 :                 ret = rfapi_rfp_get_group_config_name_l2(bgp->rfapi_cfg, name,
    4006             :                                                          criteria, search_cb);
    4007           0 :                 break;
    4008           0 :         default:
    4009           0 :                 flog_err(EC_LIB_DEVELOPMENT, "%s: Unknown group type=%d",
    4010             :                          __func__, type);
    4011             :                 /* should never happen */
    4012           0 :                 assert("Unknown type" == NULL);
    4013             :                 break;
    4014             :         }
    4015             :         return ret;
    4016             : }
    4017             : 
    4018             : /*------------------------------------------
    4019             :  * rfapi_rfp_get_l2_group_config_ptr_lni
    4020             :  *
    4021             :  * This is used to get group specific configuration pointer.
    4022             :  * Group is identified by type and logical network identifier.
    4023             :  * RFAPI frees rfp_cfg_group when group is deleted during reconfig,
    4024             :  * bgp restart or shutdown.
    4025             :  *
    4026             :  * input:
    4027             :  *    rfp_start_val     value returned by rfp_start
    4028             :  *    type              group type
    4029             :  *    logical_net_id    group logical network identifier
    4030             :  *    criteria          RFAPI caller provided search criteria
    4031             :  *    search_cb         optional rfp_group_config_search_cb_t
    4032             :  *
    4033             :  * output:
    4034             :  *    none
    4035             :  *
    4036             :  * return value:
    4037             :  *    rfp_cfg_group     Pointer to configuration structure
    4038             : --------------------------------------------*/
    4039             : void *
    4040           0 : rfapi_rfp_get_l2_group_config_ptr_lni(void *rfp_start_val,
    4041             :                                       uint32_t logical_net_id, void *criteria,
    4042             :                                       rfp_group_config_search_cb_t *search_cb)
    4043             : {
    4044           0 :         struct bgp *bgp;
    4045           0 :         struct rfapi_l2_group_cfg *rfg;
    4046           0 :         struct listnode *node;
    4047             : 
    4048           0 :         if (rfp_start_val == NULL)
    4049             :                 return NULL;
    4050             : 
    4051           0 :         bgp = rfapi_bgp_lookup_by_rfp(rfp_start_val);
    4052           0 :         if (!bgp || !bgp->rfapi_cfg)
    4053             :                 return NULL;
    4054             : 
    4055           0 :         for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->l2_groups, node, rfg)) {
    4056           0 :                 if (rfg->logical_net_id == logical_net_id
    4057           0 :                     && (search_cb == NULL
    4058           0 :                         || !search_cb(criteria, rfg->rfp_cfg))) {
    4059           0 :                         if (rfg->rfp_cfg == NULL)
    4060           0 :                                 vnc_zlog_debug_verbose(
    4061             :                                         "%s: returning rfp group config for lni=0",
    4062             :                                         __func__);
    4063           0 :                         return rfg->rfp_cfg;
    4064             :                 }
    4065             :         }
    4066             :         return NULL;
    4067             : }

Generated by: LCOV version v1.16-topotato