back to topotato report
topotato coverage report
Current view: top level - bgpd - bgp_mplsvpn.c (source / functions) Hit Total Coverage
Test: test_bgp_distance_change.py::BGPDistanceChange Lines: 94 1425 6.6 %
Date: 2023-02-24 18:37:13 Functions: 7 57 12.3 %

          Line data    Source code
       1             : /* MPLS-VPN
       2             :  * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
       3             :  *
       4             :  * This file is part of GNU Zebra.
       5             :  *
       6             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the
       8             :  * Free Software Foundation; either version 2, or (at your option) any
       9             :  * later version.
      10             :  *
      11             :  * GNU Zebra is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * 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 <zebra.h>
      22             : 
      23             : #include "command.h"
      24             : #include "prefix.h"
      25             : #include "log.h"
      26             : #include "memory.h"
      27             : #include "stream.h"
      28             : #include "queue.h"
      29             : #include "filter.h"
      30             : #include "mpls.h"
      31             : #include "json.h"
      32             : #include "zclient.h"
      33             : 
      34             : #include "bgpd/bgpd.h"
      35             : #include "bgpd/bgp_debug.h"
      36             : #include "bgpd/bgp_errors.h"
      37             : #include "bgpd/bgp_table.h"
      38             : #include "bgpd/bgp_route.h"
      39             : #include "bgpd/bgp_attr.h"
      40             : #include "bgpd/bgp_label.h"
      41             : #include "bgpd/bgp_mplsvpn.h"
      42             : #include "bgpd/bgp_packet.h"
      43             : #include "bgpd/bgp_vty.h"
      44             : #include "bgpd/bgp_vpn.h"
      45             : #include "bgpd/bgp_community.h"
      46             : #include "bgpd/bgp_ecommunity.h"
      47             : #include "bgpd/bgp_zebra.h"
      48             : #include "bgpd/bgp_nexthop.h"
      49             : #include "bgpd/bgp_nht.h"
      50             : #include "bgpd/bgp_evpn.h"
      51             : #include "bgpd/bgp_memory.h"
      52             : 
      53             : #ifdef ENABLE_BGP_VNC
      54             : #include "bgpd/rfapi/rfapi_backend.h"
      55             : #endif
      56             : 
      57             : /*
      58             :  * Definitions and external declarations.
      59             :  */
      60             : extern struct zclient *zclient;
      61             : 
      62           0 : extern int argv_find_and_parse_vpnvx(struct cmd_token **argv, int argc,
      63             :                                      int *index, afi_t *afi)
      64             : {
      65           0 :         int ret = 0;
      66           0 :         if (argv_find(argv, argc, "vpnv4", index)) {
      67           0 :                 ret = 1;
      68           0 :                 if (afi)
      69           0 :                         *afi = AFI_IP;
      70           0 :         } else if (argv_find(argv, argc, "vpnv6", index)) {
      71           0 :                 ret = 1;
      72           0 :                 if (afi)
      73           0 :                         *afi = AFI_IP6;
      74             :         }
      75           0 :         return ret;
      76             : }
      77             : 
      78           0 : uint32_t decode_label(mpls_label_t *label_pnt)
      79             : {
      80           0 :         uint32_t l;
      81           0 :         uint8_t *pnt = (uint8_t *)label_pnt;
      82             : 
      83           0 :         l = ((uint32_t)*pnt++ << 12);
      84           0 :         l |= (uint32_t)*pnt++ << 4;
      85           0 :         l |= (uint32_t)((*pnt & 0xf0) >> 4);
      86           0 :         return l;
      87             : }
      88             : 
      89           0 : void encode_label(mpls_label_t label, mpls_label_t *label_pnt)
      90             : {
      91           0 :         uint8_t *pnt = (uint8_t *)label_pnt;
      92           0 :         if (pnt == NULL)
      93             :                 return;
      94           0 :         if (label == BGP_PREVENT_VRF_2_VRF_LEAK) {
      95           0 :                 *label_pnt = label;
      96           0 :                 return;
      97             :         }
      98           0 :         *pnt++ = (label >> 12) & 0xff;
      99           0 :         *pnt++ = (label >> 4) & 0xff;
     100           0 :         *pnt++ = ((label << 4) + 1) & 0xff; /* S=1 */
     101             : }
     102             : 
     103           0 : int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr,
     104             :                        struct bgp_nlri *packet)
     105             : {
     106           0 :         struct prefix p;
     107           0 :         uint8_t psize = 0;
     108           0 :         uint8_t prefixlen;
     109           0 :         uint16_t type;
     110           0 :         struct rd_as rd_as;
     111           0 :         struct rd_ip rd_ip;
     112           0 :         struct prefix_rd prd = {0};
     113           0 :         mpls_label_t label = {0};
     114           0 :         afi_t afi;
     115           0 :         safi_t safi;
     116           0 :         bool addpath_capable;
     117           0 :         uint32_t addpath_id;
     118           0 :         int ret = 0;
     119             : 
     120             :         /* Make prefix_rd */
     121           0 :         prd.family = AF_UNSPEC;
     122           0 :         prd.prefixlen = 64;
     123             : 
     124           0 :         struct stream *data = stream_new(packet->length);
     125           0 :         stream_put(data, packet->nlri, packet->length);
     126           0 :         afi = packet->afi;
     127           0 :         safi = packet->safi;
     128           0 :         addpath_id = 0;
     129             : 
     130           0 :         addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
     131             : 
     132             : #define VPN_PREFIXLEN_MIN_BYTES (3 + 8) /* label + RD */
     133           0 :         while (STREAM_READABLE(data) > 0) {
     134             :                 /* Clear prefix structure. */
     135           0 :                 memset(&p, 0, sizeof(p));
     136             : 
     137           0 :                 if (addpath_capable) {
     138           0 :                         STREAM_GET(&addpath_id, data, BGP_ADDPATH_ID_LEN);
     139           0 :                         addpath_id = ntohl(addpath_id);
     140             :                 }
     141             : 
     142           0 :                 if (STREAM_READABLE(data) < 1) {
     143           0 :                         flog_err(
     144             :                                 EC_BGP_UPDATE_RCV,
     145             :                                 "%s [Error] Update packet error / VPN (truncated NLRI of size %u; no prefix length)",
     146             :                                 peer->host, packet->length);
     147           0 :                         ret = BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
     148           0 :                         goto done;
     149             :                 }
     150             : 
     151             :                 /* Fetch prefix length. */
     152           0 :                 STREAM_GETC(data, prefixlen);
     153           0 :                 p.family = afi2family(packet->afi);
     154           0 :                 psize = PSIZE(prefixlen);
     155             : 
     156           0 :                 if (prefixlen < VPN_PREFIXLEN_MIN_BYTES * 8) {
     157           0 :                         flog_err(
     158             :                                 EC_BGP_UPDATE_RCV,
     159             :                                 "%s [Error] Update packet error / VPN (prefix length %d less than VPN min length)",
     160             :                                 peer->host, prefixlen);
     161           0 :                         ret = BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
     162           0 :                         goto done;
     163             :                 }
     164             : 
     165             :                 /* sanity check against packet data */
     166           0 :                 if (STREAM_READABLE(data) < psize) {
     167           0 :                         flog_err(
     168             :                                 EC_BGP_UPDATE_RCV,
     169             :                                 "%s [Error] Update packet error / VPN (prefix length %d exceeds packet size %u)",
     170             :                                 peer->host, prefixlen, packet->length);
     171           0 :                         ret = BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
     172           0 :                         goto done;
     173             :                 }
     174             : 
     175             :                 /* sanity check against storage for the IP address portion */
     176           0 :                 if ((psize - VPN_PREFIXLEN_MIN_BYTES) > (ssize_t)sizeof(p.u)) {
     177             :                         flog_err(
     178             :                                 EC_BGP_UPDATE_RCV,
     179             :                                 "%s [Error] Update packet error / VPN (psize %d exceeds storage size %zu)",
     180             :                                 peer->host,
     181             :                                 prefixlen - VPN_PREFIXLEN_MIN_BYTES * 8,
     182             :                                 sizeof(p.u));
     183             :                         ret = BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
     184             :                         goto done;
     185             :                 }
     186             : 
     187             :                 /* Sanity check against max bitlen of the address family */
     188           0 :                 if ((psize - VPN_PREFIXLEN_MIN_BYTES) > prefix_blen(&p)) {
     189           0 :                         flog_err(
     190             :                                 EC_BGP_UPDATE_RCV,
     191             :                                 "%s [Error] Update packet error / VPN (psize %d exceeds family (%u) max byte len %u)",
     192             :                                 peer->host,
     193             :                                 prefixlen - VPN_PREFIXLEN_MIN_BYTES * 8,
     194             :                                 p.family, prefix_blen(&p));
     195           0 :                         ret = BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
     196           0 :                         goto done;
     197             :                 }
     198             : 
     199             :                 /* Copy label to prefix. */
     200           0 :                 if (STREAM_READABLE(data) < BGP_LABEL_BYTES) {
     201           0 :                         flog_err(
     202             :                                 EC_BGP_UPDATE_RCV,
     203             :                                 "%s [Error] Update packet error / VPN (truncated NLRI of size %u; no label)",
     204             :                                 peer->host, packet->length);
     205           0 :                         ret = BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
     206           0 :                         goto done;
     207             :                 }
     208             : 
     209           0 :                 STREAM_GET(&label, data, BGP_LABEL_BYTES);
     210           0 :                 bgp_set_valid_label(&label);
     211             : 
     212             :                 /* Copy routing distinguisher to rd. */
     213           0 :                 if (STREAM_READABLE(data) < 8) {
     214           0 :                         flog_err(
     215             :                                 EC_BGP_UPDATE_RCV,
     216             :                                 "%s [Error] Update packet error / VPN (truncated NLRI of size %u; no RD)",
     217             :                                 peer->host, packet->length);
     218           0 :                         ret = BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
     219           0 :                         goto done;
     220             :                 }
     221           0 :                 STREAM_GET(&prd.val, data, 8);
     222             : 
     223             :                 /* Decode RD type. */
     224           0 :                 type = decode_rd_type(prd.val);
     225             : 
     226           0 :                 switch (type) {
     227           0 :                 case RD_TYPE_AS:
     228           0 :                         decode_rd_as(&prd.val[2], &rd_as);
     229           0 :                         break;
     230             : 
     231           0 :                 case RD_TYPE_AS4:
     232           0 :                         decode_rd_as4(&prd.val[2], &rd_as);
     233           0 :                         break;
     234             : 
     235           0 :                 case RD_TYPE_IP:
     236           0 :                         decode_rd_ip(&prd.val[2], &rd_ip);
     237           0 :                         break;
     238             : 
     239             : #ifdef ENABLE_BGP_VNC
     240             :                 case RD_TYPE_VNC_ETH:
     241             :                         break;
     242             : #endif
     243             : 
     244           0 :                 default:
     245           0 :                         flog_err(EC_BGP_UPDATE_RCV, "Unknown RD type %d", type);
     246           0 :                         break; /* just report */
     247             :                 }
     248             : 
     249             :                 /* exclude label & RD */
     250           0 :                 p.prefixlen = prefixlen - VPN_PREFIXLEN_MIN_BYTES * 8;
     251           0 :                 STREAM_GET(p.u.val, data, psize - VPN_PREFIXLEN_MIN_BYTES);
     252             : 
     253           0 :                 if (attr) {
     254           0 :                         bgp_update(peer, &p, addpath_id, attr, packet->afi,
     255             :                                    SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP,
     256             :                                    BGP_ROUTE_NORMAL, &prd, &label, 1, 0, NULL);
     257             :                 } else {
     258           0 :                         bgp_withdraw(peer, &p, addpath_id, attr, packet->afi,
     259             :                                      SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP,
     260             :                                      BGP_ROUTE_NORMAL, &prd, &label, 1, NULL);
     261             :                 }
     262             :         }
     263             :         /* Packet length consistency check. */
     264           0 :         if (STREAM_READABLE(data) != 0) {
     265             :                 flog_err(
     266             :                         EC_BGP_UPDATE_RCV,
     267             :                         "%s [Error] Update packet error / VPN (%zu data remaining after parsing)",
     268             :                         peer->host, STREAM_READABLE(data));
     269             :                 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
     270             :         }
     271             : 
     272           0 :         goto done;
     273             : 
     274           0 : stream_failure:
     275           0 :         flog_err(
     276             :                 EC_BGP_UPDATE_RCV,
     277             :                 "%s [Error] Update packet error / VPN (NLRI of size %u - length error)",
     278             :                 peer->host, packet->length);
     279           0 :         ret = BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
     280             : 
     281           0 : done:
     282           0 :         stream_free(data);
     283           0 :         return ret;
     284             : 
     285             : #undef VPN_PREFIXLEN_MIN_BYTES
     286             : }
     287             : 
     288             : /*
     289             :  * This function informs zebra of the label this vrf sets on routes
     290             :  * leaked to VPN. Zebra should install this label in the kernel with
     291             :  * an action of "pop label and then use this vrf's IP FIB to route the PDU."
     292             :  *
     293             :  * Sending this vrf-label association is qualified by a) whether vrf->vpn
     294             :  * exporting is active ("export vpn" is enabled, vpn-policy RD and RT list
     295             :  * are set) and b) whether vpn-policy label is set.
     296             :  *
     297             :  * If any of these conditions do not hold, then we send MPLS_LABEL_NONE
     298             :  * for this vrf, which zebra interprets to mean "delete this vrf-label
     299             :  * association."
     300             :  */
     301           0 : void vpn_leak_zebra_vrf_label_update(struct bgp *bgp, afi_t afi)
     302             : {
     303           0 :         mpls_label_t label = MPLS_LABEL_NONE;
     304           0 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
     305             : 
     306           0 :         if (bgp->vrf_id == VRF_UNKNOWN) {
     307           0 :                 if (debug) {
     308           0 :                         zlog_debug(
     309             :                                 "%s: vrf %s: afi %s: vrf_id not set, can't set zebra vrf label",
     310             :                                 __func__, bgp->name_pretty, afi2str(afi));
     311             :                 }
     312           0 :                 return;
     313             :         }
     314             : 
     315           0 :         if (vpn_leak_to_vpn_active(bgp, afi, NULL)) {
     316           0 :                 label = bgp->vpn_policy[afi].tovpn_label;
     317             :         }
     318             : 
     319           0 :         if (debug) {
     320           0 :                 zlog_debug("%s: vrf %s: afi %s: setting label %d for vrf id %d",
     321             :                            __func__, bgp->name_pretty, afi2str(afi), label,
     322             :                            bgp->vrf_id);
     323             :         }
     324             : 
     325           0 :         if (label == BGP_PREVENT_VRF_2_VRF_LEAK)
     326           0 :                 label = MPLS_LABEL_NONE;
     327           0 :         zclient_send_vrf_label(zclient, bgp->vrf_id, afi, label, ZEBRA_LSP_BGP);
     328           0 :         bgp->vpn_policy[afi].tovpn_zebra_vrf_label_last_sent = label;
     329             : }
     330             : 
     331             : /*
     332             :  * If zebra tells us vrf has become unconfigured, tell zebra not to
     333             :  * use this label to forward to the vrf anymore
     334             :  */
     335           4 : void vpn_leak_zebra_vrf_label_withdraw(struct bgp *bgp, afi_t afi)
     336             : {
     337           4 :         mpls_label_t label = MPLS_LABEL_NONE;
     338           4 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
     339             : 
     340           4 :         if (bgp->vrf_id == VRF_UNKNOWN) {
     341           0 :                 if (debug) {
     342           0 :                         zlog_debug(
     343             :                                 "%s: vrf_id not set, can't delete zebra vrf label",
     344             :                                 __func__);
     345             :                 }
     346           0 :                 return;
     347             :         }
     348             : 
     349           4 :         if (debug) {
     350           0 :                 zlog_debug("%s: deleting label for vrf %s (id=%d)", __func__,
     351             :                            bgp->name_pretty, bgp->vrf_id);
     352             :         }
     353             : 
     354           4 :         zclient_send_vrf_label(zclient, bgp->vrf_id, afi, label, ZEBRA_LSP_BGP);
     355           4 :         bgp->vpn_policy[afi].tovpn_zebra_vrf_label_last_sent = label;
     356             : }
     357             : 
     358             : /*
     359             :  * This function informs zebra of the srv6-function this vrf sets on routes
     360             :  * leaked to VPN. Zebra should install this srv6-function in the kernel with
     361             :  * an action of "End.DT4/6's IP FIB to route the PDU."
     362             :  */
     363           0 : void vpn_leak_zebra_vrf_sid_update_per_af(struct bgp *bgp, afi_t afi)
     364             : {
     365           0 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
     366           0 :         enum seg6local_action_t act;
     367           0 :         struct seg6local_context ctx = {};
     368           0 :         struct in6_addr *tovpn_sid = NULL;
     369           0 :         struct in6_addr *tovpn_sid_ls = NULL;
     370           0 :         struct vrf *vrf;
     371             : 
     372           0 :         if (bgp->vrf_id == VRF_UNKNOWN) {
     373           0 :                 if (debug)
     374           0 :                         zlog_debug("%s: vrf %s: afi %s: vrf_id not set, can't set zebra vrf label",
     375             :                                    __func__, bgp->name_pretty, afi2str(afi));
     376           0 :                 return;
     377             :         }
     378             : 
     379           0 :         tovpn_sid = bgp->vpn_policy[afi].tovpn_sid;
     380           0 :         if (!tovpn_sid) {
     381           0 :                 if (debug)
     382           0 :                         zlog_debug("%s: vrf %s: afi %s: sid not set", __func__,
     383             :                                    bgp->name_pretty, afi2str(afi));
     384           0 :                 return;
     385             :         }
     386             : 
     387           0 :         if (debug)
     388           0 :                 zlog_debug("%s: vrf %s: afi %s: setting sid %pI6 for vrf id %d",
     389             :                            __func__, bgp->name_pretty, afi2str(afi), tovpn_sid,
     390             :                            bgp->vrf_id);
     391             : 
     392           0 :         vrf = vrf_lookup_by_id(bgp->vrf_id);
     393           0 :         if (!vrf)
     394             :                 return;
     395             : 
     396           0 :         ctx.table = vrf->data.l.table_id;
     397           0 :         act = afi == AFI_IP ? ZEBRA_SEG6_LOCAL_ACTION_END_DT4
     398           0 :                 : ZEBRA_SEG6_LOCAL_ACTION_END_DT6;
     399           0 :         zclient_send_localsid(zclient, tovpn_sid, bgp->vrf_id, act, &ctx);
     400             : 
     401           0 :         tovpn_sid_ls = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
     402           0 :         *tovpn_sid_ls = *tovpn_sid;
     403           0 :         bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent = tovpn_sid_ls;
     404             : }
     405             : 
     406             : /*
     407             :  * This function informs zebra of the srv6-function this vrf sets on routes
     408             :  * leaked to VPN. Zebra should install this srv6-function in the kernel with
     409             :  * an action of "End.DT46's IP FIB to route the PDU."
     410             :  */
     411           0 : void vpn_leak_zebra_vrf_sid_update_per_vrf(struct bgp *bgp)
     412             : {
     413           0 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
     414           0 :         enum seg6local_action_t act;
     415           0 :         struct seg6local_context ctx = {};
     416           0 :         struct in6_addr *tovpn_sid = NULL;
     417           0 :         struct in6_addr *tovpn_sid_ls = NULL;
     418           0 :         struct vrf *vrf;
     419             : 
     420           0 :         if (bgp->vrf_id == VRF_UNKNOWN) {
     421           0 :                 if (debug)
     422           0 :                         zlog_debug(
     423             :                                 "%s: vrf %s: vrf_id not set, can't set zebra vrf label",
     424             :                                 __func__, bgp->name_pretty);
     425           0 :                 return;
     426             :         }
     427             : 
     428           0 :         tovpn_sid = bgp->tovpn_sid;
     429           0 :         if (!tovpn_sid) {
     430           0 :                 if (debug)
     431           0 :                         zlog_debug("%s: vrf %s: sid not set", __func__,
     432             :                                    bgp->name_pretty);
     433           0 :                 return;
     434             :         }
     435             : 
     436           0 :         if (debug)
     437           0 :                 zlog_debug("%s: vrf %s: setting sid %pI6 for vrf id %d",
     438             :                            __func__, bgp->name_pretty, tovpn_sid, bgp->vrf_id);
     439             : 
     440           0 :         vrf = vrf_lookup_by_id(bgp->vrf_id);
     441           0 :         if (!vrf)
     442             :                 return;
     443             : 
     444           0 :         ctx.table = vrf->data.l.table_id;
     445           0 :         act = ZEBRA_SEG6_LOCAL_ACTION_END_DT46;
     446           0 :         zclient_send_localsid(zclient, tovpn_sid, bgp->vrf_id, act, &ctx);
     447             : 
     448           0 :         tovpn_sid_ls = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
     449           0 :         *tovpn_sid_ls = *tovpn_sid;
     450           0 :         bgp->tovpn_zebra_vrf_sid_last_sent = tovpn_sid_ls;
     451             : }
     452             : 
     453             : /*
     454             :  * This function informs zebra of the srv6-function this vrf sets on routes
     455             :  * leaked to VPN. Zebra should install this srv6-function in the kernel with
     456             :  * an action of "End.DT4/6/46's IP FIB to route the PDU."
     457             :  */
     458           0 : void vpn_leak_zebra_vrf_sid_update(struct bgp *bgp, afi_t afi)
     459             : {
     460           0 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
     461             : 
     462           0 :         if (bgp->vpn_policy[afi].tovpn_sid)
     463           0 :                 return vpn_leak_zebra_vrf_sid_update_per_af(bgp, afi);
     464             : 
     465           0 :         if (bgp->tovpn_sid)
     466           0 :                 return vpn_leak_zebra_vrf_sid_update_per_vrf(bgp);
     467             : 
     468           0 :         if (debug)
     469           0 :                 zlog_debug("%s: vrf %s: afi %s: sid not set", __func__,
     470             :                            bgp->name_pretty, afi2str(afi));
     471             : }
     472             : 
     473             : /*
     474             :  * If zebra tells us vrf has become unconfigured, tell zebra not to
     475             :  * use this srv6-function to forward to the vrf anymore
     476             :  */
     477           0 : void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi)
     478             : {
     479           0 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
     480             : 
     481           0 :         if (bgp->vrf_id == VRF_UNKNOWN) {
     482           0 :                 if (debug)
     483           0 :                         zlog_debug("%s: vrf %s: afi %s: vrf_id not set, can't set zebra vrf label",
     484             :                                    __func__, bgp->name_pretty, afi2str(afi));
     485           0 :                 return;
     486             :         }
     487             : 
     488           0 :         if (debug)
     489           0 :                 zlog_debug("%s: deleting sid for vrf %s afi (id=%d)", __func__,
     490             :                            bgp->name_pretty, bgp->vrf_id);
     491             : 
     492           0 :         zclient_send_localsid(zclient,
     493           0 :                 bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent,
     494           0 :                 bgp->vrf_id, ZEBRA_SEG6_LOCAL_ACTION_UNSPEC, NULL);
     495           0 :         XFREE(MTYPE_BGP_SRV6_SID,
     496             :               bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent);
     497             : }
     498             : 
     499             : /*
     500             :  * If zebra tells us vrf has become unconfigured, tell zebra not to
     501             :  * use this srv6-function to forward to the vrf anymore
     502             :  */
     503           0 : void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp)
     504             : {
     505           0 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
     506             : 
     507           0 :         if (bgp->vrf_id == VRF_UNKNOWN) {
     508           0 :                 if (debug)
     509           0 :                         zlog_debug(
     510             :                                 "%s: vrf %s: vrf_id not set, can't set zebra vrf label",
     511             :                                 __func__, bgp->name_pretty);
     512           0 :                 return;
     513             :         }
     514             : 
     515           0 :         if (debug)
     516           0 :                 zlog_debug("%s: deleting sid for vrf %s (id=%d)", __func__,
     517             :                            bgp->name_pretty, bgp->vrf_id);
     518             : 
     519           0 :         zclient_send_localsid(zclient, bgp->tovpn_zebra_vrf_sid_last_sent,
     520           0 :                               bgp->vrf_id, ZEBRA_SEG6_LOCAL_ACTION_UNSPEC,
     521             :                               NULL);
     522           0 :         XFREE(MTYPE_BGP_SRV6_SID, bgp->tovpn_zebra_vrf_sid_last_sent);
     523             : }
     524             : 
     525             : /*
     526             :  * If zebra tells us vrf has become unconfigured, tell zebra not to
     527             :  * use this srv6-function to forward to the vrf anymore
     528             :  */
     529           0 : void vpn_leak_zebra_vrf_sid_withdraw(struct bgp *bgp, afi_t afi)
     530             : {
     531           0 :         if (bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent)
     532           0 :                 vpn_leak_zebra_vrf_sid_withdraw_per_af(bgp, afi);
     533             : 
     534           0 :         if (bgp->tovpn_zebra_vrf_sid_last_sent)
     535           0 :                 vpn_leak_zebra_vrf_sid_withdraw_per_vrf(bgp);
     536           0 : }
     537             : 
     538           0 : int vpn_leak_label_callback(
     539             :         mpls_label_t label,
     540             :         void *labelid,
     541             :         bool allocated)
     542             : {
     543           0 :         struct vpn_policy *vp = (struct vpn_policy *)labelid;
     544           0 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
     545             : 
     546           0 :         if (debug)
     547           0 :                 zlog_debug("%s: label=%u, allocated=%d",
     548             :                         __func__, label, allocated);
     549             : 
     550           0 :         if (!allocated) {
     551             :                 /*
     552             :                  * previously-allocated label is now invalid
     553             :                  */
     554           0 :                 if (CHECK_FLAG(vp->flags, BGP_VPN_POLICY_TOVPN_LABEL_AUTO) &&
     555           0 :                         (vp->tovpn_label != MPLS_LABEL_NONE)) {
     556             : 
     557           0 :                         vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN,
     558             :                                 vp->afi, bgp_get_default(), vp->bgp);
     559           0 :                         vp->tovpn_label = MPLS_LABEL_NONE;
     560           0 :                         vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN,
     561             :                                 vp->afi, bgp_get_default(), vp->bgp);
     562             :                 }
     563           0 :                 return 0;
     564             :         }
     565             : 
     566             :         /*
     567             :          * New label allocation
     568             :          */
     569           0 :         if (!CHECK_FLAG(vp->flags, BGP_VPN_POLICY_TOVPN_LABEL_AUTO)) {
     570             : 
     571             :                 /*
     572             :                  * not currently configured for auto label, reject allocation
     573             :                  */
     574             :                 return -1;
     575             :         }
     576             : 
     577           0 :         if (vp->tovpn_label != MPLS_LABEL_NONE) {
     578           0 :                 if (label == vp->tovpn_label) {
     579             :                         /* already have same label, accept but do nothing */
     580             :                         return 0;
     581             :                 }
     582             :                 /* Shouldn't happen: different label allocation */
     583           0 :                 flog_err(EC_BGP_LABEL,
     584             :                          "%s: %s had label %u but got new assignment %u",
     585             :                          __func__, vp->bgp->name_pretty, vp->tovpn_label,
     586             :                          label);
     587             :                 /* use new one */
     588             :         }
     589             : 
     590           0 :         vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN,
     591             :                 vp->afi, bgp_get_default(), vp->bgp);
     592           0 :         vp->tovpn_label = label;
     593           0 :         vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN,
     594             :                 vp->afi, bgp_get_default(), vp->bgp);
     595             : 
     596           0 :         return 0;
     597             : }
     598             : 
     599           0 : static void sid_register(struct bgp *bgp, const struct in6_addr *sid,
     600             :                          const char *locator_name)
     601             : {
     602           0 :         struct bgp_srv6_function *func;
     603           0 :         func = XCALLOC(MTYPE_BGP_SRV6_FUNCTION,
     604             :                        sizeof(struct bgp_srv6_function));
     605           0 :         func->sid = *sid;
     606           0 :         snprintf(func->locator_name, sizeof(func->locator_name),
     607             :                  "%s", locator_name);
     608           0 :         listnode_add(bgp->srv6_functions, func);
     609           0 : }
     610             : 
     611           0 : static void sid_unregister(struct bgp *bgp, const struct in6_addr *sid)
     612             : {
     613           0 :         struct listnode *node, *nnode;
     614           0 :         struct bgp_srv6_function *func;
     615             : 
     616           0 :         for (ALL_LIST_ELEMENTS(bgp->srv6_functions, node, nnode, func))
     617           0 :                 if (sid_same(&func->sid, sid)) {
     618           0 :                         listnode_delete(bgp->srv6_functions, func);
     619           0 :                         XFREE(MTYPE_BGP_SRV6_FUNCTION, func);
     620             :                 }
     621           0 : }
     622             : 
     623           0 : static bool sid_exist(struct bgp *bgp, const struct in6_addr *sid)
     624             : {
     625           0 :         struct listnode *node;
     626           0 :         struct bgp_srv6_function *func;
     627             : 
     628           0 :         for (ALL_LIST_ELEMENTS_RO(bgp->srv6_functions, node, func))
     629           0 :                 if (sid_same(&func->sid, sid))
     630             :                         return true;
     631             :         return false;
     632             : }
     633             : 
     634             : /*
     635             :  * This function generates a new SID based on bgp->srv6_locator_chunks and
     636             :  * index. The locator and generated SID are stored in arguments sid_locator
     637             :  * and sid, respectively.
     638             :  *
     639             :  * if index != 0: try to allocate as index-mode
     640             :  * else: try to allocate as auto-mode
     641             :  */
     642           0 : static uint32_t alloc_new_sid(struct bgp *bgp, uint32_t index,
     643             :                               struct srv6_locator_chunk *sid_locator_chunk,
     644             :                               struct in6_addr *sid)
     645             : {
     646           0 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
     647           0 :         struct listnode *node;
     648           0 :         struct srv6_locator_chunk *chunk;
     649           0 :         bool alloced = false;
     650           0 :         int label = 0;
     651           0 :         uint8_t offset = 0;
     652           0 :         uint8_t func_len = 0, shift_len = 0;
     653           0 :         uint32_t index_max = 0;
     654             : 
     655           0 :         if (!bgp || !sid_locator_chunk || !sid)
     656             :                 return false;
     657             : 
     658           0 :         for (ALL_LIST_ELEMENTS_RO(bgp->srv6_locator_chunks, node, chunk)) {
     659           0 :                 if (chunk->function_bits_length >
     660             :                     BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH) {
     661           0 :                         if (debug)
     662           0 :                                 zlog_debug(
     663             :                                         "%s: invalid SRv6 Locator chunk (%pFX): Function Length must be less or equal to %d",
     664             :                                         __func__, &chunk->prefix,
     665             :                                         BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH);
     666           0 :                         continue;
     667             :                 }
     668             : 
     669           0 :                 index_max = (1 << chunk->function_bits_length) - 1;
     670             : 
     671           0 :                 if (index > index_max) {
     672           0 :                         if (debug)
     673           0 :                                 zlog_debug(
     674             :                                         "%s: skipped SRv6 Locator chunk (%pFX): Function Length is too short to support specified index (%u)",
     675             :                                         __func__, &chunk->prefix, index);
     676           0 :                         continue;
     677             :                 }
     678             : 
     679           0 :                 *sid = chunk->prefix.prefix;
     680           0 :                 *sid_locator_chunk = *chunk;
     681           0 :                 offset = chunk->block_bits_length + chunk->node_bits_length;
     682           0 :                 func_len = chunk->function_bits_length;
     683           0 :                 shift_len = BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH - func_len;
     684             : 
     685           0 :                 if (index != 0) {
     686           0 :                         label = index << shift_len;
     687           0 :                         if (label < MPLS_LABEL_UNRESERVED_MIN) {
     688           0 :                                 if (debug)
     689           0 :                                         zlog_debug(
     690             :                                                 "%s: skipped to allocate SRv6 SID (%pFX): Label (%u) is too small to use",
     691             :                                                 __func__, &chunk->prefix,
     692             :                                                 label);
     693           0 :                                 continue;
     694             :                         }
     695             : 
     696           0 :                         transpose_sid(sid, label, offset, func_len);
     697           0 :                         if (sid_exist(bgp, sid))
     698           0 :                                 continue;
     699             :                         alloced = true;
     700             :                         break;
     701             :                 }
     702             : 
     703           0 :                 for (uint32_t i = 1; i < index_max; i++) {
     704           0 :                         label = i << shift_len;
     705           0 :                         if (label < MPLS_LABEL_UNRESERVED_MIN) {
     706           0 :                                 if (debug)
     707           0 :                                         zlog_debug(
     708             :                                                 "%s: skipped to allocate SRv6 SID (%pFX): Label (%u) is too small to use",
     709             :                                                 __func__, &chunk->prefix,
     710             :                                                 label);
     711           0 :                                 continue;
     712             :                         }
     713           0 :                         transpose_sid(sid, label, offset, func_len);
     714           0 :                         if (sid_exist(bgp, sid))
     715           0 :                                 continue;
     716             :                         alloced = true;
     717             :                         break;
     718             :                 }
     719             :         }
     720             : 
     721           0 :         if (!alloced)
     722             :                 return 0;
     723             : 
     724           0 :         sid_register(bgp, sid, bgp->srv6_locator_name);
     725           0 :         return label;
     726             : }
     727             : 
     728           0 : void ensure_vrf_tovpn_sid_per_af(struct bgp *bgp_vpn, struct bgp *bgp_vrf,
     729             :                                  afi_t afi)
     730             : {
     731           0 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
     732           0 :         struct srv6_locator_chunk *tovpn_sid_locator;
     733           0 :         struct in6_addr *tovpn_sid;
     734           0 :         uint32_t tovpn_sid_index = 0, tovpn_sid_transpose_label;
     735           0 :         bool tovpn_sid_auto = false;
     736             : 
     737           0 :         if (debug)
     738           0 :                 zlog_debug("%s: try to allocate new SID for vrf %s: afi %s",
     739             :                            __func__, bgp_vrf->name_pretty, afi2str(afi));
     740             : 
     741             :         /* skip when tovpn sid is already allocated on vrf instance */
     742           0 :         if (bgp_vrf->vpn_policy[afi].tovpn_sid)
     743           0 :                 return;
     744             : 
     745             :         /*
     746             :          * skip when bgp vpn instance ins't allocated
     747             :          * or srv6 locator chunk isn't allocated
     748             :          */
     749           0 :         if (!bgp_vpn || !bgp_vpn->srv6_locator_chunks)
     750             :                 return;
     751             : 
     752           0 :         tovpn_sid_index = bgp_vrf->vpn_policy[afi].tovpn_sid_index;
     753           0 :         tovpn_sid_auto = CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
     754             :                                     BGP_VPN_POLICY_TOVPN_SID_AUTO);
     755             : 
     756             :         /* skip when VPN isn't configured on vrf-instance */
     757           0 :         if (tovpn_sid_index == 0 && !tovpn_sid_auto)
     758             :                 return;
     759             : 
     760             :         /* check invalid case both configured index and auto */
     761           0 :         if (tovpn_sid_index != 0 && tovpn_sid_auto) {
     762           0 :                 zlog_err("%s: index-mode and auto-mode both selected. ignored.",
     763             :                          __func__);
     764           0 :                 return;
     765             :         }
     766             : 
     767           0 :         tovpn_sid_locator = srv6_locator_chunk_alloc();
     768           0 :         tovpn_sid = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
     769             : 
     770           0 :         tovpn_sid_transpose_label = alloc_new_sid(bgp_vpn, tovpn_sid_index,
     771             :                                                   tovpn_sid_locator, tovpn_sid);
     772             : 
     773           0 :         if (tovpn_sid_transpose_label == 0) {
     774           0 :                 if (debug)
     775           0 :                         zlog_debug(
     776             :                                 "%s: not allocated new sid for vrf %s: afi %s",
     777             :                                 __func__, bgp_vrf->name_pretty, afi2str(afi));
     778           0 :                 srv6_locator_chunk_free(&tovpn_sid_locator);
     779           0 :                 XFREE(MTYPE_BGP_SRV6_SID, tovpn_sid);
     780           0 :                 return;
     781             :         }
     782             : 
     783           0 :         if (debug)
     784           0 :                 zlog_debug("%s: new sid %pI6 allocated for vrf %s: afi %s",
     785             :                            __func__, tovpn_sid, bgp_vrf->name_pretty,
     786             :                            afi2str(afi));
     787             : 
     788           0 :         bgp_vrf->vpn_policy[afi].tovpn_sid = tovpn_sid;
     789           0 :         bgp_vrf->vpn_policy[afi].tovpn_sid_locator = tovpn_sid_locator;
     790           0 :         bgp_vrf->vpn_policy[afi].tovpn_sid_transpose_label =
     791             :                 tovpn_sid_transpose_label;
     792             : }
     793             : 
     794           0 : void ensure_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
     795             : {
     796           0 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
     797           0 :         struct srv6_locator_chunk *tovpn_sid_locator;
     798           0 :         struct in6_addr *tovpn_sid;
     799           0 :         uint32_t tovpn_sid_index = 0, tovpn_sid_transpose_label;
     800           0 :         bool tovpn_sid_auto = false;
     801             : 
     802           0 :         if (debug)
     803           0 :                 zlog_debug("%s: try to allocate new SID for vrf %s", __func__,
     804             :                            bgp_vrf->name_pretty);
     805             : 
     806             :         /* skip when tovpn sid is already allocated on vrf instance */
     807           0 :         if (bgp_vrf->tovpn_sid)
     808           0 :                 return;
     809             : 
     810             :         /*
     811             :          * skip when bgp vpn instance ins't allocated
     812             :          * or srv6 locator chunk isn't allocated
     813             :          */
     814           0 :         if (!bgp_vpn || !bgp_vpn->srv6_locator_chunks)
     815             :                 return;
     816             : 
     817           0 :         tovpn_sid_index = bgp_vrf->tovpn_sid_index;
     818           0 :         tovpn_sid_auto = CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_AUTO);
     819             : 
     820             :         /* skip when VPN isn't configured on vrf-instance */
     821           0 :         if (tovpn_sid_index == 0 && !tovpn_sid_auto)
     822             :                 return;
     823             : 
     824             :         /* check invalid case both configured index and auto */
     825           0 :         if (tovpn_sid_index != 0 && tovpn_sid_auto) {
     826           0 :                 zlog_err("%s: index-mode and auto-mode both selected. ignored.",
     827             :                          __func__);
     828           0 :                 return;
     829             :         }
     830             : 
     831           0 :         tovpn_sid_locator = srv6_locator_chunk_alloc();
     832           0 :         tovpn_sid = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
     833             : 
     834           0 :         tovpn_sid_transpose_label = alloc_new_sid(bgp_vpn, tovpn_sid_index,
     835             :                                                   tovpn_sid_locator, tovpn_sid);
     836             : 
     837           0 :         if (tovpn_sid_transpose_label == 0) {
     838           0 :                 if (debug)
     839           0 :                         zlog_debug("%s: not allocated new sid for vrf %s",
     840             :                                    __func__, bgp_vrf->name_pretty);
     841           0 :                 srv6_locator_chunk_free(&tovpn_sid_locator);
     842           0 :                 XFREE(MTYPE_BGP_SRV6_SID, tovpn_sid);
     843           0 :                 return;
     844             :         }
     845             : 
     846           0 :         if (debug)
     847           0 :                 zlog_debug("%s: new sid %pI6 allocated for vrf %s", __func__,
     848             :                            tovpn_sid, bgp_vrf->name_pretty);
     849             : 
     850           0 :         bgp_vrf->tovpn_sid = tovpn_sid;
     851           0 :         bgp_vrf->tovpn_sid_locator = tovpn_sid_locator;
     852           0 :         bgp_vrf->tovpn_sid_transpose_label = tovpn_sid_transpose_label;
     853             : }
     854             : 
     855           0 : void ensure_vrf_tovpn_sid(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi)
     856             : {
     857             :         /* per-af sid */
     858           0 :         if (bgp_vrf->vpn_policy[afi].tovpn_sid_index != 0 ||
     859           0 :             CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
     860             :                        BGP_VPN_POLICY_TOVPN_SID_AUTO))
     861           0 :                 return ensure_vrf_tovpn_sid_per_af(bgp_vpn, bgp_vrf, afi);
     862             : 
     863             :         /* per-vrf sid */
     864           0 :         if (bgp_vrf->tovpn_sid_index != 0 ||
     865           0 :             CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_AUTO))
     866           0 :                 return ensure_vrf_tovpn_sid_per_vrf(bgp_vpn, bgp_vrf);
     867             : }
     868             : 
     869           0 : void delete_vrf_tovpn_sid_per_af(struct bgp *bgp_vpn, struct bgp *bgp_vrf,
     870             :                                  afi_t afi)
     871             : {
     872           0 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
     873           0 :         uint32_t tovpn_sid_index = 0;
     874           0 :         bool tovpn_sid_auto = false;
     875             : 
     876           0 :         if (debug)
     877           0 :                 zlog_debug("%s: try to remove SID for vrf %s: afi %s", __func__,
     878             :                            bgp_vrf->name_pretty, afi2str(afi));
     879             : 
     880           0 :         tovpn_sid_index = bgp_vrf->vpn_policy[afi].tovpn_sid_index;
     881           0 :         tovpn_sid_auto = CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
     882             :                                     BGP_VPN_POLICY_TOVPN_SID_AUTO);
     883             : 
     884             :         /* skip when VPN is configured on vrf-instance */
     885           0 :         if (tovpn_sid_index != 0 || tovpn_sid_auto)
     886             :                 return;
     887             : 
     888           0 :         srv6_locator_chunk_free(&bgp_vrf->vpn_policy[afi].tovpn_sid_locator);
     889             : 
     890           0 :         if (bgp_vrf->vpn_policy[afi].tovpn_sid) {
     891           0 :                 sid_unregister(bgp_vpn, bgp_vrf->vpn_policy[afi].tovpn_sid);
     892           0 :                 XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->vpn_policy[afi].tovpn_sid);
     893             :         }
     894           0 :         bgp_vrf->vpn_policy[afi].tovpn_sid_transpose_label = 0;
     895             : }
     896             : 
     897           0 : void delete_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
     898             : {
     899           0 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
     900           0 :         uint32_t tovpn_sid_index = 0;
     901           0 :         bool tovpn_sid_auto = false;
     902             : 
     903           0 :         if (debug)
     904           0 :                 zlog_debug("%s: try to remove SID for vrf %s", __func__,
     905             :                            bgp_vrf->name_pretty);
     906             : 
     907           0 :         tovpn_sid_index = bgp_vrf->tovpn_sid_index;
     908           0 :         tovpn_sid_auto =
     909           0 :                 CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VPN_POLICY_TOVPN_SID_AUTO);
     910             : 
     911             :         /* skip when VPN is configured on vrf-instance */
     912           0 :         if (tovpn_sid_index != 0 || tovpn_sid_auto)
     913             :                 return;
     914             : 
     915           0 :         srv6_locator_chunk_free(&bgp_vrf->tovpn_sid_locator);
     916             : 
     917           0 :         if (bgp_vrf->tovpn_sid) {
     918           0 :                 sid_unregister(bgp_vpn, bgp_vrf->tovpn_sid);
     919           0 :                 XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid);
     920             :         }
     921           0 :         bgp_vrf->tovpn_sid_transpose_label = 0;
     922             : }
     923             : 
     924           0 : void delete_vrf_tovpn_sid(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi)
     925             : {
     926           0 :         delete_vrf_tovpn_sid_per_af(bgp_vpn, bgp_vrf, afi);
     927           0 :         delete_vrf_tovpn_sid_per_vrf(bgp_vpn, bgp_vrf);
     928           0 : }
     929             : 
     930             : /*
     931             :  * This function embeds upper `len` bits of `label` in `sid`,
     932             :  * starting at offset `offset` as seen from the MSB of `sid`.
     933             :  *
     934             :  * e.g. Given that `label` is 0x12345 and `len` is 16,
     935             :  * then `label` will be embedded in `sid` as follows:
     936             :  *
     937             :  *                 <----   len  ----->
     938             :  *         label:  0001 0002 0003 0004 0005
     939             :  *         sid:    .... 0001 0002 0003 0004
     940             :  *                      <----   len  ----->
     941             :  *                    ^
     942             :  *                    |
     943             :  *                 offset from MSB
     944             :  *
     945             :  * e.g. Given that `label` is 0x12345 and `len` is 8,
     946             :  * `label` will be embedded in `sid` as follows:
     947             :  *
     948             :  *                 <- len ->
     949             :  *         label:  0001 0002 0003 0004 0005
     950             :  *         sid:    .... 0001 0002 0000 0000
     951             :  *                      <- len ->
     952             :  *                    ^
     953             :  *                    |
     954             :  *                 offset from MSB
     955             :  */
     956           0 : void transpose_sid(struct in6_addr *sid, uint32_t label, uint8_t offset,
     957             :                    uint8_t len)
     958             : {
     959           0 :         for (uint8_t idx = 0; idx < len; idx++) {
     960           0 :                 uint8_t tidx = offset + idx;
     961           0 :                 sid->s6_addr[tidx / 8] &= ~(0x1 << (7 - tidx % 8));
     962           0 :                 if (label >> (19 - idx) & 0x1)
     963           0 :                         sid->s6_addr[tidx / 8] |= 0x1 << (7 - tidx % 8);
     964             :         }
     965           0 : }
     966             : 
     967           0 : static bool labels_same(struct bgp_path_info *bpi, mpls_label_t *label,
     968             :                         uint32_t n)
     969             : {
     970           0 :         uint32_t i;
     971             : 
     972           0 :         if (!bpi->extra) {
     973           0 :                 if (!n)
     974             :                         return true;
     975             :                 else
     976           0 :                         return false;
     977             :         }
     978             : 
     979           0 :         if (n != bpi->extra->num_labels)
     980             :                 return false;
     981             : 
     982           0 :         for (i = 0; i < n; ++i) {
     983           0 :                 if (label[i] != bpi->extra->label[i])
     984             :                         return false;
     985             :         }
     986             :         return true;
     987             : }
     988             : 
     989             : /*
     990             :  * make encoded route labels match specified encoded label set
     991             :  */
     992           0 : static void setlabels(struct bgp_path_info *bpi,
     993             :                       mpls_label_t *label, /* array of labels */
     994             :                       uint32_t num_labels)
     995             : {
     996           0 :         if (num_labels)
     997           0 :                 assert(label);
     998           0 :         assert(num_labels <= BGP_MAX_LABELS);
     999             : 
    1000           0 :         if (!num_labels) {
    1001           0 :                 if (bpi->extra)
    1002           0 :                         bpi->extra->num_labels = 0;
    1003           0 :                 return;
    1004             :         }
    1005             : 
    1006           0 :         struct bgp_path_info_extra *extra = bgp_path_info_extra_get(bpi);
    1007           0 :         uint32_t i;
    1008             : 
    1009           0 :         for (i = 0; i < num_labels; ++i) {
    1010           0 :                 extra->label[i] = label[i];
    1011           0 :                 if (!bgp_is_valid_label(&label[i])) {
    1012           0 :                         bgp_set_valid_label(&extra->label[i]);
    1013             :                 }
    1014             :         }
    1015           0 :         extra->num_labels = num_labels;
    1016             : }
    1017             : 
    1018             : /*
    1019             :  * make encoded route SIDs match specified encoded sid set
    1020             :  */
    1021           0 : static void setsids(struct bgp_path_info *bpi,
    1022             :                       struct in6_addr *sid,
    1023             :                       uint32_t num_sids)
    1024             : {
    1025           0 :         uint32_t i;
    1026           0 :         struct bgp_path_info_extra *extra;
    1027             : 
    1028           0 :         if (num_sids)
    1029           0 :                 assert(sid);
    1030           0 :         assert(num_sids <= BGP_MAX_SIDS);
    1031             : 
    1032           0 :         if (!num_sids) {
    1033           0 :                 if (bpi->extra)
    1034           0 :                         bpi->extra->num_sids = 0;
    1035           0 :                 return;
    1036             :         }
    1037             : 
    1038           0 :         extra = bgp_path_info_extra_get(bpi);
    1039           0 :         for (i = 0; i < num_sids; i++)
    1040           0 :                 memcpy(&extra->sid[i].sid, &sid[i], sizeof(struct in6_addr));
    1041           0 :         extra->num_sids = num_sids;
    1042             : }
    1043             : 
    1044           0 : static void unsetsids(struct bgp_path_info *bpi)
    1045             : {
    1046           0 :         struct bgp_path_info_extra *extra;
    1047             : 
    1048           0 :         extra = bgp_path_info_extra_get(bpi);
    1049           0 :         extra->num_sids = 0;
    1050           0 :         memset(extra->sid, 0, sizeof(extra->sid));
    1051           0 : }
    1052             : 
    1053           0 : static bool leak_update_nexthop_valid(struct bgp *to_bgp, struct bgp_dest *bn,
    1054             :                                       struct attr *new_attr, afi_t afi,
    1055             :                                       safi_t safi,
    1056             :                                       struct bgp_path_info *source_bpi,
    1057             :                                       struct bgp_path_info *bpi,
    1058             :                                       struct bgp *bgp_orig,
    1059             :                                       const struct prefix *p, int debug)
    1060             : {
    1061           0 :         struct bgp_path_info *bpi_ultimate;
    1062           0 :         struct bgp *bgp_nexthop;
    1063           0 :         bool nh_valid;
    1064             : 
    1065           0 :         bpi_ultimate = bgp_get_imported_bpi_ultimate(source_bpi);
    1066             : 
    1067           0 :         if (bpi->extra && bpi->extra->bgp_orig)
    1068           0 :                 bgp_nexthop = bpi->extra->bgp_orig;
    1069             :         else
    1070             :                 bgp_nexthop = bgp_orig;
    1071             : 
    1072             :         /*
    1073             :          * No nexthop tracking for redistributed routes, for
    1074             :          * EVPN-imported routes that get leaked, or for routes
    1075             :          * leaked between VRFs with accept-own community.
    1076             :          */
    1077           0 :         if (bpi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE ||
    1078           0 :             is_pi_family_evpn(bpi_ultimate) ||
    1079           0 :             CHECK_FLAG(bpi_ultimate->flags, BGP_PATH_ACCEPT_OWN))
    1080             :                 nh_valid = true;
    1081             :         else
    1082             :                 /*
    1083             :                  * TBD do we need to do anything about the
    1084             :                  * 'connected' parameter?
    1085             :                  */
    1086           0 :                 nh_valid = bgp_find_or_add_nexthop(to_bgp, bgp_nexthop, afi,
    1087             :                                                    safi, bpi, NULL, 0, p);
    1088             : 
    1089             :         /*
    1090             :          * If you are using SRv6 VPN instead of MPLS, it need to check
    1091             :          * the SID allocation. If the sid is not allocated, the rib
    1092             :          * will be invalid.
    1093             :          */
    1094           0 :         if (to_bgp->srv6_enabled &&
    1095           0 :             (!new_attr->srv6_l3vpn && !new_attr->srv6_vpn)) {
    1096           0 :                 nh_valid = false;
    1097             :         }
    1098             : 
    1099           0 :         if (debug)
    1100           0 :                 zlog_debug("%s: %pFX nexthop is %svalid (in %s)", __func__, p,
    1101             :                            (nh_valid ? "" : "not "), bgp_nexthop->name_pretty);
    1102             : 
    1103           0 :         return nh_valid;
    1104             : }
    1105             : 
    1106             : /*
    1107             :  * returns pointer to new bgp_path_info upon success
    1108             :  */
    1109             : static struct bgp_path_info *
    1110           0 : leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
    1111             :             struct attr *new_attr, /* already interned */
    1112             :             afi_t afi, safi_t safi, struct bgp_path_info *source_bpi,
    1113             :             mpls_label_t *label, uint32_t num_labels, struct bgp *bgp_orig,
    1114             :             struct prefix *nexthop_orig, int nexthop_self_flag, int debug)
    1115             : {
    1116           0 :         const struct prefix *p = bgp_dest_get_prefix(bn);
    1117           0 :         struct bgp_path_info *bpi;
    1118           0 :         struct bgp_path_info *new;
    1119           0 :         struct bgp_path_info_extra *extra;
    1120           0 :         uint32_t num_sids = 0;
    1121           0 :         void *parent = source_bpi;
    1122             : 
    1123           0 :         if (new_attr->srv6_l3vpn || new_attr->srv6_vpn)
    1124           0 :                 num_sids = 1;
    1125             : 
    1126           0 :         if (debug)
    1127           0 :                 zlog_debug(
    1128             :                         "%s: entry: leak-to=%s, p=%pBD, type=%d, sub_type=%d",
    1129             :                         __func__, to_bgp->name_pretty, bn, source_bpi->type,
    1130             :                         source_bpi->sub_type);
    1131             : 
    1132             :         /*
    1133             :          * Routes that are redistributed into BGP from zebra do not get
    1134             :          * nexthop tracking. However, if those routes are subsequently
    1135             :          * imported to other RIBs within BGP, the leaked routes do not
    1136             :          * carry the original BGP_ROUTE_REDISTRIBUTE sub_type. Therefore,
    1137             :          * in order to determine if the route we are currently leaking
    1138             :          * should have nexthop tracking, we must find the ultimate
    1139             :          * parent so we can check its sub_type.
    1140             :          *
    1141             :          * As of now, source_bpi may at most be a second-generation route
    1142             :          * (only one hop back to ultimate parent for vrf-vpn-vrf scheme).
    1143             :          * Using a loop here supports more complex intra-bgp import-export
    1144             :          * schemes that could be implemented in the future.
    1145             :          *
    1146             :          */
    1147             : 
    1148             :         /*
    1149             :          * match parent
    1150             :          */
    1151           0 :         for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) {
    1152           0 :                 if (bpi->extra && bpi->extra->parent == parent)
    1153             :                         break;
    1154             :         }
    1155             : 
    1156           0 :         if (bpi) {
    1157           0 :                 bool labelssame = labels_same(bpi, label, num_labels);
    1158             : 
    1159           0 :                 if (CHECK_FLAG(source_bpi->flags, BGP_PATH_REMOVED)
    1160           0 :                     && CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
    1161           0 :                         if (debug) {
    1162           0 :                                 zlog_debug(
    1163             :                                         "%s: ->%s(s_flags: 0x%x b_flags: 0x%x): %pFX: Found route, being removed, not leaking",
    1164             :                                         __func__, to_bgp->name_pretty,
    1165             :                                         source_bpi->flags, bpi->flags, p);
    1166             :                         }
    1167           0 :                         return NULL;
    1168             :                 }
    1169             : 
    1170           0 :                 if (attrhash_cmp(bpi->attr, new_attr) && labelssame
    1171           0 :                     && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
    1172             : 
    1173           0 :                         bgp_attr_unintern(&new_attr);
    1174           0 :                         if (debug)
    1175           0 :                                 zlog_debug(
    1176             :                                         "%s: ->%s: %pBD: Found route, no change",
    1177             :                                         __func__, to_bgp->name_pretty, bn);
    1178           0 :                         return NULL;
    1179             :                 }
    1180             : 
    1181             :                 /* If the RT was changed via extended communities as an
    1182             :                  * import/export list, we should withdraw implicitly the old
    1183             :                  * path from VRFs.
    1184             :                  * For instance, RT list was modified using route-maps:
    1185             :                  * route-map test permit 10
    1186             :                  *   set extcommunity rt none
    1187             :                  */
    1188           0 :                 if (CHECK_FLAG(bpi->attr->flag,
    1189           0 :                                ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) &&
    1190           0 :                     CHECK_FLAG(new_attr->flag,
    1191             :                                ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
    1192           0 :                         if (!ecommunity_cmp(
    1193           0 :                                     bgp_attr_get_ecommunity(bpi->attr),
    1194           0 :                                     bgp_attr_get_ecommunity(new_attr))) {
    1195           0 :                                 vpn_leak_to_vrf_withdraw(bpi);
    1196           0 :                                 bgp_aggregate_decrement(to_bgp, p, bpi, afi,
    1197             :                                                         safi);
    1198           0 :                                 bgp_path_info_delete(bn, bpi);
    1199             :                         }
    1200             :                 }
    1201             : 
    1202             :                 /* attr is changed */
    1203           0 :                 bgp_path_info_set_flag(bn, bpi, BGP_PATH_ATTR_CHANGED);
    1204             : 
    1205             :                 /* Rewrite BGP route information. */
    1206           0 :                 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
    1207           0 :                         bgp_path_info_restore(bn, bpi);
    1208             :                 else
    1209           0 :                         bgp_aggregate_decrement(to_bgp, p, bpi, afi, safi);
    1210           0 :                 bgp_attr_unintern(&bpi->attr);
    1211           0 :                 bpi->attr = new_attr;
    1212           0 :                 bpi->uptime = monotime(NULL);
    1213             : 
    1214             :                 /*
    1215             :                  * rewrite labels
    1216             :                  */
    1217           0 :                 if (!labelssame)
    1218           0 :                         setlabels(bpi, label, num_labels);
    1219             : 
    1220             :                 /*
    1221             :                  * rewrite sid
    1222             :                  */
    1223           0 :                 if (num_sids) {
    1224           0 :                         if (new_attr->srv6_l3vpn) {
    1225           0 :                                 setsids(bpi, &new_attr->srv6_l3vpn->sid,
    1226             :                                         num_sids);
    1227             : 
    1228           0 :                                 extra = bgp_path_info_extra_get(bpi);
    1229             : 
    1230           0 :                                 extra->sid[0].loc_block_len =
    1231           0 :                                         new_attr->srv6_l3vpn->loc_block_len;
    1232           0 :                                 extra->sid[0].loc_node_len =
    1233           0 :                                         new_attr->srv6_l3vpn->loc_node_len;
    1234           0 :                                 extra->sid[0].func_len =
    1235           0 :                                         new_attr->srv6_l3vpn->func_len;
    1236           0 :                                 extra->sid[0].arg_len =
    1237           0 :                                         new_attr->srv6_l3vpn->arg_len;
    1238           0 :                                 extra->sid[0].transposition_len =
    1239           0 :                                         new_attr->srv6_l3vpn->transposition_len;
    1240           0 :                                 extra->sid[0].transposition_offset =
    1241             :                                         new_attr->srv6_l3vpn
    1242           0 :                                                 ->transposition_offset;
    1243           0 :                         } else if (new_attr->srv6_vpn)
    1244           0 :                                 setsids(bpi, &new_attr->srv6_vpn->sid,
    1245             :                                         num_sids);
    1246             :                 } else
    1247           0 :                         unsetsids(bpi);
    1248             : 
    1249           0 :                 if (nexthop_self_flag)
    1250           0 :                         bgp_path_info_set_flag(bn, bpi, BGP_PATH_ANNC_NH_SELF);
    1251             : 
    1252           0 :                 if (CHECK_FLAG(source_bpi->flags, BGP_PATH_ACCEPT_OWN))
    1253           0 :                         bgp_path_info_set_flag(bn, bpi, BGP_PATH_ACCEPT_OWN);
    1254             : 
    1255           0 :                 if (leak_update_nexthop_valid(to_bgp, bn, new_attr, afi, safi,
    1256             :                                               source_bpi, bpi, bgp_orig, p,
    1257             :                                               debug))
    1258           0 :                         bgp_path_info_set_flag(bn, bpi, BGP_PATH_VALID);
    1259             :                 else
    1260           0 :                         bgp_path_info_unset_flag(bn, bpi, BGP_PATH_VALID);
    1261             : 
    1262             :                 /* Process change. */
    1263           0 :                 bgp_aggregate_increment(to_bgp, p, bpi, afi, safi);
    1264           0 :                 bgp_process(to_bgp, bn, afi, safi);
    1265           0 :                 bgp_dest_unlock_node(bn);
    1266             : 
    1267           0 :                 if (debug)
    1268           0 :                         zlog_debug("%s: ->%s: %pBD Found route, changed attr",
    1269             :                                    __func__, to_bgp->name_pretty, bn);
    1270             : 
    1271           0 :                 return bpi;
    1272             :         }
    1273             : 
    1274           0 :         if (CHECK_FLAG(source_bpi->flags, BGP_PATH_REMOVED)) {
    1275           0 :                 if (debug) {
    1276           0 :                         zlog_debug(
    1277             :                                 "%s: ->%s(s_flags: 0x%x): %pFX: New route, being removed, not leaking",
    1278             :                                 __func__, to_bgp->name_pretty,
    1279             :                                 source_bpi->flags, p);
    1280             :                 }
    1281           0 :                 return NULL;
    1282             :         }
    1283             : 
    1284           0 :         new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_IMPORTED, 0,
    1285             :                         to_bgp->peer_self, new_attr, bn);
    1286             : 
    1287           0 :         if (source_bpi->peer) {
    1288           0 :                 extra = bgp_path_info_extra_get(new);
    1289           0 :                 extra->peer_orig = peer_lock(source_bpi->peer);
    1290             :         }
    1291             : 
    1292           0 :         if (nexthop_self_flag)
    1293           0 :                 bgp_path_info_set_flag(bn, new, BGP_PATH_ANNC_NH_SELF);
    1294             : 
    1295           0 :         if (CHECK_FLAG(source_bpi->flags, BGP_PATH_ACCEPT_OWN))
    1296           0 :                 bgp_path_info_set_flag(bn, new, BGP_PATH_ACCEPT_OWN);
    1297             : 
    1298           0 :         bgp_path_info_extra_get(new);
    1299             : 
    1300             :         /*
    1301             :          * rewrite sid
    1302             :          */
    1303           0 :         if (num_sids) {
    1304           0 :                 if (new_attr->srv6_l3vpn) {
    1305           0 :                         setsids(new, &new_attr->srv6_l3vpn->sid, num_sids);
    1306             : 
    1307           0 :                         extra = bgp_path_info_extra_get(new);
    1308             : 
    1309           0 :                         extra->sid[0].loc_block_len =
    1310           0 :                                 new_attr->srv6_l3vpn->loc_block_len;
    1311           0 :                         extra->sid[0].loc_node_len =
    1312           0 :                                 new_attr->srv6_l3vpn->loc_node_len;
    1313           0 :                         extra->sid[0].func_len = new_attr->srv6_l3vpn->func_len;
    1314           0 :                         extra->sid[0].arg_len = new_attr->srv6_l3vpn->arg_len;
    1315           0 :                         extra->sid[0].transposition_len =
    1316           0 :                                 new_attr->srv6_l3vpn->transposition_len;
    1317           0 :                         extra->sid[0].transposition_offset =
    1318           0 :                                 new_attr->srv6_l3vpn->transposition_offset;
    1319           0 :                 } else if (new_attr->srv6_vpn)
    1320           0 :                         setsids(new, &new_attr->srv6_vpn->sid, num_sids);
    1321             :         } else
    1322           0 :                 unsetsids(new);
    1323             : 
    1324           0 :         if (num_labels)
    1325           0 :                 setlabels(new, label, num_labels);
    1326             : 
    1327           0 :         new->extra->parent = bgp_path_info_lock(parent);
    1328           0 :         bgp_dest_lock_node(
    1329             :                 (struct bgp_dest *)((struct bgp_path_info *)parent)->net);
    1330           0 :         if (bgp_orig)
    1331           0 :                 new->extra->bgp_orig = bgp_lock(bgp_orig);
    1332           0 :         if (nexthop_orig)
    1333           0 :                 new->extra->nexthop_orig = *nexthop_orig;
    1334             : 
    1335           0 :         if (leak_update_nexthop_valid(to_bgp, bn, new_attr, afi, safi,
    1336             :                                       source_bpi, new, bgp_orig, p, debug))
    1337           0 :                 bgp_path_info_set_flag(bn, new, BGP_PATH_VALID);
    1338             :         else
    1339           0 :                 bgp_path_info_unset_flag(bn, new, BGP_PATH_VALID);
    1340             : 
    1341           0 :         bgp_aggregate_increment(to_bgp, p, new, afi, safi);
    1342           0 :         bgp_path_info_add(bn, new);
    1343             : 
    1344           0 :         bgp_dest_unlock_node(bn);
    1345           0 :         bgp_process(to_bgp, bn, afi, safi);
    1346             : 
    1347           0 :         if (debug)
    1348           0 :                 zlog_debug("%s: ->%s: %pBD: Added new route", __func__,
    1349             :                            to_bgp->name_pretty, bn);
    1350             : 
    1351             :         return new;
    1352             : }
    1353             : 
    1354             : /* cf vnc_import_bgp_add_route_mode_nvegroup() and add_vnc_route() */
    1355           4 : void vpn_leak_from_vrf_update(struct bgp *to_bgp,            /* to */
    1356             :                               struct bgp *from_bgp,        /* from */
    1357             :                               struct bgp_path_info *path_vrf) /* route */
    1358             : {
    1359           4 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
    1360           4 :         const struct prefix *p = bgp_dest_get_prefix(path_vrf->net);
    1361           4 :         afi_t afi = family2afi(p->family);
    1362           4 :         struct attr static_attr = {0};
    1363           4 :         struct attr *new_attr = NULL;
    1364           4 :         safi_t safi = SAFI_MPLS_VPN;
    1365           4 :         mpls_label_t label_val;
    1366           4 :         mpls_label_t label;
    1367           4 :         struct bgp_dest *bn;
    1368           4 :         const char *debugmsg;
    1369           4 :         int nexthop_self_flag = 0;
    1370             : 
    1371           4 :         if (debug)
    1372           0 :                 zlog_debug("%s: from vrf %s", __func__, from_bgp->name_pretty);
    1373             : 
    1374           0 :         if (debug && bgp_attr_get_ecommunity(path_vrf->attr)) {
    1375           0 :                 char *s = ecommunity_ecom2str(
    1376           0 :                         bgp_attr_get_ecommunity(path_vrf->attr),
    1377             :                         ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
    1378             : 
    1379           0 :                 zlog_debug("%s: %s path_vrf->type=%d, EC{%s}", __func__,
    1380             :                            from_bgp->name, path_vrf->type, s);
    1381           0 :                 XFREE(MTYPE_ECOMMUNITY_STR, s);
    1382             :         }
    1383             : 
    1384           4 :         if (!to_bgp)
    1385           4 :                 return;
    1386             : 
    1387           4 :         if (!afi) {
    1388           0 :                 if (debug)
    1389           0 :                         zlog_debug("%s: can't get afi of prefix", __func__);
    1390           0 :                 return;
    1391             :         }
    1392             : 
    1393             :         /* Is this route exportable into the VPN table? */
    1394           4 :         if (!is_route_injectable_into_vpn(path_vrf))
    1395             :                 return;
    1396             : 
    1397           4 :         if (!vpn_leak_to_vpn_active(from_bgp, afi, &debugmsg)) {
    1398           4 :                 if (debug)
    1399           0 :                         zlog_debug("%s: %s skipping: %s", __func__,
    1400             :                                    from_bgp->name, debugmsg);
    1401           4 :                 return;
    1402             :         }
    1403             : 
    1404             :         /* shallow copy */
    1405           0 :         static_attr = *path_vrf->attr;
    1406             : 
    1407             :         /*
    1408             :          * route map handling
    1409             :          */
    1410           0 :         if (from_bgp->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_TOVPN]) {
    1411           0 :                 struct bgp_path_info info;
    1412           0 :                 route_map_result_t ret;
    1413             : 
    1414           0 :                 memset(&info, 0, sizeof(info));
    1415           0 :                 info.peer = to_bgp->peer_self;
    1416           0 :                 info.attr = &static_attr;
    1417           0 :                 ret = route_map_apply(from_bgp->vpn_policy[afi]
    1418             :                                               .rmap[BGP_VPN_POLICY_DIR_TOVPN],
    1419             :                                       p, &info);
    1420           0 :                 if (RMAP_DENYMATCH == ret) {
    1421           0 :                         bgp_attr_flush(&static_attr); /* free any added parts */
    1422           0 :                         if (debug)
    1423           0 :                                 zlog_debug(
    1424             :                                         "%s: vrf %s route map \"%s\" says DENY, returning",
    1425             :                                         __func__, from_bgp->name_pretty,
    1426             :                                         from_bgp->vpn_policy[afi]
    1427             :                                                 .rmap[BGP_VPN_POLICY_DIR_TOVPN]
    1428             :                                                 ->name);
    1429           0 :                         return;
    1430             :                 }
    1431             :         }
    1432             : 
    1433           0 :         if (debug && bgp_attr_get_ecommunity(&static_attr)) {
    1434           0 :                 char *s = ecommunity_ecom2str(
    1435             :                         bgp_attr_get_ecommunity(&static_attr),
    1436             :                         ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
    1437             : 
    1438           0 :                 zlog_debug("%s: post route map static_attr.ecommunity{%s}",
    1439             :                            __func__, s);
    1440           0 :                 XFREE(MTYPE_ECOMMUNITY_STR, s);
    1441             :         }
    1442             : 
    1443             :         /*
    1444             :          * Add the vpn-policy rt-list
    1445             :          */
    1446           0 :         struct ecommunity *old_ecom;
    1447           0 :         struct ecommunity *new_ecom;
    1448             : 
    1449             :         /* Export with the 'from' instance's export RTs. */
    1450             :         /* If doing VRF-to-VRF leaking, strip existing RTs first. */
    1451           0 :         old_ecom = bgp_attr_get_ecommunity(&static_attr);
    1452           0 :         if (old_ecom) {
    1453           0 :                 new_ecom = ecommunity_dup(old_ecom);
    1454           0 :                 if (CHECK_FLAG(from_bgp->af_flags[afi][SAFI_UNICAST],
    1455             :                                BGP_CONFIG_VRF_TO_VRF_EXPORT))
    1456           0 :                         ecommunity_strip_rts(new_ecom);
    1457           0 :                 new_ecom = ecommunity_merge(
    1458             :                         new_ecom, from_bgp->vpn_policy[afi]
    1459             :                                           .rtlist[BGP_VPN_POLICY_DIR_TOVPN]);
    1460           0 :                 if (!old_ecom->refcnt)
    1461           0 :                         ecommunity_free(&old_ecom);
    1462             :         } else {
    1463           0 :                 new_ecom = ecommunity_dup(
    1464             :                         from_bgp->vpn_policy[afi]
    1465             :                                 .rtlist[BGP_VPN_POLICY_DIR_TOVPN]);
    1466             :         }
    1467           0 :         bgp_attr_set_ecommunity(&static_attr, new_ecom);
    1468             : 
    1469           0 :         if (debug && bgp_attr_get_ecommunity(&static_attr)) {
    1470           0 :                 char *s = ecommunity_ecom2str(
    1471             :                         bgp_attr_get_ecommunity(&static_attr),
    1472             :                         ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
    1473             : 
    1474           0 :                 zlog_debug("%s: post merge static_attr.ecommunity{%s}",
    1475             :                            __func__, s);
    1476           0 :                 XFREE(MTYPE_ECOMMUNITY_STR, s);
    1477             :         }
    1478             : 
    1479           0 :         community_strip_accept_own(&static_attr);
    1480             : 
    1481             :         /* Nexthop */
    1482             :         /* if policy nexthop not set, use 0 */
    1483           0 :         if (CHECK_FLAG(from_bgp->vpn_policy[afi].flags,
    1484             :                        BGP_VPN_POLICY_TOVPN_NEXTHOP_SET)) {
    1485           0 :                 struct prefix *nexthop =
    1486             :                         &from_bgp->vpn_policy[afi].tovpn_nexthop;
    1487             : 
    1488           0 :                 switch (nexthop->family) {
    1489           0 :                 case AF_INET:
    1490             :                         /* prevent mp_nexthop_global_in <- self in bgp_route.c
    1491             :                          */
    1492           0 :                         static_attr.nexthop.s_addr = nexthop->u.prefix4.s_addr;
    1493             : 
    1494           0 :                         static_attr.mp_nexthop_global_in = nexthop->u.prefix4;
    1495           0 :                         static_attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
    1496           0 :                         break;
    1497             : 
    1498           0 :                 case AF_INET6:
    1499           0 :                         static_attr.mp_nexthop_global = nexthop->u.prefix6;
    1500           0 :                         static_attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
    1501           0 :                         break;
    1502             : 
    1503             :                 default:
    1504           0 :                         assert(0);
    1505             :                 }
    1506             :         } else {
    1507           0 :                 if (!CHECK_FLAG(from_bgp->af_flags[afi][SAFI_UNICAST],
    1508             :                                 BGP_CONFIG_VRF_TO_VRF_EXPORT)) {
    1509           0 :                         if (afi == AFI_IP &&
    1510           0 :                             !BGP_ATTR_NEXTHOP_AFI_IP6(path_vrf->attr)) {
    1511             :                                 /*
    1512             :                                  * For ipv4, copy to multiprotocol
    1513             :                                  * nexthop field
    1514             :                                  */
    1515           0 :                                 static_attr.mp_nexthop_global_in =
    1516             :                                         static_attr.nexthop;
    1517           0 :                                 static_attr.mp_nexthop_len =
    1518             :                                         BGP_ATTR_NHLEN_IPV4;
    1519             :                                 /*
    1520             :                                  * XXX Leave static_attr.nexthop
    1521             :                                  * intact for NHT
    1522             :                                  */
    1523           0 :                                 static_attr.flag &=
    1524             :                                         ~ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
    1525             :                         }
    1526             :                 } else {
    1527             :                         /* Update based on next-hop family to account for
    1528             :                          * RFC 5549 (BGP unnumbered) scenario. Note that
    1529             :                          * specific action is only needed for the case of
    1530             :                          * IPv4 nexthops as the attr has been copied
    1531             :                          * otherwise.
    1532             :                          */
    1533           0 :                         if (afi == AFI_IP
    1534           0 :                             && !BGP_ATTR_NEXTHOP_AFI_IP6(path_vrf->attr)) {
    1535           0 :                                 static_attr.mp_nexthop_global_in.s_addr =
    1536           0 :                                         static_attr.nexthop.s_addr;
    1537           0 :                                 static_attr.mp_nexthop_len =
    1538             :                                         BGP_ATTR_NHLEN_IPV4;
    1539           0 :                                 static_attr.flag |=
    1540             :                                         ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
    1541             :                         }
    1542             :                 }
    1543             :                 nexthop_self_flag = 1;
    1544             :         }
    1545             : 
    1546           0 :         label_val = from_bgp->vpn_policy[afi].tovpn_label;
    1547           0 :         if (label_val == MPLS_LABEL_NONE) {
    1548           0 :                 encode_label(MPLS_LABEL_IMPLICIT_NULL, &label);
    1549             :         } else {
    1550           0 :                 encode_label(label_val, &label);
    1551             :         }
    1552             : 
    1553             :         /* Set originator ID to "me" */
    1554           0 :         SET_FLAG(static_attr.flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID));
    1555           0 :         static_attr.originator_id = to_bgp->router_id;
    1556             : 
    1557             :         /* Set SID for SRv6 VPN */
    1558           0 :         if (from_bgp->vpn_policy[afi].tovpn_sid_locator) {
    1559           0 :                 struct srv6_locator_chunk *locator =
    1560             :                         from_bgp->vpn_policy[afi].tovpn_sid_locator;
    1561           0 :                 encode_label(
    1562             :                         from_bgp->vpn_policy[afi].tovpn_sid_transpose_label,
    1563             :                         &label);
    1564           0 :                 static_attr.srv6_l3vpn = XCALLOC(MTYPE_BGP_SRV6_L3VPN,
    1565             :                                 sizeof(struct bgp_attr_srv6_l3vpn));
    1566           0 :                 static_attr.srv6_l3vpn->sid_flags = 0x00;
    1567           0 :                 static_attr.srv6_l3vpn->endpoint_behavior =
    1568             :                         afi == AFI_IP
    1569           0 :                                 ? (CHECK_FLAG(locator->flags, SRV6_LOCATOR_USID)
    1570             :                                            ? SRV6_ENDPOINT_BEHAVIOR_END_DT4_USID
    1571             :                                            : SRV6_ENDPOINT_BEHAVIOR_END_DT4)
    1572           0 :                                 : (CHECK_FLAG(locator->flags, SRV6_LOCATOR_USID)
    1573             :                                            ? SRV6_ENDPOINT_BEHAVIOR_END_DT6_USID
    1574             :                                            : SRV6_ENDPOINT_BEHAVIOR_END_DT6);
    1575           0 :                 static_attr.srv6_l3vpn->loc_block_len =
    1576             :                         from_bgp->vpn_policy[afi]
    1577           0 :                                 .tovpn_sid_locator->block_bits_length;
    1578           0 :                 static_attr.srv6_l3vpn->loc_node_len =
    1579             :                         from_bgp->vpn_policy[afi]
    1580           0 :                                 .tovpn_sid_locator->node_bits_length;
    1581           0 :                 static_attr.srv6_l3vpn->func_len =
    1582             :                         from_bgp->vpn_policy[afi]
    1583           0 :                                 .tovpn_sid_locator->function_bits_length;
    1584           0 :                 static_attr.srv6_l3vpn->arg_len =
    1585             :                         from_bgp->vpn_policy[afi]
    1586           0 :                                 .tovpn_sid_locator->argument_bits_length;
    1587           0 :                 static_attr.srv6_l3vpn->transposition_len =
    1588             :                         from_bgp->vpn_policy[afi]
    1589             :                                 .tovpn_sid_locator->function_bits_length;
    1590           0 :                 static_attr.srv6_l3vpn->transposition_offset =
    1591             :                         from_bgp->vpn_policy[afi]
    1592           0 :                                 .tovpn_sid_locator->block_bits_length +
    1593             :                         from_bgp->vpn_policy[afi]
    1594             :                                 .tovpn_sid_locator->node_bits_length;
    1595           0 :                 ;
    1596           0 :                 memcpy(&static_attr.srv6_l3vpn->sid,
    1597             :                        &from_bgp->vpn_policy[afi]
    1598             :                                 .tovpn_sid_locator->prefix.prefix,
    1599             :                        sizeof(struct in6_addr));
    1600           0 :         } else if (from_bgp->tovpn_sid_locator) {
    1601           0 :                 struct srv6_locator_chunk *locator =
    1602             :                         from_bgp->tovpn_sid_locator;
    1603           0 :                 encode_label(from_bgp->tovpn_sid_transpose_label, &label);
    1604           0 :                 static_attr.srv6_l3vpn =
    1605           0 :                         XCALLOC(MTYPE_BGP_SRV6_L3VPN,
    1606             :                                 sizeof(struct bgp_attr_srv6_l3vpn));
    1607           0 :                 static_attr.srv6_l3vpn->sid_flags = 0x00;
    1608           0 :                 static_attr.srv6_l3vpn->endpoint_behavior =
    1609           0 :                         CHECK_FLAG(locator->flags, SRV6_LOCATOR_USID)
    1610             :                                 ? SRV6_ENDPOINT_BEHAVIOR_END_DT46_USID
    1611             :                                 : SRV6_ENDPOINT_BEHAVIOR_END_DT46;
    1612           0 :                 static_attr.srv6_l3vpn->loc_block_len =
    1613           0 :                         from_bgp->tovpn_sid_locator->block_bits_length;
    1614           0 :                 static_attr.srv6_l3vpn->loc_node_len =
    1615           0 :                         from_bgp->tovpn_sid_locator->node_bits_length;
    1616           0 :                 static_attr.srv6_l3vpn->func_len =
    1617           0 :                         from_bgp->tovpn_sid_locator->function_bits_length;
    1618           0 :                 static_attr.srv6_l3vpn->arg_len =
    1619           0 :                         from_bgp->tovpn_sid_locator->argument_bits_length;
    1620           0 :                 static_attr.srv6_l3vpn->transposition_len =
    1621             :                         from_bgp->tovpn_sid_locator->function_bits_length;
    1622           0 :                 static_attr.srv6_l3vpn->transposition_offset =
    1623           0 :                         from_bgp->tovpn_sid_locator->block_bits_length +
    1624             :                         from_bgp->tovpn_sid_locator->node_bits_length;
    1625           0 :                 memcpy(&static_attr.srv6_l3vpn->sid,
    1626             :                        &from_bgp->tovpn_sid_locator->prefix.prefix,
    1627             :                        sizeof(struct in6_addr));
    1628             :         }
    1629             : 
    1630             : 
    1631           0 :         new_attr = bgp_attr_intern(
    1632             :                 &static_attr);      /* hashed refcounted everything */
    1633           0 :         bgp_attr_flush(&static_attr); /* free locally-allocated parts */
    1634             : 
    1635           0 :         if (debug && bgp_attr_get_ecommunity(new_attr)) {
    1636           0 :                 char *s = ecommunity_ecom2str(bgp_attr_get_ecommunity(new_attr),
    1637             :                                               ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
    1638             : 
    1639           0 :                 zlog_debug("%s: new_attr->ecommunity{%s}", __func__, s);
    1640           0 :                 XFREE(MTYPE_ECOMMUNITY_STR, s);
    1641             :         }
    1642             : 
    1643             :         /* Now new_attr is an allocated interned attr */
    1644             : 
    1645           0 :         bn = bgp_afi_node_get(to_bgp->rib[afi][safi], afi, safi, p,
    1646             :                               &(from_bgp->vpn_policy[afi].tovpn_rd));
    1647             : 
    1648           0 :         struct bgp_path_info *new_info;
    1649             : 
    1650           0 :         new_info =
    1651           0 :                 leak_update(to_bgp, bn, new_attr, afi, safi, path_vrf, &label,
    1652             :                             1, from_bgp, NULL, nexthop_self_flag, debug);
    1653             : 
    1654             :         /*
    1655             :          * Routes actually installed in the vpn RIB must also be
    1656             :          * offered to all vrfs (because now they originate from
    1657             :          * the vpn RIB).
    1658             :          *
    1659             :          * Acceptance into other vrfs depends on rt-lists.
    1660             :          * Originating vrf will not accept the looped back route
    1661             :          * because of loop checking.
    1662             :          */
    1663           0 :         if (new_info)
    1664           0 :                 vpn_leak_to_vrf_update(from_bgp, new_info, NULL);
    1665             : }
    1666             : 
    1667           2 : void vpn_leak_from_vrf_withdraw(struct bgp *to_bgp,             /* to */
    1668             :                                 struct bgp *from_bgp,           /* from */
    1669             :                                 struct bgp_path_info *path_vrf) /* route */
    1670             : {
    1671           2 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
    1672           2 :         const struct prefix *p = bgp_dest_get_prefix(path_vrf->net);
    1673           2 :         afi_t afi = family2afi(p->family);
    1674           2 :         safi_t safi = SAFI_MPLS_VPN;
    1675           2 :         struct bgp_path_info *bpi;
    1676           2 :         struct bgp_dest *bn;
    1677           2 :         const char *debugmsg;
    1678             : 
    1679           2 :         if (debug) {
    1680           0 :                 zlog_debug(
    1681             :                         "%s: entry: leak-from=%s, p=%pBD, type=%d, sub_type=%d",
    1682             :                         __func__, from_bgp->name_pretty, path_vrf->net,
    1683             :                         path_vrf->type, path_vrf->sub_type);
    1684             :         }
    1685             : 
    1686           2 :         if (!to_bgp)
    1687           2 :                 return;
    1688             : 
    1689           2 :         if (!afi) {
    1690           0 :                 if (debug)
    1691           0 :                         zlog_debug("%s: can't get afi of prefix", __func__);
    1692           0 :                 return;
    1693             :         }
    1694             : 
    1695             :         /* Is this route exportable into the VPN table? */
    1696           2 :         if (!is_route_injectable_into_vpn(path_vrf))
    1697             :                 return;
    1698             : 
    1699           2 :         if (!vpn_leak_to_vpn_active(from_bgp, afi, &debugmsg)) {
    1700           2 :                 if (debug)
    1701           0 :                         zlog_debug("%s: skipping: %s", __func__, debugmsg);
    1702           2 :                 return;
    1703             :         }
    1704             : 
    1705           0 :         if (debug)
    1706           0 :                 zlog_debug("%s: withdrawing (path_vrf=%p)", __func__, path_vrf);
    1707             : 
    1708           0 :         bn = bgp_afi_node_get(to_bgp->rib[afi][safi], afi, safi, p,
    1709             :                               &(from_bgp->vpn_policy[afi].tovpn_rd));
    1710             : 
    1711           0 :         if (!bn)
    1712             :                 return;
    1713             :         /*
    1714             :          * vrf -> vpn
    1715             :          * match original bpi imported from
    1716             :          */
    1717           0 :         for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) {
    1718           0 :                 if (bpi->extra && bpi->extra->parent == path_vrf) {
    1719             :                         break;
    1720             :                 }
    1721             :         }
    1722             : 
    1723           0 :         if (bpi) {
    1724             :                 /* withdraw from looped vrfs as well */
    1725           0 :                 vpn_leak_to_vrf_withdraw(bpi);
    1726             : 
    1727           0 :                 bgp_aggregate_decrement(to_bgp, p, bpi, afi, safi);
    1728           0 :                 bgp_path_info_delete(bn, bpi);
    1729           0 :                 bgp_process(to_bgp, bn, afi, safi);
    1730             :         }
    1731           0 :         bgp_dest_unlock_node(bn);
    1732             : }
    1733             : 
    1734           0 : void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp, struct bgp *from_bgp,
    1735             :                                     afi_t afi)
    1736             : {
    1737           0 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
    1738           0 :         struct bgp_dest *pdest;
    1739           0 :         safi_t safi = SAFI_MPLS_VPN;
    1740             : 
    1741             :         /*
    1742             :          * Walk vpn table, delete bpi with bgp_orig == from_bgp
    1743             :          */
    1744           0 :         for (pdest = bgp_table_top(to_bgp->rib[afi][safi]); pdest;
    1745           0 :              pdest = bgp_route_next(pdest)) {
    1746             : 
    1747           0 :                 struct bgp_table *table;
    1748           0 :                 struct bgp_dest *bn;
    1749           0 :                 struct bgp_path_info *bpi;
    1750             : 
    1751             :                 /* This is the per-RD table of prefixes */
    1752           0 :                 table = bgp_dest_get_bgp_table_info(pdest);
    1753             : 
    1754           0 :                 if (!table)
    1755           0 :                         continue;
    1756             : 
    1757           0 :                 for (bn = bgp_table_top(table); bn; bn = bgp_route_next(bn)) {
    1758           0 :                         bpi = bgp_dest_get_bgp_path_info(bn);
    1759           0 :                         if (debug && bpi) {
    1760           0 :                                 zlog_debug("%s: looking at prefix %pBD",
    1761             :                                            __func__, bn);
    1762             :                         }
    1763             : 
    1764           0 :                         for (; bpi; bpi = bpi->next) {
    1765           0 :                                 if (debug)
    1766           0 :                                         zlog_debug("%s: type %d, sub_type %d",
    1767             :                                                    __func__, bpi->type,
    1768             :                                                    bpi->sub_type);
    1769           0 :                                 if (bpi->sub_type != BGP_ROUTE_IMPORTED)
    1770           0 :                                         continue;
    1771           0 :                                 if (!bpi->extra)
    1772           0 :                                         continue;
    1773           0 :                                 if ((struct bgp *)bpi->extra->bgp_orig ==
    1774             :                                     from_bgp) {
    1775             :                                         /* delete route */
    1776           0 :                                         if (debug)
    1777           0 :                                                 zlog_debug("%s: deleting it",
    1778             :                                                            __func__);
    1779             :                                         /* withdraw from leak-to vrfs as well */
    1780           0 :                                         vpn_leak_to_vrf_withdraw(bpi);
    1781           0 :                                         bgp_aggregate_decrement(
    1782             :                                                 to_bgp, bgp_dest_get_prefix(bn),
    1783             :                                                 bpi, afi, safi);
    1784           0 :                                         bgp_path_info_delete(bn, bpi);
    1785           0 :                                         bgp_process(to_bgp, bn, afi, safi);
    1786             :                                 }
    1787             :                         }
    1788             :                 }
    1789             :         }
    1790           0 : }
    1791             : 
    1792           0 : void vpn_leak_from_vrf_update_all(struct bgp *to_bgp, struct bgp *from_bgp,
    1793             :                                   afi_t afi)
    1794             : {
    1795           0 :         struct bgp_dest *bn;
    1796           0 :         struct bgp_path_info *bpi;
    1797           0 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
    1798             : 
    1799           0 :         if (debug)
    1800           0 :                 zlog_debug("%s: entry, afi=%d, vrf=%s", __func__, afi,
    1801             :                            from_bgp->name_pretty);
    1802             : 
    1803           0 :         for (bn = bgp_table_top(from_bgp->rib[afi][SAFI_UNICAST]); bn;
    1804           0 :              bn = bgp_route_next(bn)) {
    1805             : 
    1806           0 :                 if (debug)
    1807           0 :                         zlog_debug("%s: node=%p", __func__, bn);
    1808             : 
    1809           0 :                 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
    1810           0 :                      bpi = bpi->next) {
    1811           0 :                         if (debug)
    1812           0 :                                 zlog_debug(
    1813             :                                         "%s: calling vpn_leak_from_vrf_update",
    1814             :                                         __func__);
    1815           0 :                         vpn_leak_from_vrf_update(to_bgp, from_bgp, bpi);
    1816             :                 }
    1817             :         }
    1818           0 : }
    1819             : 
    1820           0 : static struct bgp *bgp_lookup_by_rd(struct bgp_path_info *bpi,
    1821             :                                     struct prefix_rd *rd, afi_t afi)
    1822             : {
    1823           0 :         struct listnode *node, *nnode;
    1824           0 :         struct bgp *bgp;
    1825             : 
    1826           0 :         if (!rd)
    1827             :                 return NULL;
    1828             : 
    1829             :         /* If ACCEPT_OWN is not enabled for this path - return. */
    1830           0 :         if (!CHECK_FLAG(bpi->flags, BGP_PATH_ACCEPT_OWN))
    1831             :                 return NULL;
    1832             : 
    1833           0 :         for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
    1834           0 :                 if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
    1835           0 :                         continue;
    1836             : 
    1837           0 :                 if (!CHECK_FLAG(bgp->vpn_policy[afi].flags,
    1838             :                                 BGP_VPN_POLICY_TOVPN_RD_SET))
    1839           0 :                         continue;
    1840             : 
    1841             :                 /* Check if we have source VRF by RD value */
    1842           0 :                 if (memcmp(&bgp->vpn_policy[afi].tovpn_rd.val, rd->val,
    1843             :                            ECOMMUNITY_SIZE) == 0)
    1844           0 :                         return bgp;
    1845             :         }
    1846             : 
    1847             :         return NULL;
    1848             : }
    1849             : 
    1850           0 : static bool vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp,   /* to */
    1851             :                                           struct bgp *from_bgp, /* from */
    1852             :                                           struct bgp_path_info *path_vpn,
    1853             :                                           struct prefix_rd *prd)
    1854             : {
    1855           0 :         const struct prefix *p = bgp_dest_get_prefix(path_vpn->net);
    1856           0 :         afi_t afi = family2afi(p->family);
    1857             : 
    1858           0 :         struct attr static_attr = {0};
    1859           0 :         struct attr *new_attr = NULL;
    1860           0 :         struct bgp_dest *bn;
    1861           0 :         safi_t safi = SAFI_UNICAST;
    1862           0 :         const char *debugmsg;
    1863           0 :         struct prefix nexthop_orig;
    1864           0 :         mpls_label_t *pLabels = NULL;
    1865           0 :         uint32_t num_labels = 0;
    1866           0 :         int nexthop_self_flag = 1;
    1867           0 :         struct bgp_path_info *bpi_ultimate = NULL;
    1868           0 :         int origin_local = 0;
    1869           0 :         struct bgp *src_vrf;
    1870           0 :         struct interface *ifp;
    1871             : 
    1872           0 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
    1873             : 
    1874           0 :         if (!vpn_leak_from_vpn_active(to_bgp, afi, &debugmsg)) {
    1875           0 :                 if (debug)
    1876           0 :                         zlog_debug(
    1877             :                                 "%s: from vpn (%s) to vrf (%s), skipping: %s",
    1878             :                                 __func__, from_bgp->name_pretty,
    1879             :                                 to_bgp->name_pretty, debugmsg);
    1880           0 :                 return false;
    1881             :         }
    1882             : 
    1883             :         /*
    1884             :          * For VRF-2-VRF route-leaking,
    1885             :          * the source will be the originating VRF.
    1886             :          *
    1887             :          * If ACCEPT_OWN mechanism is enabled, then we SHOULD(?)
    1888             :          * get the source VRF (BGP) by looking at the RD.
    1889             :          */
    1890           0 :         struct bgp *src_bgp = bgp_lookup_by_rd(path_vpn, prd, afi);
    1891             : 
    1892           0 :         if (path_vpn->extra && path_vpn->extra->bgp_orig)
    1893             :                 src_vrf = path_vpn->extra->bgp_orig;
    1894           0 :         else if (src_bgp)
    1895             :                 src_vrf = src_bgp;
    1896             :         else
    1897           0 :                 src_vrf = from_bgp;
    1898             : 
    1899             :         /* Check for intersection of route targets */
    1900           0 :         if (!ecommunity_include(
    1901             :                     to_bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN],
    1902           0 :                     bgp_attr_get_ecommunity(path_vpn->attr))) {
    1903           0 :                 if (debug)
    1904           0 :                         zlog_debug(
    1905             :                                 "from vpn (%s) to vrf (%s), skipping after no intersection of route targets",
    1906             :                                 from_bgp->name_pretty, to_bgp->name_pretty);
    1907           0 :                 return false;
    1908             :         }
    1909             : 
    1910             :         /* A route MUST NOT ever be accepted back into its source VRF, even if
    1911             :          * it carries one or more RTs that match that VRF.
    1912             :          */
    1913           0 :         if (CHECK_FLAG(path_vpn->flags, BGP_PATH_ACCEPT_OWN) && prd &&
    1914           0 :             memcmp(&prd->val, &to_bgp->vpn_policy[afi].tovpn_rd.val,
    1915             :                    ECOMMUNITY_SIZE) == 0) {
    1916           0 :                 if (debug)
    1917           0 :                         zlog_debug(
    1918             :                                 "%s: skipping import, match RD (%pRD) of src VRF (%s) and the prefix (%pFX)",
    1919             :                                 __func__, prd, to_bgp->name_pretty, p);
    1920             : 
    1921           0 :                 return false;
    1922             :         }
    1923             : 
    1924           0 :         if (debug)
    1925           0 :                 zlog_debug("%s: updating RD %pRD, %pFX to %s", __func__, prd, p,
    1926             :                            to_bgp->name_pretty);
    1927             : 
    1928             :         /* shallow copy */
    1929           0 :         static_attr = *path_vpn->attr;
    1930             : 
    1931           0 :         struct ecommunity *old_ecom;
    1932           0 :         struct ecommunity *new_ecom;
    1933             : 
    1934             :         /* If doing VRF-to-VRF leaking, strip RTs. */
    1935           0 :         old_ecom = bgp_attr_get_ecommunity(&static_attr);
    1936           0 :         if (old_ecom && CHECK_FLAG(to_bgp->af_flags[afi][safi],
    1937             :                                    BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
    1938           0 :                 new_ecom = ecommunity_dup(old_ecom);
    1939           0 :                 ecommunity_strip_rts(new_ecom);
    1940           0 :                 bgp_attr_set_ecommunity(&static_attr, new_ecom);
    1941             : 
    1942           0 :                 if (new_ecom->size == 0) {
    1943           0 :                         ecommunity_free(&new_ecom);
    1944           0 :                         bgp_attr_set_ecommunity(&static_attr, NULL);
    1945             :                 }
    1946             : 
    1947           0 :                 if (!old_ecom->refcnt)
    1948           0 :                         ecommunity_free(&old_ecom);
    1949             :         }
    1950             : 
    1951           0 :         community_strip_accept_own(&static_attr);
    1952             : 
    1953             :         /*
    1954             :          * Nexthop: stash and clear
    1955             :          *
    1956             :          * Nexthop is valid in context of VPN core, but not in destination vrf.
    1957             :          * Stash it for later label resolution by vrf ingress path and then
    1958             :          * overwrite with 0, i.e., "me", for the sake of vrf advertisement.
    1959             :          */
    1960           0 :         uint8_t nhfamily = NEXTHOP_FAMILY(path_vpn->attr->mp_nexthop_len);
    1961             : 
    1962           0 :         memset(&nexthop_orig, 0, sizeof(nexthop_orig));
    1963           0 :         nexthop_orig.family = nhfamily;
    1964             : 
    1965             :         /* If the path has accept-own community and the source VRF
    1966             :          * is valid, reset next-hop to self, to allow importing own
    1967             :          * routes between different VRFs on the same node.
    1968             :          * Set the nh ifindex to VRF's interface, not the real interface.
    1969             :          * Let the kernel to decide with double lookup the real next-hop
    1970             :          * interface when installing the route.
    1971             :          */
    1972           0 :         if (src_bgp) {
    1973           0 :                 subgroup_announce_reset_nhop(nhfamily, &static_attr);
    1974           0 :                 ifp = if_get_vrf_loopback(src_vrf->vrf_id);
    1975           0 :                 if (ifp)
    1976           0 :                         static_attr.nh_ifindex = ifp->ifindex;
    1977             :         }
    1978             : 
    1979           0 :         switch (nhfamily) {
    1980           0 :         case AF_INET:
    1981             :                 /* save */
    1982           0 :                 nexthop_orig.u.prefix4 = path_vpn->attr->mp_nexthop_global_in;
    1983           0 :                 nexthop_orig.prefixlen = IPV4_MAX_BITLEN;
    1984             : 
    1985           0 :                 if (CHECK_FLAG(to_bgp->af_flags[afi][safi],
    1986             :                                BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
    1987           0 :                         static_attr.nexthop.s_addr =
    1988           0 :                                 nexthop_orig.u.prefix4.s_addr;
    1989             : 
    1990           0 :                         static_attr.mp_nexthop_global_in =
    1991             :                                 path_vpn->attr->mp_nexthop_global_in;
    1992           0 :                         static_attr.mp_nexthop_len =
    1993           0 :                                 path_vpn->attr->mp_nexthop_len;
    1994             :                 }
    1995           0 :                 static_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
    1996           0 :                 break;
    1997           0 :         case AF_INET6:
    1998             :                 /* save */
    1999           0 :                 nexthop_orig.u.prefix6 = path_vpn->attr->mp_nexthop_global;
    2000           0 :                 nexthop_orig.prefixlen = IPV6_MAX_BITLEN;
    2001             : 
    2002           0 :                 if (CHECK_FLAG(to_bgp->af_flags[afi][safi],
    2003             :                                BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
    2004           0 :                         static_attr.mp_nexthop_global = nexthop_orig.u.prefix6;
    2005             :                 }
    2006             :                 break;
    2007             :         }
    2008             : 
    2009             :         /*
    2010             :          * route map handling
    2011             :          */
    2012           0 :         if (to_bgp->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_FROMVPN]) {
    2013           0 :                 struct bgp_path_info info;
    2014           0 :                 route_map_result_t ret;
    2015             : 
    2016           0 :                 memset(&info, 0, sizeof(info));
    2017           0 :                 info.peer = to_bgp->peer_self;
    2018           0 :                 info.attr = &static_attr;
    2019           0 :                 info.extra = path_vpn->extra; /* Used for source-vrf filter */
    2020           0 :                 ret = route_map_apply(to_bgp->vpn_policy[afi]
    2021             :                                               .rmap[BGP_VPN_POLICY_DIR_FROMVPN],
    2022             :                                       p, &info);
    2023           0 :                 if (RMAP_DENYMATCH == ret) {
    2024           0 :                         bgp_attr_flush(&static_attr); /* free any added parts */
    2025           0 :                         if (debug)
    2026           0 :                                 zlog_debug(
    2027             :                                         "%s: vrf %s vpn-policy route map \"%s\" says DENY, returning",
    2028             :                                         __func__, to_bgp->name_pretty,
    2029             :                                         to_bgp->vpn_policy[afi]
    2030             :                                                 .rmap[BGP_VPN_POLICY_DIR_FROMVPN]
    2031             :                                                 ->name);
    2032           0 :                         return false;
    2033             :                 }
    2034             :                 /*
    2035             :                  * if route-map changed nexthop, don't nexthop-self on output
    2036             :                  */
    2037           0 :                 if (!CHECK_FLAG(static_attr.rmap_change_flags,
    2038             :                                                 BATTR_RMAP_NEXTHOP_UNCHANGED))
    2039           0 :                         nexthop_self_flag = 0;
    2040             :         }
    2041             : 
    2042           0 :         new_attr = bgp_attr_intern(&static_attr);
    2043           0 :         bgp_attr_flush(&static_attr);
    2044             : 
    2045           0 :         bn = bgp_afi_node_get(to_bgp->rib[afi][safi], afi, safi, p, NULL);
    2046             : 
    2047             :         /*
    2048             :          * ensure labels are copied
    2049             :          *
    2050             :          * However, there is a special case: if the route originated in
    2051             :          * another local VRF (as opposed to arriving via VPN), then the
    2052             :          * nexthop is reached by hairpinning through this router (me)
    2053             :          * using IP forwarding only (no LSP). Therefore, the route
    2054             :          * imported to the VRF should not have labels attached. Note
    2055             :          * that nexthop tracking is also involved: eliminating the
    2056             :          * labels for these routes enables the non-labeled nexthops
    2057             :          * from the originating VRF to be considered valid for this route.
    2058             :          */
    2059           0 :         if (!CHECK_FLAG(to_bgp->af_flags[afi][safi],
    2060             :                         BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
    2061             :                 /* work back to original route */
    2062           0 :                 bpi_ultimate = bgp_get_imported_bpi_ultimate(path_vpn);
    2063             : 
    2064             :                 /*
    2065             :                  * if original route was unicast,
    2066             :                  * then it did not arrive over vpn
    2067             :                  */
    2068           0 :                 if (bpi_ultimate->net) {
    2069           0 :                         struct bgp_table *table;
    2070             : 
    2071           0 :                         table = bgp_dest_table(bpi_ultimate->net);
    2072           0 :                         if (table && (table->safi == SAFI_UNICAST))
    2073             :                                 origin_local = 1;
    2074             :                 }
    2075             : 
    2076             :                 /* copy labels */
    2077           0 :                 if (!origin_local && path_vpn->extra
    2078           0 :                     && path_vpn->extra->num_labels) {
    2079           0 :                         num_labels = path_vpn->extra->num_labels;
    2080           0 :                         if (num_labels > BGP_MAX_LABELS)
    2081             :                                 num_labels = BGP_MAX_LABELS;
    2082           0 :                         pLabels = path_vpn->extra->label;
    2083             :                 }
    2084             :         }
    2085             : 
    2086           0 :         if (debug)
    2087           0 :                 zlog_debug("%s: pfx %pBD: num_labels %d", __func__,
    2088             :                            path_vpn->net, num_labels);
    2089             : 
    2090           0 :         leak_update(to_bgp, bn, new_attr, afi, safi, path_vpn, pLabels,
    2091             :                     num_labels, src_vrf, &nexthop_orig, nexthop_self_flag,
    2092             :                     debug);
    2093           0 :         return true;
    2094             : }
    2095             : 
    2096           0 : bool vpn_leak_to_vrf_update(struct bgp *from_bgp,
    2097             :                             struct bgp_path_info *path_vpn,
    2098             :                             struct prefix_rd *prd)
    2099             : {
    2100           0 :         struct listnode *mnode, *mnnode;
    2101           0 :         struct bgp *bgp;
    2102           0 :         bool leak_success = false;
    2103             : 
    2104           0 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
    2105             : 
    2106           0 :         if (debug)
    2107           0 :                 zlog_debug("%s: start (path_vpn=%p)", __func__, path_vpn);
    2108             : 
    2109             :         /* Loop over VRFs */
    2110           0 :         for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
    2111             : 
    2112           0 :                 if (!path_vpn->extra
    2113           0 :                     || path_vpn->extra->bgp_orig != bgp) { /* no loop */
    2114           0 :                         leak_success |= vpn_leak_to_vrf_update_onevrf(
    2115             :                                 bgp, from_bgp, path_vpn, prd);
    2116             :                 }
    2117             :         }
    2118           0 :         return leak_success;
    2119             : }
    2120             : 
    2121           0 : void vpn_leak_to_vrf_withdraw(struct bgp_path_info *path_vpn)
    2122             : {
    2123           0 :         const struct prefix *p;
    2124           0 :         afi_t afi;
    2125           0 :         safi_t safi = SAFI_UNICAST;
    2126           0 :         struct bgp *bgp;
    2127           0 :         struct listnode *mnode, *mnnode;
    2128           0 :         struct bgp_dest *bn;
    2129           0 :         struct bgp_path_info *bpi;
    2130           0 :         const char *debugmsg;
    2131             : 
    2132           0 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
    2133             : 
    2134           0 :         if (debug)
    2135           0 :                 zlog_debug("%s: entry: p=%pBD, type=%d, sub_type=%d", __func__,
    2136             :                            path_vpn->net, path_vpn->type, path_vpn->sub_type);
    2137             : 
    2138           0 :         if (debug)
    2139           0 :                 zlog_debug("%s: start (path_vpn=%p)", __func__, path_vpn);
    2140             : 
    2141           0 :         if (!path_vpn->net) {
    2142             : #ifdef ENABLE_BGP_VNC
    2143             :                 /* BGP_ROUTE_RFP routes do not have path_vpn->net set (yet) */
    2144           0 :                 if (path_vpn->type == ZEBRA_ROUTE_BGP
    2145           0 :                     && path_vpn->sub_type == BGP_ROUTE_RFP) {
    2146             : 
    2147           0 :                         return;
    2148             :                 }
    2149             : #endif
    2150           0 :                 if (debug)
    2151           0 :                         zlog_debug(
    2152             :                                 "%s: path_vpn->net unexpectedly NULL, no prefix, bailing",
    2153             :                                 __func__);
    2154           0 :                 return;
    2155             :         }
    2156             : 
    2157           0 :         p = bgp_dest_get_prefix(path_vpn->net);
    2158           0 :         afi = family2afi(p->family);
    2159             : 
    2160             :         /* Loop over VRFs */
    2161           0 :         for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
    2162           0 :                 if (!vpn_leak_from_vpn_active(bgp, afi, &debugmsg)) {
    2163           0 :                         if (debug)
    2164           0 :                                 zlog_debug("%s: from %s, skipping: %s",
    2165             :                                            __func__, bgp->name_pretty,
    2166             :                                            debugmsg);
    2167           0 :                         continue;
    2168             :                 }
    2169             : 
    2170             :                 /* Check for intersection of route targets */
    2171           0 :                 if (!ecommunity_include(
    2172             :                             bgp->vpn_policy[afi]
    2173             :                                     .rtlist[BGP_VPN_POLICY_DIR_FROMVPN],
    2174           0 :                             bgp_attr_get_ecommunity(path_vpn->attr))) {
    2175             : 
    2176           0 :                         continue;
    2177             :                 }
    2178             : 
    2179           0 :                 if (debug)
    2180           0 :                         zlog_debug("%s: withdrawing from vrf %s", __func__,
    2181             :                                    bgp->name_pretty);
    2182             : 
    2183           0 :                 bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
    2184             : 
    2185           0 :                 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
    2186           0 :                      bpi = bpi->next) {
    2187           0 :                         if (bpi->extra
    2188           0 :                             && (struct bgp_path_info *)bpi->extra->parent
    2189             :                                        == path_vpn) {
    2190             :                                 break;
    2191             :                         }
    2192             :                 }
    2193             : 
    2194           0 :                 if (bpi) {
    2195           0 :                         if (debug)
    2196           0 :                                 zlog_debug("%s: deleting bpi %p", __func__,
    2197             :                                            bpi);
    2198           0 :                         bgp_aggregate_decrement(bgp, p, bpi, afi, safi);
    2199           0 :                         bgp_path_info_delete(bn, bpi);
    2200           0 :                         bgp_process(bgp, bn, afi, safi);
    2201             :                 }
    2202           0 :                 bgp_dest_unlock_node(bn);
    2203             :         }
    2204             : }
    2205             : 
    2206           0 : void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi)
    2207             : {
    2208           0 :         struct bgp_dest *bn;
    2209           0 :         struct bgp_path_info *bpi;
    2210           0 :         safi_t safi = SAFI_UNICAST;
    2211           0 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
    2212             : 
    2213           0 :         if (debug)
    2214           0 :                 zlog_debug("%s: entry", __func__);
    2215             :         /*
    2216             :          * Walk vrf table, delete bpi with bgp_orig in a different vrf
    2217             :          */
    2218           0 :         for (bn = bgp_table_top(to_bgp->rib[afi][safi]); bn;
    2219           0 :              bn = bgp_route_next(bn)) {
    2220             : 
    2221           0 :                 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
    2222           0 :                      bpi = bpi->next) {
    2223           0 :                         if (bpi->extra && bpi->extra->bgp_orig != to_bgp &&
    2224           0 :                             bpi->extra->parent &&
    2225           0 :                             is_pi_family_vpn(bpi->extra->parent)) {
    2226             : 
    2227             :                                 /* delete route */
    2228           0 :                                 bgp_aggregate_decrement(to_bgp,
    2229             :                                                         bgp_dest_get_prefix(bn),
    2230             :                                                         bpi, afi, safi);
    2231           0 :                                 bgp_path_info_delete(bn, bpi);
    2232           0 :                                 bgp_process(to_bgp, bn, afi, safi);
    2233             :                         }
    2234             :                 }
    2235             :         }
    2236           0 : }
    2237             : 
    2238           0 : void vpn_leak_to_vrf_update_all(struct bgp *to_bgp, struct bgp *vpn_from,
    2239             :                                 afi_t afi)
    2240             : {
    2241           0 :         struct bgp_dest *pdest;
    2242           0 :         safi_t safi = SAFI_MPLS_VPN;
    2243             : 
    2244           0 :         assert(vpn_from);
    2245             : 
    2246             :         /*
    2247             :          * Walk vpn table
    2248             :          */
    2249           0 :         for (pdest = bgp_table_top(vpn_from->rib[afi][safi]); pdest;
    2250           0 :              pdest = bgp_route_next(pdest)) {
    2251           0 :                 struct bgp_table *table;
    2252           0 :                 struct bgp_dest *bn;
    2253           0 :                 struct bgp_path_info *bpi;
    2254             : 
    2255             :                 /* This is the per-RD table of prefixes */
    2256           0 :                 table = bgp_dest_get_bgp_table_info(pdest);
    2257             : 
    2258           0 :                 if (!table)
    2259           0 :                         continue;
    2260             : 
    2261           0 :                 for (bn = bgp_table_top(table); bn; bn = bgp_route_next(bn)) {
    2262             : 
    2263           0 :                         for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
    2264           0 :                              bpi = bpi->next) {
    2265             : 
    2266           0 :                                 if (bpi->extra &&
    2267           0 :                                     bpi->extra->bgp_orig == to_bgp)
    2268           0 :                                         continue;
    2269             : 
    2270           0 :                                 vpn_leak_to_vrf_update_onevrf(to_bgp, vpn_from,
    2271             :                                                               bpi, NULL);
    2272             :                         }
    2273             :                 }
    2274             :         }
    2275           0 : }
    2276             : 
    2277             : /*
    2278             :  * This function is called for definition/deletion/change to a route-map
    2279             :  */
    2280           0 : static void vpn_policy_routemap_update(struct bgp *bgp, const char *rmap_name)
    2281             : {
    2282           0 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_RMAP_EVENT);
    2283           0 :         afi_t afi;
    2284           0 :         struct route_map *rmap;
    2285             : 
    2286           0 :         if (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT
    2287             :             && bgp->inst_type != BGP_INSTANCE_TYPE_VRF) {
    2288             : 
    2289             :                 return;
    2290             :         }
    2291             : 
    2292           0 :         rmap = route_map_lookup_by_name(rmap_name); /* NULL if deleted */
    2293             : 
    2294           0 :         for (afi = 0; afi < AFI_MAX; ++afi) {
    2295             : 
    2296           0 :                 if (bgp->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_TOVPN]
    2297           0 :                         && !strcmp(rmap_name,
    2298             :                                bgp->vpn_policy[afi]
    2299             :                                        .rmap_name[BGP_VPN_POLICY_DIR_TOVPN])) {
    2300             : 
    2301           0 :                         if (debug)
    2302           0 :                                 zlog_debug(
    2303             :                                         "%s: rmap \"%s\" matches vrf-policy tovpn for as %d afi %s",
    2304             :                                         __func__, rmap_name, bgp->as,
    2305             :                                         afi2str(afi));
    2306             : 
    2307           0 :                         vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
    2308             :                                            bgp_get_default(), bgp);
    2309           0 :                         if (debug)
    2310           0 :                                 zlog_debug("%s: after vpn_leak_prechange",
    2311             :                                            __func__);
    2312             : 
    2313             :                         /* in case of definition/deletion */
    2314           0 :                         bgp->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_TOVPN] =
    2315             :                                 rmap;
    2316             : 
    2317           0 :                         vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
    2318             :                                             bgp_get_default(), bgp);
    2319             : 
    2320           0 :                         if (debug)
    2321           0 :                                 zlog_debug("%s: after vpn_leak_postchange",
    2322             :                                            __func__);
    2323             :                 }
    2324             : 
    2325           0 :                 if (bgp->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_FROMVPN]
    2326           0 :                         && !strcmp(rmap_name,
    2327             :                                 bgp->vpn_policy[afi]
    2328             :                                 .rmap_name[BGP_VPN_POLICY_DIR_FROMVPN]))  {
    2329             : 
    2330           0 :                         if (debug) {
    2331           0 :                                 zlog_debug("%s: rmap \"%s\" matches vrf-policy fromvpn for as %d afi %s",
    2332             :                                         __func__, rmap_name, bgp->as,
    2333             :                                         afi2str(afi));
    2334             :                         }
    2335             : 
    2336           0 :                         vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, afi,
    2337             :                                            bgp_get_default(), bgp);
    2338             : 
    2339             :                         /* in case of definition/deletion */
    2340           0 :                         bgp->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_FROMVPN] =
    2341             :                                         rmap;
    2342             : 
    2343           0 :                         vpn_leak_postchange(BGP_VPN_POLICY_DIR_FROMVPN, afi,
    2344             :                                             bgp_get_default(), bgp);
    2345             :                 }
    2346             :         }
    2347             : }
    2348             : 
    2349             : /* This API is used during router-id change, reflect VPNs
    2350             :  * auto RD and RT values and readvertise routes to VPN table.
    2351             :  */
    2352           4 : void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw,
    2353             :                                  bool is_config)
    2354             : {
    2355           4 :         afi_t afi;
    2356           4 :         int debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF)
    2357           4 :                      | BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
    2358           4 :         char *vname;
    2359           4 :         const char *export_name;
    2360           4 :         char buf[RD_ADDRSTRLEN];
    2361           4 :         struct bgp *bgp_import;
    2362           4 :         struct listnode *node;
    2363           4 :         struct ecommunity *ecom;
    2364           4 :         enum vpn_policy_direction idir, edir;
    2365             : 
    2366             :         /*
    2367             :          * Router-id change that is not explicitly configured
    2368             :          * (a change from zebra, frr restart for example)
    2369             :          * should not replace a configured vpn RD/RT.
    2370             :          */
    2371           4 :         if (!is_config) {
    2372           0 :                 if (debug)
    2373           0 :                         zlog_debug("%s: skipping non explicit router-id change",
    2374             :                                    __func__);
    2375           0 :                 return;
    2376             :         }
    2377             : 
    2378           4 :         if (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT
    2379             :             && bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
    2380             :                 return;
    2381             : 
    2382           4 :         export_name = bgp->name ? bgp->name : VRF_DEFAULT_NAME;
    2383           4 :         idir = BGP_VPN_POLICY_DIR_FROMVPN;
    2384           4 :         edir = BGP_VPN_POLICY_DIR_TOVPN;
    2385             : 
    2386          20 :         for (afi = 0; afi < AFI_MAX; ++afi) {
    2387          16 :                 if (!vpn_leak_to_vpn_active(bgp, afi, NULL))
    2388          16 :                         continue;
    2389             : 
    2390           0 :                 if (withdraw) {
    2391           0 :                         vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN,
    2392             :                                            afi, bgp_get_default(), bgp);
    2393           0 :                         if (debug)
    2394           0 :                                 zlog_debug("%s: %s after to_vpn vpn_leak_prechange",
    2395             :                                            __func__, export_name);
    2396             : 
    2397             :                         /* Remove import RT from VRFs */
    2398           0 :                         ecom = bgp->vpn_policy[afi].rtlist[edir];
    2399           0 :                         for (ALL_LIST_ELEMENTS_RO(bgp->vpn_policy[afi].
    2400             :                                                   export_vrf, node, vname)) {
    2401           0 :                                 if (strcmp(vname, VRF_DEFAULT_NAME) == 0)
    2402           0 :                                         bgp_import = bgp_get_default();
    2403             :                                 else
    2404           0 :                                         bgp_import = bgp_lookup_by_name(vname);
    2405           0 :                                 if (!bgp_import)
    2406           0 :                                         continue;
    2407             : 
    2408           0 :                                 ecommunity_del_val(
    2409             :                                         bgp_import->vpn_policy[afi]
    2410             :                                                 .rtlist[idir],
    2411           0 :                                         (struct ecommunity_val *)ecom->val);
    2412             :                         }
    2413             :                 } else {
    2414             :                         /* New router-id derive auto RD and RT and export
    2415             :                          * to VPN
    2416             :                          */
    2417           0 :                         form_auto_rd(bgp->router_id, bgp->vrf_rd_id,
    2418             :                                      &bgp->vrf_prd_auto);
    2419           0 :                         bgp->vpn_policy[afi].tovpn_rd = bgp->vrf_prd_auto;
    2420           0 :                         prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd, buf,
    2421             :                                       sizeof(buf));
    2422             : 
    2423             :                         /* free up pre-existing memory if any and allocate
    2424             :                          *  the ecommunity attribute with new RD/RT
    2425             :                          */
    2426           0 :                         if (bgp->vpn_policy[afi].rtlist[edir])
    2427           0 :                                 ecommunity_free(
    2428             :                                         &bgp->vpn_policy[afi].rtlist[edir]);
    2429           0 :                         bgp->vpn_policy[afi].rtlist[edir] = ecommunity_str2com(
    2430             :                                 buf, ECOMMUNITY_ROUTE_TARGET, 0);
    2431             : 
    2432             :                         /* Update import_vrf rt_list */
    2433           0 :                         ecom = bgp->vpn_policy[afi].rtlist[edir];
    2434           0 :                         for (ALL_LIST_ELEMENTS_RO(bgp->vpn_policy[afi].
    2435             :                                                   export_vrf, node, vname)) {
    2436           0 :                                 if (strcmp(vname, VRF_DEFAULT_NAME) == 0)
    2437           0 :                                         bgp_import = bgp_get_default();
    2438             :                                 else
    2439           0 :                                         bgp_import = bgp_lookup_by_name(vname);
    2440           0 :                                 if (!bgp_import)
    2441           0 :                                         continue;
    2442           0 :                                 if (bgp_import->vpn_policy[afi].rtlist[idir])
    2443           0 :                                         bgp_import->vpn_policy[afi].rtlist[idir]
    2444           0 :                                                 = ecommunity_merge(
    2445             :                                                 bgp_import->vpn_policy[afi]
    2446             :                                                 .rtlist[idir], ecom);
    2447             :                                 else
    2448           0 :                                         bgp_import->vpn_policy[afi].rtlist[idir]
    2449           0 :                                                 = ecommunity_dup(ecom);
    2450             :                         }
    2451             : 
    2452             :                         /* Update routes to VPN */
    2453           0 :                         vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN,
    2454             :                                             afi, bgp_get_default(),
    2455             :                                             bgp);
    2456           0 :                         if (debug)
    2457          16 :                                 zlog_debug("%s: %s after to_vpn vpn_leak_postchange",
    2458             :                                            __func__, export_name);
    2459             :                 }
    2460             :         }
    2461             : }
    2462             : 
    2463           0 : void vpn_policy_routemap_event(const char *rmap_name)
    2464             : {
    2465           0 :         int debug = BGP_DEBUG(vpn, VPN_LEAK_RMAP_EVENT);
    2466           0 :         struct listnode *mnode, *mnnode;
    2467           0 :         struct bgp *bgp;
    2468             : 
    2469           0 :         if (debug)
    2470           0 :                 zlog_debug("%s: entry", __func__);
    2471             : 
    2472           0 :         if (bm->bgp == NULL) /* may be called during cleanup */
    2473             :                 return;
    2474             : 
    2475           0 :         for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp))
    2476           0 :                 vpn_policy_routemap_update(bgp, rmap_name);
    2477             : }
    2478             : 
    2479           0 : void vrf_import_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
    2480             :                          afi_t afi, safi_t safi)
    2481             : {
    2482           0 :         const char *export_name;
    2483           0 :         enum vpn_policy_direction idir, edir;
    2484           0 :         char *vname, *tmp_name;
    2485           0 :         char buf[RD_ADDRSTRLEN];
    2486           0 :         struct ecommunity *ecom;
    2487           0 :         bool first_export = false;
    2488           0 :         int debug;
    2489           0 :         struct listnode *node;
    2490           0 :         bool is_inst_match = false;
    2491             : 
    2492           0 :         export_name = to_bgp->name ? to_bgp->name : VRF_DEFAULT_NAME;
    2493           0 :         idir = BGP_VPN_POLICY_DIR_FROMVPN;
    2494           0 :         edir = BGP_VPN_POLICY_DIR_TOVPN;
    2495             : 
    2496           0 :         debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) |
    2497             :                      BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
    2498             : 
    2499             :         /*
    2500             :          * Cross-ref both VRFs. Also, note if this is the first time
    2501             :          * any VRF is importing from "import_vrf".
    2502             :          */
    2503           0 :         vname = (from_bgp->name ? XSTRDUP(MTYPE_TMP, from_bgp->name)
    2504           0 :                                : XSTRDUP(MTYPE_TMP, VRF_DEFAULT_NAME));
    2505             : 
    2506             :         /* Check the import_vrf list of destination vrf for the source vrf name,
    2507             :          * insert otherwise.
    2508             :          */
    2509           0 :         for (ALL_LIST_ELEMENTS_RO(to_bgp->vpn_policy[afi].import_vrf,
    2510             :                                   node, tmp_name)) {
    2511           0 :                 if (strcmp(vname, tmp_name) == 0) {
    2512             :                         is_inst_match = true;
    2513             :                         break;
    2514             :                 }
    2515             :         }
    2516           0 :         if (!is_inst_match)
    2517           0 :                 listnode_add(to_bgp->vpn_policy[afi].import_vrf,
    2518             :                                      vname);
    2519             :         else
    2520           0 :                 XFREE(MTYPE_TMP, vname);
    2521             : 
    2522             :         /* Check if the source vrf already exports to any vrf,
    2523             :          * first time export requires to setup auto derived RD/RT values.
    2524             :          * Add the destination vrf name to export vrf list if it is
    2525             :          * not present.
    2526             :          */
    2527           0 :         is_inst_match = false;
    2528           0 :         vname = XSTRDUP(MTYPE_TMP, export_name);
    2529           0 :         if (!listcount(from_bgp->vpn_policy[afi].export_vrf)) {
    2530             :                 first_export = true;
    2531             :         } else {
    2532           0 :                 for (ALL_LIST_ELEMENTS_RO(from_bgp->vpn_policy[afi].export_vrf,
    2533             :                                           node, tmp_name)) {
    2534           0 :                         if (strcmp(vname, tmp_name) == 0) {
    2535             :                                 is_inst_match = true;
    2536             :                                 break;
    2537             :                         }
    2538             :                 }
    2539             :         }
    2540           0 :         if (!is_inst_match)
    2541           0 :                 listnode_add(from_bgp->vpn_policy[afi].export_vrf,
    2542             :                              vname);
    2543             :         else
    2544           0 :                 XFREE(MTYPE_TMP, vname);
    2545             : 
    2546             :         /* Update import RT for current VRF using export RT of the VRF we're
    2547             :          * importing from. First though, make sure "import_vrf" has that
    2548             :          * set.
    2549             :          */
    2550           0 :         if (first_export) {
    2551           0 :                 form_auto_rd(from_bgp->router_id, from_bgp->vrf_rd_id,
    2552             :                              &from_bgp->vrf_prd_auto);
    2553           0 :                 from_bgp->vpn_policy[afi].tovpn_rd = from_bgp->vrf_prd_auto;
    2554           0 :                 SET_FLAG(from_bgp->vpn_policy[afi].flags,
    2555             :                          BGP_VPN_POLICY_TOVPN_RD_SET);
    2556           0 :                 prefix_rd2str(&from_bgp->vpn_policy[afi].tovpn_rd,
    2557             :                               buf, sizeof(buf));
    2558           0 :                 from_bgp->vpn_policy[afi].rtlist[edir] =
    2559           0 :                         ecommunity_str2com(buf, ECOMMUNITY_ROUTE_TARGET, 0);
    2560           0 :                 SET_FLAG(from_bgp->af_flags[afi][safi],
    2561             :                          BGP_CONFIG_VRF_TO_VRF_EXPORT);
    2562           0 :                 from_bgp->vpn_policy[afi].tovpn_label =
    2563             :                         BGP_PREVENT_VRF_2_VRF_LEAK;
    2564             :         }
    2565           0 :         ecom = from_bgp->vpn_policy[afi].rtlist[edir];
    2566           0 :         if (to_bgp->vpn_policy[afi].rtlist[idir])
    2567           0 :                 to_bgp->vpn_policy[afi].rtlist[idir] =
    2568           0 :                         ecommunity_merge(to_bgp->vpn_policy[afi]
    2569             :                                          .rtlist[idir], ecom);
    2570             :         else
    2571           0 :                 to_bgp->vpn_policy[afi].rtlist[idir] = ecommunity_dup(ecom);
    2572           0 :         SET_FLAG(to_bgp->af_flags[afi][safi], BGP_CONFIG_VRF_TO_VRF_IMPORT);
    2573             : 
    2574           0 :         if (debug) {
    2575           0 :                 const char *from_name;
    2576           0 :                 char *ecom1, *ecom2;
    2577             : 
    2578           0 :                 from_name = from_bgp->name ? from_bgp->name :
    2579           0 :                         VRF_DEFAULT_NAME;
    2580             : 
    2581           0 :                 ecom1 = ecommunity_ecom2str(
    2582             :                         to_bgp->vpn_policy[afi].rtlist[idir],
    2583             :                         ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
    2584             : 
    2585           0 :                 ecom2 = ecommunity_ecom2str(
    2586             :                         to_bgp->vpn_policy[afi].rtlist[edir],
    2587             :                         ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
    2588             : 
    2589           0 :                 zlog_debug(
    2590             :                         "%s from %s to %s first_export %u import-rt %s export-rt %s",
    2591             :                         __func__, from_name, export_name, first_export, ecom1,
    2592             :                         ecom2);
    2593             : 
    2594           0 :                 ecommunity_strfree(&ecom1);
    2595           0 :                 ecommunity_strfree(&ecom2);
    2596             :         }
    2597             : 
    2598             :         /* Does "import_vrf" first need to export its routes or that
    2599             :          * is already done and we just need to import those routes
    2600             :          * from the global table?
    2601             :          */
    2602           0 :         if (first_export)
    2603           0 :                 vpn_leak_postchange(edir, afi, bgp_get_default(), from_bgp);
    2604             :         else
    2605           0 :                 vpn_leak_postchange(idir, afi, bgp_get_default(), to_bgp);
    2606           0 : }
    2607             : 
    2608           0 : void vrf_unimport_from_vrf(struct bgp *to_bgp, struct bgp *from_bgp,
    2609             :                            afi_t afi, safi_t safi)
    2610             : {
    2611           0 :         const char *export_name, *tmp_name;
    2612           0 :         enum vpn_policy_direction idir, edir;
    2613           0 :         char *vname;
    2614           0 :         struct ecommunity *ecom = NULL;
    2615           0 :         struct listnode *node;
    2616           0 :         int debug;
    2617             : 
    2618           0 :         export_name = to_bgp->name ? to_bgp->name : VRF_DEFAULT_NAME;
    2619           0 :         tmp_name = from_bgp->name ? from_bgp->name : VRF_DEFAULT_NAME;
    2620           0 :         idir = BGP_VPN_POLICY_DIR_FROMVPN;
    2621           0 :         edir = BGP_VPN_POLICY_DIR_TOVPN;
    2622             : 
    2623           0 :         debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) |
    2624             :                      BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
    2625             : 
    2626             :         /* Were we importing from "import_vrf"? */
    2627           0 :         for (ALL_LIST_ELEMENTS_RO(to_bgp->vpn_policy[afi].import_vrf, node,
    2628             :                                   vname)) {
    2629           0 :                 if (strcmp(vname, tmp_name) == 0)
    2630             :                         break;
    2631             :         }
    2632             : 
    2633             :         /*
    2634             :          * We do not check in the cli if the passed in bgp
    2635             :          * instance is actually imported into us before
    2636             :          * we call this function.  As such if we do not
    2637             :          * find this in the import_vrf list than
    2638             :          * we just need to return safely.
    2639             :          */
    2640           0 :         if (!vname)
    2641             :                 return;
    2642             : 
    2643           0 :         if (debug)
    2644           0 :                 zlog_debug("%s from %s to %s", __func__, tmp_name, export_name);
    2645             : 
    2646             :         /* Remove "import_vrf" from our import list. */
    2647           0 :         listnode_delete(to_bgp->vpn_policy[afi].import_vrf, vname);
    2648           0 :         XFREE(MTYPE_TMP, vname);
    2649             : 
    2650             :         /* Remove routes imported from "import_vrf". */
    2651             :         /* TODO: In the current logic, we have to first remove all
    2652             :          * imported routes and then (if needed) import back routes
    2653             :          */
    2654           0 :         vpn_leak_prechange(idir, afi, bgp_get_default(), to_bgp);
    2655             : 
    2656           0 :         if (to_bgp->vpn_policy[afi].import_vrf->count == 0) {
    2657           0 :                 if (!to_bgp->vpn_policy[afi].rmap[idir])
    2658           0 :                         UNSET_FLAG(to_bgp->af_flags[afi][safi],
    2659             :                                    BGP_CONFIG_VRF_TO_VRF_IMPORT);
    2660           0 :                 if (to_bgp->vpn_policy[afi].rtlist[idir])
    2661           0 :                         ecommunity_free(&to_bgp->vpn_policy[afi].rtlist[idir]);
    2662             :         } else {
    2663           0 :                 ecom = from_bgp->vpn_policy[afi].rtlist[edir];
    2664           0 :                 if (ecom)
    2665           0 :                         ecommunity_del_val(to_bgp->vpn_policy[afi].rtlist[idir],
    2666           0 :                                    (struct ecommunity_val *)ecom->val);
    2667           0 :                 vpn_leak_postchange(idir, afi, bgp_get_default(), to_bgp);
    2668             :         }
    2669             : 
    2670             :         /*
    2671             :          * What?
    2672             :          * So SA is assuming that since the ALL_LIST_ELEMENTS_RO
    2673             :          * below is checking for NULL that export_vrf can be
    2674             :          * NULL, consequently it is complaining( like a cabbage )
    2675             :          * that we could dereference and crash in the listcount(..)
    2676             :          * check below.
    2677             :          * So make it happy, under protest, with liberty and justice
    2678             :          * for all.
    2679             :          */
    2680           0 :         assert(from_bgp->vpn_policy[afi].export_vrf);
    2681             : 
    2682             :         /* Remove us from "import_vrf's" export list. If no other VRF
    2683             :          * is importing from "import_vrf", cleanup appropriately.
    2684             :          */
    2685           0 :         for (ALL_LIST_ELEMENTS_RO(from_bgp->vpn_policy[afi].export_vrf,
    2686             :                                   node, vname)) {
    2687           0 :                 if (strcmp(vname, export_name) == 0)
    2688             :                         break;
    2689             :         }
    2690             : 
    2691             :         /*
    2692             :          * If we have gotten to this point then the vname must
    2693             :          * exist.  If not, we are in a world of trouble and
    2694             :          * have slag sitting around.
    2695             :          *
    2696             :          * import_vrf and export_vrf must match in having
    2697             :          * the in/out names as appropriate.
    2698             :          * export_vrf list could have been cleaned up
    2699             :          * as part of no router bgp source instnace.
    2700             :          */
    2701           0 :         if (!vname)
    2702             :                 return;
    2703             : 
    2704           0 :         listnode_delete(from_bgp->vpn_policy[afi].export_vrf, vname);
    2705           0 :         XFREE(MTYPE_TMP, vname);
    2706             : 
    2707           0 :         if (!listcount(from_bgp->vpn_policy[afi].export_vrf)) {
    2708           0 :                 vpn_leak_prechange(edir, afi, bgp_get_default(), from_bgp);
    2709           0 :                 ecommunity_free(&from_bgp->vpn_policy[afi].rtlist[edir]);
    2710           0 :                 UNSET_FLAG(from_bgp->af_flags[afi][safi],
    2711             :                            BGP_CONFIG_VRF_TO_VRF_EXPORT);
    2712           0 :                 memset(&from_bgp->vpn_policy[afi].tovpn_rd, 0,
    2713             :                        sizeof(struct prefix_rd));
    2714           0 :                 UNSET_FLAG(from_bgp->vpn_policy[afi].flags,
    2715             :                            BGP_VPN_POLICY_TOVPN_RD_SET);
    2716           0 :                 from_bgp->vpn_policy[afi].tovpn_label = MPLS_LABEL_NONE;
    2717             : 
    2718             :         }
    2719             : }
    2720             : 
    2721             : /* For testing purpose, static route of MPLS-VPN. */
    2722           0 : DEFUN (vpnv4_network,
    2723             :        vpnv4_network_cmd,
    2724             :        "network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)",
    2725             :        "Specify a network to announce via BGP\n"
    2726             :        "IPv4 prefix\n"
    2727             :        "Specify Route Distinguisher\n"
    2728             :        "VPN Route Distinguisher\n"
    2729             :        "VPN NLRI label (tag)\n"
    2730             :        "VPN NLRI label (tag)\n"
    2731             :        "Label value\n")
    2732             : {
    2733           0 :         int idx_ipv4_prefixlen = 1;
    2734           0 :         int idx_ext_community = 3;
    2735           0 :         int idx_label = 5;
    2736           0 :         return bgp_static_set_safi(
    2737           0 :                 AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg,
    2738           0 :                 argv[idx_ext_community]->arg, argv[idx_label]->arg, NULL, 0,
    2739             :                 NULL, NULL, NULL, NULL);
    2740             : }
    2741             : 
    2742           0 : DEFUN (vpnv4_network_route_map,
    2743             :        vpnv4_network_route_map_cmd,
    2744             :        "network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575) route-map RMAP_NAME",
    2745             :        "Specify a network to announce via BGP\n"
    2746             :        "IPv4 prefix\n"
    2747             :        "Specify Route Distinguisher\n"
    2748             :        "VPN Route Distinguisher\n"
    2749             :        "VPN NLRI label (tag)\n"
    2750             :        "VPN NLRI label (tag)\n"
    2751             :        "Label value\n"
    2752             :        "route map\n"
    2753             :        "route map name\n")
    2754             : {
    2755           0 :         int idx_ipv4_prefixlen = 1;
    2756           0 :         int idx_ext_community = 3;
    2757           0 :         int idx_label = 5;
    2758           0 :         int idx_word_2 = 7;
    2759           0 :         return bgp_static_set_safi(
    2760           0 :                 AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg,
    2761           0 :                 argv[idx_ext_community]->arg, argv[idx_label]->arg,
    2762           0 :                 argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL);
    2763             : }
    2764             : 
    2765             : /* For testing purpose, static route of MPLS-VPN. */
    2766           0 : DEFUN (no_vpnv4_network,
    2767             :        no_vpnv4_network_cmd,
    2768             :        "no network A.B.C.D/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)",
    2769             :        NO_STR
    2770             :        "Specify a network to announce via BGP\n"
    2771             :        "IPv4 prefix\n"
    2772             :        "Specify Route Distinguisher\n"
    2773             :        "VPN Route Distinguisher\n"
    2774             :        "VPN NLRI label (tag)\n"
    2775             :        "VPN NLRI label (tag)\n"
    2776             :        "Label value\n")
    2777             : {
    2778           0 :         int idx_ipv4_prefixlen = 2;
    2779           0 :         int idx_ext_community = 4;
    2780           0 :         int idx_label = 6;
    2781           0 :         return bgp_static_unset_safi(AFI_IP, SAFI_MPLS_VPN, vty,
    2782           0 :                                      argv[idx_ipv4_prefixlen]->arg,
    2783           0 :                                      argv[idx_ext_community]->arg,
    2784           0 :                                      argv[idx_label]->arg, 0, NULL, NULL, NULL);
    2785             : }
    2786             : 
    2787           0 : DEFUN (vpnv6_network,
    2788             :        vpnv6_network_cmd,
    2789             :        "network X:X::X:X/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575) [route-map RMAP_NAME]",
    2790             :        "Specify a network to announce via BGP\n"
    2791             :        "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
    2792             :        "Specify Route Distinguisher\n"
    2793             :        "VPN Route Distinguisher\n"
    2794             :        "VPN NLRI label (tag)\n"
    2795             :        "VPN NLRI label (tag)\n"
    2796             :        "Label value\n"
    2797             :        "route map\n"
    2798             :        "route map name\n")
    2799             : {
    2800           0 :         int idx_ipv6_prefix = 1;
    2801           0 :         int idx_ext_community = 3;
    2802           0 :         int idx_label = 5;
    2803           0 :         int idx_word_2 = 7;
    2804           0 :         if (argc == 8)
    2805           0 :                 return bgp_static_set_safi(
    2806           0 :                         AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg,
    2807           0 :                         argv[idx_ext_community]->arg, argv[idx_label]->arg,
    2808           0 :                         argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL);
    2809             :         else
    2810           0 :                 return bgp_static_set_safi(
    2811           0 :                         AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg,
    2812           0 :                         argv[idx_ext_community]->arg, argv[idx_label]->arg,
    2813             :                         NULL, 0, NULL, NULL, NULL, NULL);
    2814             : }
    2815             : 
    2816             : /* For testing purpose, static route of MPLS-VPN. */
    2817           0 : DEFUN (no_vpnv6_network,
    2818             :        no_vpnv6_network_cmd,
    2819             :        "no network X:X::X:X/M rd ASN:NN_OR_IP-ADDRESS:NN <tag|label> (0-1048575)",
    2820             :        NO_STR
    2821             :        "Specify a network to announce via BGP\n"
    2822             :        "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
    2823             :        "Specify Route Distinguisher\n"
    2824             :        "VPN Route Distinguisher\n"
    2825             :        "VPN NLRI label (tag)\n"
    2826             :        "VPN NLRI label (tag)\n"
    2827             :        "Label value\n")
    2828             : {
    2829           0 :         int idx_ipv6_prefix = 2;
    2830           0 :         int idx_ext_community = 4;
    2831           0 :         int idx_label = 6;
    2832           0 :         return bgp_static_unset_safi(AFI_IP6, SAFI_MPLS_VPN, vty,
    2833           0 :                                      argv[idx_ipv6_prefix]->arg,
    2834           0 :                                      argv[idx_ext_community]->arg,
    2835           0 :                                      argv[idx_label]->arg, 0, NULL, NULL, NULL);
    2836             : }
    2837             : 
    2838           0 : int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd,
    2839             :                       enum bgp_show_type type, void *output_arg, int tags,
    2840             :                       bool use_json)
    2841             : {
    2842           0 :         struct bgp *bgp;
    2843           0 :         struct bgp_table *table;
    2844           0 :         uint16_t show_flags = 0;
    2845             : 
    2846           0 :         if (use_json)
    2847           0 :                 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
    2848             : 
    2849           0 :         bgp = bgp_get_default();
    2850           0 :         if (bgp == NULL) {
    2851           0 :                 if (!use_json)
    2852           0 :                         vty_out(vty, "No BGP process is configured\n");
    2853             :                 else
    2854           0 :                         vty_out(vty, "{}\n");
    2855           0 :                 return CMD_WARNING;
    2856             :         }
    2857           0 :         table = bgp->rib[afi][SAFI_MPLS_VPN];
    2858           0 :         return bgp_show_table_rd(vty, bgp, SAFI_MPLS_VPN, table, prd, type,
    2859             :                                  output_arg, show_flags);
    2860             : }
    2861             : 
    2862           0 : DEFUN (show_bgp_ip_vpn_all_rd,
    2863             :        show_bgp_ip_vpn_all_rd_cmd,
    2864             :        "show bgp "BGP_AFI_CMD_STR" vpn all [rd <ASN:NN_OR_IP-ADDRESS:NN|all>] [json]",
    2865             :        SHOW_STR
    2866             :        BGP_STR
    2867             :        BGP_VPNVX_HELP_STR
    2868             :        "Display VPN NLRI specific information\n"
    2869             :        "Display VPN NLRI specific information\n"
    2870             :        "Display information for a route distinguisher\n"
    2871             :        "VPN Route Distinguisher\n"
    2872             :        "All VPN Route Distinguishers\n"
    2873             :        JSON_STR)
    2874             : {
    2875           0 :         int ret;
    2876           0 :         struct prefix_rd prd;
    2877           0 :         afi_t afi;
    2878           0 :         int idx = 0;
    2879             : 
    2880           0 :         if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
    2881             :                 /* Constrain search if user supplies RD && RD != "all" */
    2882           0 :                 if (argv_find(argv, argc, "rd", &idx)
    2883           0 :                     && strcmp(argv[idx + 1]->arg, "all")) {
    2884           0 :                         ret = str2prefix_rd(argv[idx + 1]->arg, &prd);
    2885           0 :                         if (!ret) {
    2886           0 :                                 vty_out(vty,
    2887             :                                         "%% Malformed Route Distinguisher\n");
    2888           0 :                                 return CMD_WARNING;
    2889             :                         }
    2890           0 :                         return bgp_show_mpls_vpn(vty, afi, &prd,
    2891             :                                                  bgp_show_type_normal, NULL, 0,
    2892           0 :                                                  use_json(argc, argv));
    2893             :                 } else {
    2894           0 :                         return bgp_show_mpls_vpn(vty, afi, NULL,
    2895             :                                                  bgp_show_type_normal, NULL, 0,
    2896           0 :                                                  use_json(argc, argv));
    2897             :                 }
    2898             :         }
    2899             :         return CMD_SUCCESS;
    2900             : }
    2901             : 
    2902             : ALIAS(show_bgp_ip_vpn_all_rd,
    2903             :       show_bgp_ip_vpn_rd_cmd,
    2904             :        "show bgp "BGP_AFI_CMD_STR" vpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> [json]",
    2905             :        SHOW_STR
    2906             :        BGP_STR
    2907             :        BGP_VPNVX_HELP_STR
    2908             :        "Display VPN NLRI specific information\n"
    2909             :        "Display information for a route distinguisher\n"
    2910             :        "VPN Route Distinguisher\n"
    2911             :        "All VPN Route Distinguishers\n"
    2912             :        JSON_STR)
    2913             : 
    2914             : #ifdef KEEP_OLD_VPN_COMMANDS
    2915             : DEFUN (show_ip_bgp_vpn_rd,
    2916             :        show_ip_bgp_vpn_rd_cmd,
    2917             :        "show ip bgp "BGP_AFI_CMD_STR" vpn rd <ASN:NN_OR_IP-ADDRESS:NN|all>",
    2918             :        SHOW_STR
    2919             :        IP_STR
    2920             :        BGP_STR
    2921             :        BGP_AFI_HELP_STR
    2922             :        BGP_AF_MODIFIER_STR
    2923             :        "Display information for a route distinguisher\n"
    2924             :        "VPN Route Distinguisher\n"
    2925             :        "All VPN Route Distinguishers\n")
    2926             : {
    2927             :         int idx_ext_community = argc - 1;
    2928             :         int ret;
    2929             :         struct prefix_rd prd;
    2930             :         afi_t afi;
    2931             :         int idx = 0;
    2932             : 
    2933             :         if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
    2934             :                 if (!strcmp(argv[idx_ext_community]->arg, "all"))
    2935             :                         return bgp_show_mpls_vpn(vty, afi, NULL,
    2936             :                                                  bgp_show_type_normal, NULL, 0,
    2937             :                                                  0);
    2938             :                 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
    2939             :                 if (!ret) {
    2940             :                         vty_out(vty, "%% Malformed Route Distinguisher\n");
    2941             :                         return CMD_WARNING;
    2942             :                 }
    2943             :                 return bgp_show_mpls_vpn(vty, afi, &prd, bgp_show_type_normal,
    2944             :                                          NULL, 0, 0);
    2945             :         }
    2946             :         return CMD_SUCCESS;
    2947             : }
    2948             : 
    2949             : DEFUN (show_ip_bgp_vpn_all,
    2950             :        show_ip_bgp_vpn_all_cmd,
    2951             :        "show [ip] bgp <vpnv4|vpnv6>",
    2952             :        SHOW_STR
    2953             :        IP_STR
    2954             :        BGP_STR
    2955             :        BGP_VPNVX_HELP_STR)
    2956             : {
    2957             :         afi_t afi;
    2958             :         int idx = 0;
    2959             : 
    2960             :         if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi))
    2961             :                 return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal,
    2962             :                                          NULL, 0, 0);
    2963             :         return CMD_SUCCESS;
    2964             : }
    2965             : 
    2966             : DEFUN (show_ip_bgp_vpn_all_tags,
    2967             :        show_ip_bgp_vpn_all_tags_cmd,
    2968             :        "show [ip] bgp <vpnv4|vpnv6> all tags",
    2969             :        SHOW_STR
    2970             :        IP_STR
    2971             :        BGP_STR
    2972             :        BGP_VPNVX_HELP_STR
    2973             :        "Display information about all VPNv4/VPNV6 NLRIs\n"
    2974             :        "Display BGP tags for prefixes\n")
    2975             : {
    2976             :         afi_t afi;
    2977             :         int idx = 0;
    2978             : 
    2979             :         if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi))
    2980             :                 return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal,
    2981             :                                          NULL, 1, 0);
    2982             :         return CMD_SUCCESS;
    2983             : }
    2984             : 
    2985             : DEFUN (show_ip_bgp_vpn_rd_tags,
    2986             :        show_ip_bgp_vpn_rd_tags_cmd,
    2987             :        "show [ip] bgp <vpnv4|vpnv6> rd <ASN:NN_OR_IP-ADDRESS:NN|all> tags",
    2988             :        SHOW_STR
    2989             :        IP_STR
    2990             :        BGP_STR
    2991             :        BGP_VPNVX_HELP_STR
    2992             :        "Display information for a route distinguisher\n"
    2993             :        "VPN Route Distinguisher\n"
    2994             :        "All VPN Route Distinguishers\n"
    2995             :        "Display BGP tags for prefixes\n")
    2996             : {
    2997             :         int idx_ext_community = 5;
    2998             :         int ret;
    2999             :         struct prefix_rd prd;
    3000             :         afi_t afi;
    3001             :         int idx = 0;
    3002             : 
    3003             :         if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
    3004             :                 if (!strcmp(argv[idx_ext_community]->arg, "all"))
    3005             :                         return bgp_show_mpls_vpn(vty, afi, NULL,
    3006             :                                                  bgp_show_type_normal, NULL, 1,
    3007             :                                                  0);
    3008             :                 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
    3009             :                 if (!ret) {
    3010             :                         vty_out(vty, "%% Malformed Route Distinguisher\n");
    3011             :                         return CMD_WARNING;
    3012             :                 }
    3013             :                 return bgp_show_mpls_vpn(vty, afi, &prd, bgp_show_type_normal,
    3014             :                                          NULL, 1, 0);
    3015             :         }
    3016             :         return CMD_SUCCESS;
    3017             : }
    3018             : 
    3019             : DEFUN (show_ip_bgp_vpn_all_neighbor_routes,
    3020             :        show_ip_bgp_vpn_all_neighbor_routes_cmd,
    3021             :        "show [ip] bgp <vpnv4|vpnv6> all neighbors A.B.C.D routes [json]",
    3022             :        SHOW_STR
    3023             :        IP_STR
    3024             :        BGP_STR
    3025             :        BGP_VPNVX_HELP_STR
    3026             :        "Display information about all VPNv4/VPNv6 NLRIs\n"
    3027             :        "Detailed information on TCP and BGP neighbor connections\n"
    3028             :        "Neighbor to display information about\n"
    3029             :        "Display routes learned from neighbor\n"
    3030             :        JSON_STR)
    3031             : {
    3032             :         int idx_ipv4 = 6;
    3033             :         union sockunion su;
    3034             :         struct peer *peer;
    3035             :         int ret;
    3036             :         bool uj = use_json(argc, argv);
    3037             :         afi_t afi;
    3038             :         int idx = 0;
    3039             : 
    3040             :         if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
    3041             :                 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
    3042             :                 if (ret < 0) {
    3043             :                         if (uj) {
    3044             :                                 json_object *json_no = NULL;
    3045             :                                 json_no = json_object_new_object();
    3046             :                                 json_object_string_add(json_no, "warning",
    3047             :                                                        "Malformed address");
    3048             :                                 vty_out(vty, "%s\n",
    3049             :                                         json_object_to_json_string(json_no));
    3050             :                                 json_object_free(json_no);
    3051             :                         } else
    3052             :                                 vty_out(vty, "Malformed address: %s\n",
    3053             :                                         argv[idx_ipv4]->arg);
    3054             :                         return CMD_WARNING;
    3055             :                 }
    3056             : 
    3057             :                 peer = peer_lookup(NULL, &su);
    3058             :                 if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) {
    3059             :                         if (uj) {
    3060             :                                 json_object *json_no = NULL;
    3061             :                                 json_no = json_object_new_object();
    3062             :                                 json_object_string_add(
    3063             :                                         json_no, "warning",
    3064             :                                         "No such neighbor or address family");
    3065             :                                 vty_out(vty, "%s\n",
    3066             :                                         json_object_to_json_string(json_no));
    3067             :                                 json_object_free(json_no);
    3068             :                         } else
    3069             :                                 vty_out(vty,
    3070             :                                         "%% No such neighbor or address family\n");
    3071             :                         return CMD_WARNING;
    3072             :                 }
    3073             : 
    3074             :                 return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_neighbor,
    3075             :                                          &su, 0, uj);
    3076             :         }
    3077             :         return CMD_SUCCESS;
    3078             : }
    3079             : 
    3080             : DEFUN (show_ip_bgp_vpn_rd_neighbor_routes,
    3081             :        show_ip_bgp_vpn_rd_neighbor_routes_cmd,
    3082             :        "show [ip] bgp <vpnv4|vpnv6> rd <ASN:NN_OR_IP-ADDRESS:NN|all> neighbors A.B.C.D routes [json]",
    3083             :        SHOW_STR
    3084             :        IP_STR
    3085             :        BGP_STR
    3086             :        BGP_VPNVX_HELP_STR
    3087             :        "Display information for a route distinguisher\n"
    3088             :        "VPN Route Distinguisher\n"
    3089             :        "All VPN Route Distinguishers\n"
    3090             :        "Detailed information on TCP and BGP neighbor connections\n"
    3091             :        "Neighbor to display information about\n"
    3092             :        "Display routes learned from neighbor\n"
    3093             :        JSON_STR)
    3094             : {
    3095             :         int idx_ext_community = 5;
    3096             :         int idx_ipv4 = 7;
    3097             :         int ret;
    3098             :         union sockunion su;
    3099             :         struct peer *peer;
    3100             :         struct prefix_rd prd;
    3101             :         bool prefix_rd_all = false;
    3102             :         bool uj = use_json(argc, argv);
    3103             :         afi_t afi;
    3104             :         int idx = 0;
    3105             : 
    3106             :         if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
    3107             :                 if (!strcmp(argv[idx_ext_community]->arg, "all"))
    3108             :                         prefix_rd_all = true;
    3109             :                 else {
    3110             :                         ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
    3111             :                         if (!ret) {
    3112             :                                 if (uj) {
    3113             :                                         json_object *json_no = NULL;
    3114             :                                         json_no = json_object_new_object();
    3115             :                                         json_object_string_add(
    3116             :                                                 json_no, "warning",
    3117             :                                                 "Malformed Route Distinguisher");
    3118             :                                         vty_out(vty, "%s\n",
    3119             :                                                 json_object_to_json_string(
    3120             :                                                         json_no));
    3121             :                                         json_object_free(json_no);
    3122             :                                 } else
    3123             :                                         vty_out(vty,
    3124             :                                                 "%% Malformed Route Distinguisher\n");
    3125             :                                 return CMD_WARNING;
    3126             :                         }
    3127             :                 }
    3128             : 
    3129             :                 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
    3130             :                 if (ret < 0) {
    3131             :                         if (uj) {
    3132             :                                 json_object *json_no = NULL;
    3133             :                                 json_no = json_object_new_object();
    3134             :                                 json_object_string_add(json_no, "warning",
    3135             :                                                        "Malformed address");
    3136             :                                 vty_out(vty, "%s\n",
    3137             :                                         json_object_to_json_string(json_no));
    3138             :                                 json_object_free(json_no);
    3139             :                         } else
    3140             :                                 vty_out(vty, "Malformed address: %s\n",
    3141             :                                         argv[idx_ext_community]->arg);
    3142             :                         return CMD_WARNING;
    3143             :                 }
    3144             : 
    3145             :                 peer = peer_lookup(NULL, &su);
    3146             :                 if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) {
    3147             :                         if (uj) {
    3148             :                                 json_object *json_no = NULL;
    3149             :                                 json_no = json_object_new_object();
    3150             :                                 json_object_string_add(
    3151             :                                         json_no, "warning",
    3152             :                                         "No such neighbor or address family");
    3153             :                                 vty_out(vty, "%s\n",
    3154             :                                         json_object_to_json_string(json_no));
    3155             :                                 json_object_free(json_no);
    3156             :                         } else
    3157             :                                 vty_out(vty,
    3158             :                                         "%% No such neighbor or address family\n");
    3159             :                         return CMD_WARNING;
    3160             :                 }
    3161             : 
    3162             :                 if (prefix_rd_all)
    3163             :                         return bgp_show_mpls_vpn(vty, afi, NULL,
    3164             :                                                  bgp_show_type_neighbor, &su, 0,
    3165             :                                                  uj);
    3166             :                 else
    3167             :                         return bgp_show_mpls_vpn(vty, afi, &prd,
    3168             :                                                  bgp_show_type_neighbor, &su, 0,
    3169             :                                                  uj);
    3170             :         }
    3171             :         return CMD_SUCCESS;
    3172             : }
    3173             : 
    3174             : DEFUN (show_ip_bgp_vpn_all_neighbor_advertised_routes,
    3175             :        show_ip_bgp_vpn_all_neighbor_advertised_routes_cmd,
    3176             :        "show [ip] bgp <vpnv4|vpnv6> all neighbors A.B.C.D advertised-routes [json]",
    3177             :        SHOW_STR
    3178             :        IP_STR
    3179             :        BGP_STR
    3180             :        BGP_VPNVX_HELP_STR
    3181             :        "Display information about all VPNv4/VPNv6 NLRIs\n"
    3182             :        "Detailed information on TCP and BGP neighbor connections\n"
    3183             :        "Neighbor to display information about\n"
    3184             :        "Display the routes advertised to a BGP neighbor\n"
    3185             :        JSON_STR)
    3186             : {
    3187             :         int idx_ipv4 = 6;
    3188             :         int ret;
    3189             :         struct peer *peer;
    3190             :         union sockunion su;
    3191             :         bool uj = use_json(argc, argv);
    3192             :         afi_t afi;
    3193             :         int idx = 0;
    3194             : 
    3195             :         if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
    3196             :                 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
    3197             :                 if (ret < 0) {
    3198             :                         if (uj) {
    3199             :                                 json_object *json_no = NULL;
    3200             :                                 json_no = json_object_new_object();
    3201             :                                 json_object_string_add(json_no, "warning",
    3202             :                                                        "Malformed address");
    3203             :                                 vty_out(vty, "%s\n",
    3204             :                                         json_object_to_json_string(json_no));
    3205             :                                 json_object_free(json_no);
    3206             :                         } else
    3207             :                                 vty_out(vty, "Malformed address: %s\n",
    3208             :                                         argv[idx_ipv4]->arg);
    3209             :                         return CMD_WARNING;
    3210             :                 }
    3211             :                 peer = peer_lookup(NULL, &su);
    3212             :                 if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) {
    3213             :                         if (uj) {
    3214             :                                 json_object *json_no = NULL;
    3215             :                                 json_no = json_object_new_object();
    3216             :                                 json_object_string_add(
    3217             :                                         json_no, "warning",
    3218             :                                         "No such neighbor or address family");
    3219             :                                 vty_out(vty, "%s\n",
    3220             :                                         json_object_to_json_string(json_no));
    3221             :                                 json_object_free(json_no);
    3222             :                         } else
    3223             :                                 vty_out(vty,
    3224             :                                         "%% No such neighbor or address family\n");
    3225             :                         return CMD_WARNING;
    3226             :                 }
    3227             :                 return show_adj_route_vpn(vty, peer, NULL, AFI_IP,
    3228             :                                           SAFI_MPLS_VPN, uj);
    3229             :         }
    3230             :         return CMD_SUCCESS;
    3231             : }
    3232             : 
    3233             : DEFUN (show_ip_bgp_vpn_rd_neighbor_advertised_routes,
    3234             :        show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd,
    3235             :        "show [ip] bgp <vpnv4|vpnv6> rd <ASN:NN_OR_IP-ADDRESS:NN|all> neighbors A.B.C.D advertised-routes [json]",
    3236             :        SHOW_STR
    3237             :        IP_STR
    3238             :        BGP_STR
    3239             :        BGP_VPNVX_HELP_STR
    3240             :        "Display information for a route distinguisher\n"
    3241             :        "VPN Route Distinguisher\n"
    3242             :        "All VPN Route Distinguishers\n"
    3243             :        "Detailed information on TCP and BGP neighbor connections\n"
    3244             :        "Neighbor to display information about\n"
    3245             :        "Display the routes advertised to a BGP neighbor\n"
    3246             :        JSON_STR)
    3247             : {
    3248             :         int idx_ext_community = 5;
    3249             :         int idx_ipv4 = 7;
    3250             :         int ret;
    3251             :         struct peer *peer;
    3252             :         struct prefix_rd prd;
    3253             :         union sockunion su;
    3254             :         bool uj = use_json(argc, argv);
    3255             :         afi_t afi;
    3256             :         int idx = 0;
    3257             : 
    3258             :         if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
    3259             :                 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
    3260             :                 if (ret < 0) {
    3261             :                         if (uj) {
    3262             :                                 json_object *json_no = NULL;
    3263             :                                 json_no = json_object_new_object();
    3264             :                                 json_object_string_add(json_no, "warning",
    3265             :                                                        "Malformed address");
    3266             :                                 vty_out(vty, "%s\n",
    3267             :                                         json_object_to_json_string(json_no));
    3268             :                                 json_object_free(json_no);
    3269             :                         } else
    3270             :                                 vty_out(vty, "Malformed address: %s\n",
    3271             :                                         argv[idx_ext_community]->arg);
    3272             :                         return CMD_WARNING;
    3273             :                 }
    3274             :                 peer = peer_lookup(NULL, &su);
    3275             :                 if (!peer || !peer->afc[afi][SAFI_MPLS_VPN]) {
    3276             :                         if (uj) {
    3277             :                                 json_object *json_no = NULL;
    3278             :                                 json_no = json_object_new_object();
    3279             :                                 json_object_string_add(
    3280             :                                         json_no, "warning",
    3281             :                                         "No such neighbor or address family");
    3282             :                                 vty_out(vty, "%s\n",
    3283             :                                         json_object_to_json_string(json_no));
    3284             :                                 json_object_free(json_no);
    3285             :                         } else
    3286             :                                 vty_out(vty,
    3287             :                                         "%% No such neighbor or address family\n");
    3288             :                         return CMD_WARNING;
    3289             :                 }
    3290             : 
    3291             :                 if (!strcmp(argv[idx_ext_community]->arg, "all"))
    3292             :                         return show_adj_route_vpn(vty, peer, NULL, AFI_IP,
    3293             :                                                   SAFI_MPLS_VPN, uj);
    3294             :                 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
    3295             :                 if (!ret) {
    3296             :                         if (uj) {
    3297             :                                 json_object *json_no = NULL;
    3298             :                                 json_no = json_object_new_object();
    3299             :                                 json_object_string_add(
    3300             :                                         json_no, "warning",
    3301             :                                         "Malformed Route Distinguisher");
    3302             :                                 vty_out(vty, "%s\n",
    3303             :                                         json_object_to_json_string(json_no));
    3304             :                                 json_object_free(json_no);
    3305             :                         } else
    3306             :                                 vty_out(vty,
    3307             :                                         "%% Malformed Route Distinguisher\n");
    3308             :                         return CMD_WARNING;
    3309             :                 }
    3310             : 
    3311             :                 return show_adj_route_vpn(vty, peer, &prd, AFI_IP,
    3312             :                                           SAFI_MPLS_VPN, uj);
    3313             :         }
    3314             :         return CMD_SUCCESS;
    3315             : }
    3316             : #endif /* KEEP_OLD_VPN_COMMANDS */
    3317             : 
    3318           2 : void bgp_mplsvpn_init(void)
    3319             : {
    3320           2 :         install_element(BGP_VPNV4_NODE, &vpnv4_network_cmd);
    3321           2 :         install_element(BGP_VPNV4_NODE, &vpnv4_network_route_map_cmd);
    3322           2 :         install_element(BGP_VPNV4_NODE, &no_vpnv4_network_cmd);
    3323             : 
    3324           2 :         install_element(BGP_VPNV6_NODE, &vpnv6_network_cmd);
    3325           2 :         install_element(BGP_VPNV6_NODE, &no_vpnv6_network_cmd);
    3326             : 
    3327           2 :         install_element(VIEW_NODE, &show_bgp_ip_vpn_all_rd_cmd);
    3328           2 :         install_element(VIEW_NODE, &show_bgp_ip_vpn_rd_cmd);
    3329             : #ifdef KEEP_OLD_VPN_COMMANDS
    3330             :         install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_cmd);
    3331             :         install_element(VIEW_NODE, &show_ip_bgp_vpn_all_cmd);
    3332             :         install_element(VIEW_NODE, &show_ip_bgp_vpn_all_tags_cmd);
    3333             :         install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_tags_cmd);
    3334             :         install_element(VIEW_NODE, &show_ip_bgp_vpn_all_neighbor_routes_cmd);
    3335             :         install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_neighbor_routes_cmd);
    3336             :         install_element(VIEW_NODE,
    3337             :                         &show_ip_bgp_vpn_all_neighbor_advertised_routes_cmd);
    3338             :         install_element(VIEW_NODE,
    3339             :                         &show_ip_bgp_vpn_rd_neighbor_advertised_routes_cmd);
    3340             : #endif /* KEEP_OLD_VPN_COMMANDS */
    3341           2 : }
    3342             : 
    3343           0 : vrf_id_t get_first_vrf_for_redirect_with_rt(struct ecommunity *eckey)
    3344             : {
    3345           0 :         struct listnode *mnode, *mnnode;
    3346           0 :         struct bgp *bgp;
    3347           0 :         afi_t afi = AFI_IP;
    3348             : 
    3349           0 :         if (eckey->unit_size == IPV6_ECOMMUNITY_SIZE)
    3350           0 :                 afi = AFI_IP6;
    3351             : 
    3352           0 :         for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
    3353           0 :                 struct ecommunity *ec;
    3354             : 
    3355           0 :                 if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
    3356           0 :                         continue;
    3357             : 
    3358           0 :                 ec = bgp->vpn_policy[afi].import_redirect_rtlist;
    3359             : 
    3360           0 :                 if (ec && eckey->unit_size != ec->unit_size)
    3361           0 :                         continue;
    3362             : 
    3363           0 :                 if (ecommunity_include(ec, eckey))
    3364           0 :                         return bgp->vrf_id;
    3365             :         }
    3366             :         return VRF_UNKNOWN;
    3367             : }
    3368             : 
    3369             : /*
    3370             :  * The purpose of this function is to process leaks that were deferred
    3371             :  * from earlier per-vrf configuration due to not-yet-existing default
    3372             :  * vrf, in other words, configuration such as:
    3373             :  *
    3374             :  *     router bgp MMM vrf FOO
    3375             :  *       address-family ipv4 unicast
    3376             :  *         rd vpn export 1:1
    3377             :  *       exit-address-family
    3378             :  *
    3379             :  *     router bgp NNN
    3380             :  *       ...
    3381             :  *
    3382             :  * This function gets called when the default instance ("router bgp NNN")
    3383             :  * is created.
    3384             :  */
    3385           2 : void vpn_leak_postchange_all(void)
    3386             : {
    3387           2 :         struct listnode *next;
    3388           2 :         struct bgp *bgp;
    3389           2 :         struct bgp *bgp_default = bgp_get_default();
    3390             : 
    3391           2 :         assert(bgp_default);
    3392             : 
    3393             :         /* First, do any exporting from VRFs to the single VPN RIB */
    3394           6 :         for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) {
    3395             : 
    3396           2 :                 if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
    3397           2 :                         continue;
    3398             : 
    3399           0 :                 vpn_leak_postchange(
    3400             :                         BGP_VPN_POLICY_DIR_TOVPN,
    3401             :                         AFI_IP,
    3402             :                         bgp_default,
    3403             :                         bgp);
    3404             : 
    3405           0 :                 vpn_leak_postchange(
    3406             :                         BGP_VPN_POLICY_DIR_TOVPN,
    3407             :                         AFI_IP6,
    3408             :                         bgp_default,
    3409             :                         bgp);
    3410             :         }
    3411             : 
    3412             :         /* Now, do any importing to VRFs from the single VPN RIB */
    3413           6 :         for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) {
    3414             : 
    3415           2 :                 if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
    3416           2 :                         continue;
    3417             : 
    3418           0 :                 vpn_leak_postchange(
    3419             :                         BGP_VPN_POLICY_DIR_FROMVPN,
    3420             :                         AFI_IP,
    3421             :                         bgp_default,
    3422             :                         bgp);
    3423             : 
    3424           0 :                 vpn_leak_postchange(
    3425             :                         BGP_VPN_POLICY_DIR_FROMVPN,
    3426             :                         AFI_IP6,
    3427             :                         bgp_default,
    3428             :                         bgp);
    3429             :         }
    3430           2 : }
    3431             : 
    3432             : /* When a bgp vrf instance is unconfigured, remove its routes
    3433             :  * from the VPN table and this vrf could be importing routes from other
    3434             :  * bgp vrf instnaces, unimport them.
    3435             :  * VRF X and VRF Y are exporting routes to each other.
    3436             :  * When VRF X is deleted, unimport its routes from all target vrfs,
    3437             :  * also VRF Y should unimport its routes from VRF X table.
    3438             :  * This will ensure VPN table is cleaned up appropriately.
    3439             :  */
    3440           2 : void bgp_vpn_leak_unimport(struct bgp *from_bgp)
    3441             : {
    3442           2 :         struct bgp *to_bgp;
    3443           2 :         const char *tmp_name;
    3444           2 :         char *vname;
    3445           2 :         struct listnode *node, *next;
    3446           2 :         safi_t safi = SAFI_UNICAST;
    3447           2 :         afi_t afi;
    3448           2 :         bool is_vrf_leak_bind;
    3449           2 :         int debug;
    3450             : 
    3451           2 :         if (from_bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
    3452             :                 return;
    3453             : 
    3454           0 :         debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) |
    3455             :                      BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
    3456             : 
    3457           0 :         tmp_name = from_bgp->name ? from_bgp->name : VRF_DEFAULT_NAME;
    3458             : 
    3459           0 :         for (afi = 0; afi < AFI_MAX; ++afi) {
    3460             :                 /* vrf leak is for IPv4 and IPv6 Unicast only */
    3461           0 :                 if (afi != AFI_IP && afi != AFI_IP6)
    3462           0 :                         continue;
    3463             : 
    3464           0 :                 for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, to_bgp)) {
    3465           0 :                         if (from_bgp == to_bgp)
    3466           0 :                                 continue;
    3467             : 
    3468             :                         /* Unimport and remove source vrf from the
    3469             :                          * other vrfs import list.
    3470             :                          */
    3471           0 :                         struct vpn_policy *to_vpolicy;
    3472             : 
    3473           0 :                         is_vrf_leak_bind = false;
    3474           0 :                         to_vpolicy = &(to_bgp->vpn_policy[afi]);
    3475           0 :                         for (ALL_LIST_ELEMENTS_RO(to_vpolicy->import_vrf, node,
    3476             :                                                   vname)) {
    3477           0 :                                 if (strcmp(vname, tmp_name) == 0) {
    3478             :                                         is_vrf_leak_bind = true;
    3479             :                                         break;
    3480             :                                 }
    3481             :                         }
    3482             :                         /* skip this bgp instance as there is no leak to this
    3483             :                          * vrf instance.
    3484             :                          */
    3485           0 :                         if (!is_vrf_leak_bind)
    3486           0 :                                 continue;
    3487             : 
    3488           0 :                         if (debug)
    3489           0 :                                 zlog_debug("%s: unimport routes from %s to_bgp %s afi %s import vrfs count %u",
    3490             :                                            __func__, from_bgp->name_pretty,
    3491             :                                            to_bgp->name_pretty, afi2str(afi),
    3492             :                                            to_vpolicy->import_vrf->count);
    3493             : 
    3494           0 :                         vrf_unimport_from_vrf(to_bgp, from_bgp, afi, safi);
    3495             : 
    3496             :                         /* readd vrf name as unimport removes import vrf name
    3497             :                          * from the destination vrf's import list where the
    3498             :                          * `import vrf` configuration still exist.
    3499             :                          */
    3500           0 :                         vname = XSTRDUP(MTYPE_TMP, tmp_name);
    3501           0 :                         listnode_add(to_bgp->vpn_policy[afi].import_vrf,
    3502             :                                      vname);
    3503           0 :                         SET_FLAG(to_bgp->af_flags[afi][safi],
    3504             :                                  BGP_CONFIG_VRF_TO_VRF_IMPORT);
    3505             : 
    3506             :                         /* If to_bgp exports its routes to the bgp vrf
    3507             :                          * which is being deleted, un-import the
    3508             :                          * to_bgp routes from VPN.
    3509             :                          */
    3510           0 :                         for (ALL_LIST_ELEMENTS_RO(to_bgp->vpn_policy[afi]
    3511             :                                                   .export_vrf, node,
    3512             :                                                   vname)) {
    3513           0 :                                 if (strcmp(vname, tmp_name) == 0) {
    3514           0 :                                         vrf_unimport_from_vrf(from_bgp, to_bgp,
    3515             :                                                       afi, safi);
    3516           0 :                                         break;
    3517             :                                 }
    3518             :                         }
    3519             :                 }
    3520             :         }
    3521             :         return;
    3522             : }
    3523             : 
    3524             : /* When a router bgp is configured, there could be a bgp vrf
    3525             :  * instance importing routes from this newly configured
    3526             :  * bgp vrf instance. Export routes from configured
    3527             :  * bgp vrf to VPN.
    3528             :  * VRF Y has import from bgp vrf x,
    3529             :  * when a bgp vrf x instance is created, export its routes
    3530             :  * to VRF Y instance.
    3531             :  */
    3532           0 : void bgp_vpn_leak_export(struct bgp *from_bgp)
    3533             : {
    3534           0 :         afi_t afi;
    3535           0 :         const char *export_name;
    3536           0 :         char *vname;
    3537           0 :         struct listnode *node, *next;
    3538           0 :         struct ecommunity *ecom;
    3539           0 :         enum vpn_policy_direction idir, edir;
    3540           0 :         safi_t safi = SAFI_UNICAST;
    3541           0 :         struct bgp *to_bgp;
    3542           0 :         int debug;
    3543             : 
    3544           0 :         debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) |
    3545             :                      BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
    3546             : 
    3547           0 :         idir = BGP_VPN_POLICY_DIR_FROMVPN;
    3548           0 :         edir = BGP_VPN_POLICY_DIR_TOVPN;
    3549             : 
    3550           0 :         export_name = from_bgp->name ? from_bgp->name : VRF_DEFAULT_NAME;
    3551             : 
    3552           0 :         for (afi = 0; afi < AFI_MAX; ++afi) {
    3553             :                 /* vrf leak is for IPv4 and IPv6 Unicast only */
    3554           0 :                 if (afi != AFI_IP && afi != AFI_IP6)
    3555           0 :                         continue;
    3556             : 
    3557           0 :                 for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, to_bgp)) {
    3558           0 :                         if (from_bgp == to_bgp)
    3559           0 :                                 continue;
    3560             : 
    3561             :                         /* bgp instance has import list, check to see if newly
    3562             :                          * configured bgp instance is the list.
    3563             :                          */
    3564           0 :                         struct vpn_policy *to_vpolicy;
    3565             : 
    3566           0 :                         to_vpolicy = &(to_bgp->vpn_policy[afi]);
    3567           0 :                         for (ALL_LIST_ELEMENTS_RO(to_vpolicy->import_vrf,
    3568             :                                                   node, vname)) {
    3569           0 :                                 if (strcmp(vname, export_name) != 0)
    3570           0 :                                         continue;
    3571             : 
    3572           0 :                                 if (debug)
    3573           0 :                                         zlog_debug("%s: found from_bgp %s in to_bgp %s import list, import routes.",
    3574             :                                            __func__,
    3575             :                                            export_name, to_bgp->name_pretty);
    3576             : 
    3577           0 :                                 ecom = from_bgp->vpn_policy[afi].rtlist[edir];
    3578             :                                 /* remove import rt, it will be readded
    3579             :                                  * as part of import from vrf.
    3580             :                                  */
    3581           0 :                                 if (ecom)
    3582           0 :                                         ecommunity_del_val(
    3583             :                                                 to_vpolicy->rtlist[idir],
    3584             :                                                 (struct ecommunity_val *)
    3585           0 :                                                         ecom->val);
    3586           0 :                                 vrf_import_from_vrf(to_bgp, from_bgp,
    3587             :                                                     afi, safi);
    3588           0 :                                 break;
    3589             : 
    3590             :                         }
    3591             :                 }
    3592             :         }
    3593           0 : }

Generated by: LCOV version v1.16-topotato