3 * Copyright 2009-2016, LabN Consulting, L.L.C.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
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
22 * File: vnc_export_bgp.c
23 * Purpose: Export routes to BGP directly (not via zebra)
26 #include "lib/zebra.h"
27 #include "lib/prefix.h"
28 #include "lib/agg_table.h"
31 #include "lib/stream.h"
32 #include "lib/memory.h"
33 #include "lib/linklist.h"
34 #include "lib/plist.h"
35 #include "lib/routemap.h"
36 #include "lib/lib_errors.h"
38 #include "bgpd/bgpd.h"
39 #include "bgpd/bgp_ecommunity.h"
40 #include "bgpd/bgp_attr.h"
41 #include "bgpd/bgp_aspath.h"
43 #include "bgpd/rfapi/vnc_export_bgp.h"
44 #include "bgpd/rfapi/vnc_export_bgp_p.h"
45 #include "bgpd/rfapi/vnc_export_table.h"
46 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
47 #include "bgpd/rfapi/rfapi.h"
48 #include "bgpd/rfapi/rfapi_import.h"
49 #include "bgpd/rfapi/rfapi_private.h"
50 #include "bgpd/rfapi/rfapi_backend.h"
51 #include "bgpd/rfapi/rfapi_vty.h"
52 #include "bgpd/rfapi/vnc_debug.h"
55 static void vnc_direct_add_rn_group_rd(struct bgp
*bgp
,
56 struct rfapi_nve_group_cfg
*rfg
,
57 struct agg_node
*rn
, struct attr
*attr
,
59 struct rfapi_descriptor
*irfd
);
61 /***********************************************************************
62 * Export methods that set nexthop to CE (from 5226 roo EC) BEGIN
63 ***********************************************************************/
66 * Memory allocation approach: make a ghost attr that
67 * has non-interned parts for the modifications. ghost attr
68 * memory is allocated by caller.
70 * - extract ce (=5226) EC and use as new nexthop
71 * - strip Tunnel Encap attr
74 static void encap_attr_export_ce(struct attr
*new, struct attr
*orig
,
75 struct prefix
*use_nexthop
)
78 * Make "new" a ghost attr copy of "orig"
80 memset(new, 0, sizeof(struct attr
));
86 switch (use_nexthop
->family
) {
88 new->nexthop
= use_nexthop
->u
.prefix4
;
89 new->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
; /* bytes */
90 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
94 new->mp_nexthop_global
= use_nexthop
->u
.prefix6
;
95 new->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
; /* bytes */
106 * Note that it will be deleted when BGP sends to any eBGP
107 * peer unless PEER_FLAG_MED_UNCHANGED is set:
109 * neighbor NEIGHBOR attribute-unchanged med
111 if (!CHECK_FLAG(new->flag
, BGP_ATTR_MULTI_EXIT_DISC
)) {
112 if (CHECK_FLAG(new->flag
, BGP_ATTR_LOCAL_PREF
)) {
113 if (new->local_pref
> 255)
116 new->med
= 255 - new->local_pref
;
118 new->med
= 255; /* shouldn't happen */
120 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
124 * "new" is now a ghost attr:
125 * - it owns an "extra" struct
126 * - it owns any non-interned parts
127 * - any references to interned parts are not counted
129 * Caller should, after using the attr, call:
130 * - bgp_attr_flush() to free non-interned parts
134 static int getce(struct bgp
*bgp
, struct attr
*attr
, struct prefix
*pfx_ce
)
138 uint16_t localadmin
= bgp
->rfapi_cfg
->resolve_nve_roo_local_admin
;
139 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
141 for (ecp
= ecomm
->val
, i
= 0; i
< ecomm
->size
;
142 ++i
, ecp
+= ECOMMUNITY_SIZE
) {
144 if (VNC_DEBUG(EXPORT_BGP_GETCE
)) {
146 "%s: %02x %02x %02x %02x %02x %02x %02x %02x",
147 __func__
, ecp
[0], ecp
[1], ecp
[2], ecp
[3],
148 ecp
[4], ecp
[5], ecp
[6], ecp
[7]);
154 if (ecp
[0] != 1 || ecp
[1] != 3) {
159 * Match local admin value?
161 if (ecp
[6] != ((localadmin
& 0xff00) >> 8)
162 || ecp
[7] != (localadmin
& 0xff))
165 memset((uint8_t *)pfx_ce
, 0, sizeof(*pfx_ce
));
166 memcpy(&pfx_ce
->u
.prefix4
, ecp
+ 2, 4);
167 pfx_ce
->family
= AF_INET
;
168 pfx_ce
->prefixlen
= IPV4_MAX_BITLEN
;
176 void vnc_direct_bgp_add_route_ce(struct bgp
*bgp
, struct agg_node
*rn
,
177 struct bgp_path_info
*bpi
)
179 struct attr
*attr
= bpi
->attr
;
180 struct peer
*peer
= bpi
->peer
;
181 const struct prefix
*prefix
= agg_node_get_prefix(rn
);
182 afi_t afi
= family2afi(prefix
->family
);
183 struct bgp_dest
*udest
;
184 struct bgp_path_info
*ubpi
;
187 struct prefix ce_nexthop
;
188 struct prefix post_routemap_nexthop
;
192 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of route node",
197 if ((bpi
->type
!= ZEBRA_ROUTE_BGP
)
198 || (bpi
->sub_type
!= BGP_ROUTE_NORMAL
199 && bpi
->sub_type
!= BGP_ROUTE_RFP
200 && bpi
->sub_type
!= BGP_ROUTE_STATIC
)) {
202 vnc_zlog_debug_verbose(
203 "%s: wrong route type/sub_type for export, skipping",
208 /* check bgp redist flag for vnc direct ("vpn") routes */
209 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
210 vnc_zlog_debug_verbose(
211 "%s: bgp redistribution of VNC direct routes is off",
216 if (!bgp
->rfapi_cfg
) {
217 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
222 if (!VNC_EXPORT_BGP_CE_ENABLED(bgp
->rfapi_cfg
)) {
223 vnc_zlog_debug_verbose(
224 "%s: export-to-bgp ce mode not enabled, skipping",
232 if (bgp
->rfapi_cfg
->plist_export_bgp
[afi
]) {
233 if (prefix_list_apply(bgp
->rfapi_cfg
->plist_export_bgp
[afi
],
236 vnc_zlog_debug_verbose(
237 "%s: prefix list denied, skipping", __func__
);
245 * This works only for IPv4 because IPv6 addresses are too big
246 * to fit in an extended community
248 if (getce(bgp
, attr
, &ce_nexthop
)) {
249 vnc_zlog_debug_verbose("%s: EC has no encoded CE, skipping",
255 * Is this route already represented in the unicast RIB?
256 * (look up prefix; compare route type, sub_type, peer, nexthop)
258 udest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
, SAFI_UNICAST
,
260 for (ubpi
= bgp_dest_get_bgp_path_info(udest
); ubpi
;
262 struct prefix unicast_nexthop
;
264 if (CHECK_FLAG(ubpi
->flags
, BGP_PATH_REMOVED
))
267 rfapiUnicastNexthop2Prefix(afi
, ubpi
->attr
, &unicast_nexthop
);
269 if (ubpi
->type
== ZEBRA_ROUTE_VNC_DIRECT
270 && ubpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
271 && ubpi
->peer
== peer
272 && prefix_same(&unicast_nexthop
, &ce_nexthop
)) {
274 vnc_zlog_debug_verbose(
275 "%s: already have matching exported unicast route, skipping",
282 * Construct new attribute set with CE addr as
283 * nexthop and without Tunnel Encap attr
285 encap_attr_export_ce(&hattr
, attr
, &ce_nexthop
);
286 if (bgp
->rfapi_cfg
->routemap_export_bgp
) {
287 struct bgp_path_info info
;
288 route_map_result_t ret
;
290 memset(&info
, 0, sizeof(info
));
293 ret
= route_map_apply(bgp
->rfapi_cfg
->routemap_export_bgp
,
295 if (ret
== RMAP_DENYMATCH
) {
296 bgp_attr_flush(&hattr
);
301 iattr
= bgp_attr_intern(&hattr
);
302 bgp_attr_flush(&hattr
);
305 * Rule: disallow route-map alteration of next-hop, because it
306 * would make it too difficult to keep track of the correspondence
307 * between VPN routes and unicast routes.
309 rfapiUnicastNexthop2Prefix(afi
, iattr
, &post_routemap_nexthop
);
311 if (!prefix_same(&ce_nexthop
, &post_routemap_nexthop
)) {
312 vnc_zlog_debug_verbose(
313 "%s: route-map modification of nexthop not allowed, skipping",
315 bgp_attr_unintern(&iattr
);
319 bgp_update(peer
, prefix
, 0, /* addpath_id */
320 iattr
, /* bgp_update copies this attr */
321 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
322 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
323 NULL
, 0, /* tag not used for unicast */
324 0, NULL
); /* EVPN not used */
325 bgp_attr_unintern(&iattr
);
330 * "Withdrawing a Route" export process
332 void vnc_direct_bgp_del_route_ce(struct bgp
*bgp
, struct agg_node
*rn
,
333 struct bgp_path_info
*bpi
)
335 const struct prefix
*p
= agg_node_get_prefix(rn
);
336 afi_t afi
= family2afi(p
->family
);
337 struct bgp_path_info
*vbpi
;
338 struct prefix ce_nexthop
;
341 flog_err(EC_LIB_DEVELOPMENT
, "%s: bad afi", __func__
);
345 /* check bgp redist flag for vnc direct ("vpn") routes */
346 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
347 vnc_zlog_debug_verbose(
348 "%s: bgp redistribution of VNC direct routes is off",
353 if (!bgp
->rfapi_cfg
) {
354 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
358 if (!VNC_EXPORT_BGP_CE_ENABLED(bgp
->rfapi_cfg
)) {
359 vnc_zlog_debug_verbose(
360 "%s: export-to-bgp ce mode not enabled, skipping",
367 * This works only for IPv4 because IPv6 addresses are too big
368 * to fit in an extended community
370 if (getce(bgp
, bpi
->attr
, &ce_nexthop
)) {
371 vnc_zlog_debug_verbose("%s: EC has no encoded CE, skipping",
377 * Look for other VPN routes with same prefix, same 5226 CE,
378 * same peer. If at least one is present, don't remove the
379 * route from the unicast RIB
382 for (vbpi
= rn
->info
; vbpi
; vbpi
= vbpi
->next
) {
386 if (bpi
->peer
!= vbpi
->peer
)
388 if (getce(bgp
, vbpi
->attr
, &ce
))
390 if (prefix_same(&ce
, &ce_nexthop
)) {
391 vnc_zlog_debug_verbose(
392 "%s: still have a route via CE, not deleting unicast",
401 bgp_withdraw(bpi
->peer
, p
, 0, /* addpath_id */
402 NULL
, /* attr, ignored */
403 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
404 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
405 NULL
, 0, NULL
); /* tag not used for unicast */
408 static void vnc_direct_bgp_vpn_enable_ce(struct bgp
*bgp
, afi_t afi
)
411 struct bgp_path_info
*ri
;
413 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
418 if (!(bgp
->rfapi_cfg
))
421 if (!VNC_EXPORT_BGP_CE_ENABLED(bgp
->rfapi_cfg
)) {
422 vnc_zlog_debug_verbose(
423 "%s: export of CE routes not enabled, skipping",
428 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
429 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
434 * Go through entire ce import table and export to BGP unicast.
436 for (rn
= agg_route_top(bgp
->rfapi
->it_ce
->imported_vpn
[afi
]); rn
;
437 rn
= agg_route_next(rn
)) {
441 vnc_zlog_debug_verbose("%s: checking prefix %pRN", __func__
,
444 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
446 vnc_zlog_debug_verbose("%s: ri->sub_type: %d", __func__
,
449 if (ri
->sub_type
== BGP_ROUTE_NORMAL
450 || ri
->sub_type
== BGP_ROUTE_RFP
451 || ri
->sub_type
== BGP_ROUTE_STATIC
) {
453 vnc_direct_bgp_add_route_ce(bgp
, rn
, ri
);
459 static void vnc_direct_bgp_vpn_disable_ce(struct bgp
*bgp
, afi_t afi
)
461 struct bgp_dest
*dest
;
463 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
468 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
469 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
474 * Go through the entire BGP unicast table and remove routes that
477 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_UNICAST
]); dest
;
478 dest
= bgp_route_next(dest
)) {
480 struct bgp_path_info
*ri
;
481 struct bgp_path_info
*next
;
483 for (ri
= bgp_dest_get_bgp_path_info(dest
), next
= NULL
; ri
;
488 if (ri
->type
== ZEBRA_ROUTE_VNC_DIRECT
489 && ri
->sub_type
== BGP_ROUTE_REDISTRIBUTE
) {
492 ri
->peer
, bgp_dest_get_prefix(dest
),
495 AFI_IP
, SAFI_UNICAST
,
496 ZEBRA_ROUTE_VNC_DIRECT
,
497 BGP_ROUTE_REDISTRIBUTE
,
498 NULL
, /* RD not used for unicast */
500 NULL
); /* tag not used for unicast */
506 /***********************************************************************
507 * Export methods that set nexthop to CE (from 5226 roo EC) END
508 ***********************************************************************/
510 /***********************************************************************
511 * Export methods that proxy nexthop BEGIN
512 ***********************************************************************/
514 static struct ecommunity
*vnc_route_origin_ecom(struct agg_node
*rn
)
516 struct ecommunity
*new;
517 struct bgp_path_info
*bpi
;
522 new = ecommunity_new();
524 for (bpi
= rn
->info
; bpi
; bpi
= bpi
->next
) {
526 struct ecommunity_val roec
;
528 switch (BGP_MP_NEXTHOP_FAMILY(bpi
->attr
->mp_nexthop_len
)) {
530 memset(&roec
, 0, sizeof(roec
));
534 &bpi
->attr
->mp_nexthop_global_in
.s_addr
, 4);
537 ecommunity_add_val(new, &roec
, false, false);
540 /* No support for IPv6 addresses in extended communities
547 ecommunity_free(&new);
554 static struct ecommunity
*vnc_route_origin_ecom_single(struct in_addr
*origin
)
556 struct ecommunity
*new;
557 struct ecommunity_val roec
;
559 memset(&roec
, 0, sizeof(roec
));
562 memcpy(roec
.val
+ 2, &origin
->s_addr
, 4);
566 new = ecommunity_new();
568 ecommunity_add_val(new, &roec
, false, false);
571 ecommunity_free(&new);
580 * New memory allocation approach: make a ghost attr that
581 * has non-interned parts for the modifications. ghost attr
582 * memory is allocated by caller.
585 encap_attr_export(struct attr
*new, struct attr
*orig
,
586 struct prefix
*new_nexthop
,
587 struct agg_node
*rn
) /* for VN addrs for ecom list */
588 /* if rn is 0, use route's nexthop */
590 struct prefix orig_nexthop
;
591 struct prefix
*use_nexthop
;
592 static struct ecommunity
*ecom_ro
;
595 use_nexthop
= new_nexthop
;
597 use_nexthop
= &orig_nexthop
;
598 orig_nexthop
.family
=
599 BGP_MP_NEXTHOP_FAMILY(orig
->mp_nexthop_len
);
600 if (orig_nexthop
.family
== AF_INET
) {
601 orig_nexthop
.prefixlen
= IPV4_MAX_BITLEN
;
602 orig_nexthop
.u
.prefix4
= orig
->mp_nexthop_global_in
;
603 } else if (orig_nexthop
.family
== AF_INET6
) {
604 orig_nexthop
.prefixlen
= IPV6_MAX_BITLEN
;
605 orig_nexthop
.u
.prefix6
= orig
->mp_nexthop_global
;
607 return -1; /* FAIL - can't compute nexthop */
613 * Make "new" a ghost attr copy of "orig"
615 memset(new, 0, sizeof(struct attr
));
621 switch (use_nexthop
->family
) {
623 new->nexthop
= use_nexthop
->u
.prefix4
;
624 new->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
; /* bytes */
625 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
629 new->mp_nexthop_global
= use_nexthop
->u
.prefix6
;
630 new->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
; /* bytes */
639 ecom_ro
= vnc_route_origin_ecom(rn
);
641 /* TBD use lcom for IPv6 */
642 ecom_ro
= vnc_route_origin_ecom_single(&use_nexthop
->u
.prefix4
);
644 if (bgp_attr_get_ecommunity(new)) {
646 bgp_attr_set_ecommunity(
648 ecommunity_merge(ecom_ro
,
649 bgp_attr_get_ecommunity(new)));
651 bgp_attr_set_ecommunity(new, ecom_ro
);
654 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
660 * Note that it will be deleted when BGP sends to any eBGP
661 * peer unless PEER_FLAG_MED_UNCHANGED is set:
663 * neighbor NEIGHBOR attribute-unchanged med
665 if (!CHECK_FLAG(new->flag
, BGP_ATTR_MULTI_EXIT_DISC
)) {
666 if (CHECK_FLAG(new->flag
, BGP_ATTR_LOCAL_PREF
)) {
667 if (new->local_pref
> 255)
670 new->med
= 255 - new->local_pref
;
672 new->med
= 255; /* shouldn't happen */
674 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
678 * "new" is now a ghost attr:
679 * - it owns an "extra" struct
680 * - it owns any non-interned parts
681 * - any references to interned parts are not counted
683 * Caller should, after using the attr, call:
684 * - bgp_attr_flush() to free non-interned parts
691 * "Adding a Route" export process
693 void vnc_direct_bgp_add_prefix(struct bgp
*bgp
,
694 struct rfapi_import_table
*import_table
,
697 struct attr attr
= {0};
698 struct listnode
*node
, *nnode
;
699 struct rfapi_rfg_name
*rfgn
;
700 const struct prefix
*p
= agg_node_get_prefix(rn
);
701 afi_t afi
= family2afi(p
->family
);
704 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of route node",
709 /* check bgp redist flag for vnc direct ("vpn") routes */
710 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
711 vnc_zlog_debug_verbose(
712 "%s: bgp redistribution of VNC direct routes is off",
717 if (!bgp
->rfapi_cfg
) {
718 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
723 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
724 vnc_zlog_debug_verbose(
725 "%s: export-to-bgp group mode not enabled, skipping",
730 if (!listcount(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
)) {
731 vnc_zlog_debug_verbose(
732 "%s: no bgp-direct export nve group, skipping",
737 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
738 /* TBD set some configured med, see add_vnc_route() */
740 vnc_zlog_debug_verbose(
741 "%s: looping over nve-groups in direct-bgp export list",
744 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
750 * If nve group is not defined yet, skip it
756 * If the nve group uses a different import table, skip it
758 if (import_table
!= rfgn
->rfg
->rfapi_import_table
)
762 * if no NVEs currently associated with this group, skip it
764 if (rfgn
->rfg
->type
!= RFAPI_GROUP_CFG_VRF
&& !rfgn
->rfg
->nves
)
768 * per-nve-group prefix list check
770 if (rfgn
->rfg
->plist_export_bgp
[afi
]) {
771 if (prefix_list_apply(rfgn
->rfg
->plist_export_bgp
[afi
],
778 if (rfgn
->rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
779 vnc_direct_add_rn_group_rd(bgp
, rfgn
->rfg
, rn
, &attr
,
780 afi
, rfgn
->rfg
->rfd
);
783 * - but consistent with rest of function
788 * For each NVE that is assigned to the export nve group,
790 * a route with that NVE as its next hop
792 for (ln
= listhead(rfgn
->rfg
->nves
); ln
;
793 ln
= listnextnode(ln
)) {
794 vnc_direct_add_rn_group_rd(bgp
, rfgn
->rfg
, rn
, &attr
,
795 afi
, listgetdata(ln
));
799 aspath_unintern(&attr
.aspath
);
803 * "Withdrawing a Route" export process
805 void vnc_direct_bgp_del_prefix(struct bgp
*bgp
,
806 struct rfapi_import_table
*import_table
,
809 struct listnode
*node
, *nnode
;
810 struct rfapi_rfg_name
*rfgn
;
811 const struct prefix
*p
= agg_node_get_prefix(rn
);
812 afi_t afi
= family2afi(p
->family
);
815 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi route node",
820 /* check bgp redist flag for vnc direct ("vpn") routes */
821 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
822 vnc_zlog_debug_verbose(
823 "%s: bgp redistribution of VNC direct routes is off",
828 if (!bgp
->rfapi_cfg
) {
829 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
834 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
835 vnc_zlog_debug_verbose(
836 "%s: export-to-bgp group mode not enabled, skipping",
841 if (!listcount(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
)) {
842 vnc_zlog_debug_verbose(
843 "%s: no bgp-direct export nve group, skipping",
848 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
854 * If nve group is not defined yet, skip it
860 * if no NVEs currently associated with this group, skip it
862 if (rfgn
->rfg
->type
!= RFAPI_GROUP_CFG_VRF
&& !rfgn
->rfg
->nves
)
866 * If the nve group uses a different import table,
869 if (import_table
!= rfgn
->rfg
->rfapi_import_table
)
872 if (rfgn
->rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
874 struct rfapi_descriptor
*irfd
;
876 irfd
= rfgn
->rfg
->rfd
;
878 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
, &nhp
))
881 bgp_withdraw(irfd
->peer
, p
, /* prefix */
883 NULL
, /* attr, ignored */
884 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
885 BGP_ROUTE_REDISTRIBUTE
,
886 NULL
, /* RD not used for unicast */
888 NULL
); /* tag not used for unicast */
891 * - but consistent with rest of function
896 * For each NVE that is assigned to the export nve group,
898 * a route with that NVE as its next hop
900 for (ln
= listhead(rfgn
->rfg
->nves
); ln
;
901 ln
= listnextnode(ln
)) {
904 struct rfapi_descriptor
*irfd
;
906 irfd
= listgetdata(ln
);
908 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
, &nhp
))
911 bgp_withdraw(irfd
->peer
, p
, /* prefix */
913 NULL
, /* attr, ignored */
914 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
915 BGP_ROUTE_REDISTRIBUTE
,
916 NULL
, /* RD not used for unicast */
918 NULL
); /* tag not used for unicast */
923 void vnc_direct_bgp_add_nve(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
)
925 struct listnode
*node
, *nnode
;
926 struct rfapi_rfg_name
*rfgn
;
927 struct rfapi_nve_group_cfg
*rfg
= rfd
->rfg
;
928 afi_t afi
= family2afi(rfd
->vn_addr
.addr_family
);
931 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of nve vn addr",
938 if (!bgp
->rfapi_cfg
) {
939 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
943 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
944 vnc_zlog_debug_verbose(
945 "%s: export-to-bgp group mode not enabled, skipping",
950 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
951 vnc_zlog_debug_verbose(
952 "%s: bgp redistribution of VNC direct routes is off",
958 * Loop over the list of NVE-Groups configured for
959 * exporting to direct-bgp and see if this new NVE's
960 * group is among them.
962 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
966 * Yes, this NVE's group is configured for export to direct-bgp
968 if (rfgn
->rfg
== rfg
) {
970 struct agg_table
*rt
= NULL
;
972 struct attr attr
= {0};
973 struct rfapi_import_table
*import_table
;
976 import_table
= rfg
->rfapi_import_table
;
978 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
979 rt
= import_table
->imported_vpn
[afi
];
981 flog_err(EC_LIB_DEVELOPMENT
, "%s: bad afi %d",
986 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
987 /* TBD set some configured med, see add_vnc_route() */
990 * Walk the NVE-Group's VNC Import table
992 for (rn
= agg_route_top(rt
); rn
;
993 rn
= agg_route_next(rn
)) {
998 struct rfapi_descriptor
*irfd
= rfd
;
1001 struct bgp_path_info info
;
1002 const struct prefix
*p
=
1003 agg_node_get_prefix(rn
);
1005 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
,
1010 * per-nve-group prefix list check
1012 if (rfgn
->rfg
->plist_export_bgp
[afi
]) {
1013 if (prefix_list_apply(
1014 rfgn
->rfg
->plist_export_bgp
1024 * Construct new attribute set with
1026 * nexthop and without Tunnel Encap attr
1028 if (encap_attr_export(&hattr
, &attr
,
1032 if (rfgn
->rfg
->routemap_export_bgp
) {
1033 route_map_result_t ret
;
1034 info
.peer
= irfd
->peer
;
1036 ret
= route_map_apply(
1038 ->routemap_export_bgp
,
1040 if (ret
== RMAP_DENYMATCH
) {
1041 bgp_attr_flush(&hattr
);
1046 iattr
= bgp_attr_intern(&hattr
);
1047 bgp_attr_flush(&hattr
);
1049 irfd
->peer
, p
, /* prefix */
1051 iattr
, /* bgp_update copies
1054 ZEBRA_ROUTE_VNC_DIRECT
,
1055 BGP_ROUTE_REDISTRIBUTE
, NULL
,
1056 /* RD not used for unicast */
1058 /* tag not used for unicast */
1059 0, 0, NULL
); /* EVPN not used */
1061 bgp_attr_unintern(&iattr
);
1065 aspath_unintern(&attr
.aspath
);
1071 void vnc_direct_bgp_del_nve(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
)
1073 struct listnode
*node
, *nnode
;
1074 struct rfapi_rfg_name
*rfgn
;
1075 struct rfapi_nve_group_cfg
*rfg
= rfd
->rfg
;
1076 afi_t afi
= family2afi(rfd
->vn_addr
.addr_family
);
1079 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of nve vn addr",
1086 if (!bgp
->rfapi_cfg
) {
1087 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1091 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
1092 vnc_zlog_debug_verbose(
1093 "%s: export-to-bgp group mode not enabled, skipping",
1098 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
1099 vnc_zlog_debug_verbose(
1100 "%s: bgp redistribution of VNC direct routes is off",
1106 * Loop over the list of NVE-Groups configured for
1107 * exporting to direct-bgp and see if this new NVE's
1108 * group is among them.
1110 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
1114 * Yes, this NVE's group is configured for export to direct-bgp
1116 if (rfg
&& rfgn
->rfg
== rfg
) {
1118 struct agg_table
*rt
= NULL
;
1119 struct agg_node
*rn
;
1120 struct rfapi_import_table
*import_table
;
1122 import_table
= rfg
->rfapi_import_table
;
1124 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
1125 rt
= import_table
->imported_vpn
[afi
];
1127 flog_err(EC_LIB_DEVELOPMENT
, "%s: bad afi %d",
1133 * Walk the NVE-Group's VNC Import table
1135 for (rn
= agg_route_top(rt
); rn
;
1136 rn
= agg_route_next(rn
)) {
1139 const struct prefix
*p
=
1140 agg_node_get_prefix(rn
);
1142 struct rfapi_descriptor
*irfd
= rfd
;
1144 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
,
1148 bgp_withdraw(irfd
->peer
, p
, /* prefix */
1150 NULL
, /* attr, ignored */
1152 ZEBRA_ROUTE_VNC_DIRECT
,
1153 BGP_ROUTE_REDISTRIBUTE
,
1154 NULL
, /* RD not used for
1156 NULL
, 0, NULL
); /* tag not
1165 static void vnc_direct_add_rn_group_rd(struct bgp
*bgp
,
1166 struct rfapi_nve_group_cfg
*rfg
,
1167 struct agg_node
*rn
, struct attr
*attr
,
1168 afi_t afi
, struct rfapi_descriptor
*irfd
)
1171 struct bgp_path_info info
;
1174 const struct prefix
*p
= agg_node_get_prefix(rn
);
1176 if (irfd
== NULL
&& rfg
->type
!= RFAPI_GROUP_CFG_VRF
) {
1177 /* need new rfapi_handle, for peer strcture
1178 * -- based on vnc_add_vrf_prefi */
1179 assert(rfg
->rfd
== NULL
);
1181 if (!rfg
->rt_export_list
|| !rfg
->rfapi_import_table
) {
1182 vnc_zlog_debug_verbose(
1183 "%s: VRF \"%s\" is missing RT import/export configuration.",
1184 __func__
, rfg
->name
);
1187 if (!rfg
->rd
.prefixlen
) {
1188 vnc_zlog_debug_verbose(
1189 "%s: VRF \"%s\" is missing RD configuration.",
1190 __func__
, rfg
->name
);
1193 if (rfg
->label
> MPLS_LABEL_MAX
) {
1194 vnc_zlog_debug_verbose(
1195 "%s: VRF \"%s\" is missing default label configuration.",
1196 __func__
, rfg
->name
);
1200 irfd
= XCALLOC(MTYPE_RFAPI_DESC
,
1201 sizeof(struct rfapi_descriptor
));
1205 * leave most fields empty as will get from (dynamic) config
1208 irfd
->default_tunneltype_option
.type
= BGP_ENCAP_TYPE_MPLS
;
1210 if (rfg
->vn_prefix
.family
1211 && !CHECK_FLAG(rfg
->flags
, RFAPI_RFG_VPN_NH_SELF
)) {
1212 rfapiQprefix2Raddr(&rfg
->vn_prefix
, &irfd
->vn_addr
);
1214 memset(&irfd
->vn_addr
, 0, sizeof(struct rfapi_ip_addr
));
1215 irfd
->vn_addr
.addr_family
= AF_INET
;
1216 irfd
->vn_addr
.addr
.v4
= bgp
->router_id
;
1218 irfd
->un_addr
= irfd
->vn_addr
; /* sigh, need something in UN for
1220 vnc_zlog_debug_verbose("%s: Opening RFD for VRF %s", __func__
,
1222 rfapi_init_and_open(bgp
, irfd
, rfg
);
1225 if (irfd
== NULL
|| rfapiRaddr2Qprefix(&irfd
->vn_addr
, &nhp
))
1229 * Construct new attribute set with NVE's VN
1231 * nexthop and without Tunnel Encap attr
1233 if (encap_attr_export(&hattr
, attr
, &nhp
, rn
))
1236 if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD
)) {
1237 vnc_zlog_debug_any("%s: attr follows", __func__
);
1238 rfapiPrintAttrPtrs(NULL
, attr
);
1239 vnc_zlog_debug_any("%s: hattr follows", __func__
);
1240 rfapiPrintAttrPtrs(NULL
, &hattr
);
1243 if (rfg
->routemap_export_bgp
) {
1244 route_map_result_t ret
;
1246 info
.peer
= irfd
->peer
;
1248 ret
= route_map_apply(rfg
->routemap_export_bgp
, p
, &info
);
1249 if (ret
== RMAP_DENYMATCH
) {
1250 bgp_attr_flush(&hattr
);
1251 vnc_zlog_debug_verbose(
1252 "%s: route map says DENY, so not calling bgp_update",
1258 if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD
)) {
1259 vnc_zlog_debug_any("%s: hattr after route_map_apply:",
1261 rfapiPrintAttrPtrs(NULL
, &hattr
);
1263 iattr
= bgp_attr_intern(&hattr
);
1264 bgp_attr_flush(&hattr
);
1266 bgp_update(irfd
->peer
, p
, /* prefix */
1268 iattr
, /* bgp_update copies it */
1269 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
1270 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
1271 NULL
, /* tag not used for unicast */
1272 0, 0, NULL
); /* EVPN not used */
1274 bgp_attr_unintern(&iattr
);
1280 * Caller is responsible for ensuring that the specified nve-group
1281 * is actually part of the list of exported nve groups.
1283 static void vnc_direct_bgp_add_group_afi(struct bgp
*bgp
,
1284 struct rfapi_nve_group_cfg
*rfg
,
1287 struct agg_table
*rt
= NULL
;
1288 struct agg_node
*rn
;
1289 struct attr attr
= {0};
1290 struct rfapi_import_table
*import_table
;
1292 vnc_zlog_debug_verbose("%s: entry", __func__
);
1294 import_table
= rfg
->rfapi_import_table
;
1295 if (!import_table
) {
1296 vnc_zlog_debug_verbose(
1297 "%s: import table not defined, returning", __func__
);
1301 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
1302 rt
= import_table
->imported_vpn
[afi
];
1304 flog_err(EC_LIB_DEVELOPMENT
, "%s: bad afi %d", __func__
, afi
);
1308 if (!rfg
->nves
&& rfg
->type
!= RFAPI_GROUP_CFG_VRF
) {
1309 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__
);
1313 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
1314 /* TBD set some configured med, see add_vnc_route() */
1317 * Walk the NVE-Group's VNC Import table
1319 for (rn
= agg_route_top(rt
); rn
; rn
= agg_route_next(rn
)) {
1322 const struct prefix
*p
= agg_node_get_prefix(rn
);
1323 struct listnode
*ln
;
1326 * per-nve-group prefix list check
1328 if (rfg
->plist_export_bgp
[afi
]) {
1329 if (prefix_list_apply(
1330 rfg
->plist_export_bgp
[afi
], p
)
1335 if (rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
1336 vnc_direct_add_rn_group_rd(bgp
, rfg
, rn
, &attr
,
1340 * - but consistent with rest of function
1345 * For each NVE that is assigned to the export nve
1347 * a route with that NVE as its next hop
1349 for (ln
= listhead(rfg
->nves
); ln
;
1350 ln
= listnextnode(ln
)) {
1351 vnc_direct_add_rn_group_rd(bgp
, rfg
, rn
, &attr
,
1358 aspath_unintern(&attr
.aspath
);
1363 * Caller is responsible for ensuring that the specified nve-group
1364 * is actually part of the list of exported nve groups.
1366 void vnc_direct_bgp_add_group(struct bgp
*bgp
, struct rfapi_nve_group_cfg
*rfg
)
1368 vnc_direct_bgp_add_group_afi(bgp
, rfg
, AFI_IP
);
1369 vnc_direct_bgp_add_group_afi(bgp
, rfg
, AFI_IP6
);
1372 static void vnc_direct_del_rn_group_rd(struct bgp
*bgp
,
1373 struct rfapi_nve_group_cfg
*rfg
,
1374 struct agg_node
*rn
, afi_t afi
,
1375 struct rfapi_descriptor
*irfd
)
1380 bgp_withdraw(irfd
->peer
, agg_node_get_prefix(rn
), /* prefix */
1382 NULL
, /* attr, ignored */
1383 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
1384 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
1385 NULL
, 0, NULL
); /* tag not used for unicast */
1390 * Caller is responsible for ensuring that the specified nve-group
1391 * was actually part of the list of exported nve groups.
1393 static void vnc_direct_bgp_del_group_afi(struct bgp
*bgp
,
1394 struct rfapi_nve_group_cfg
*rfg
,
1397 struct agg_table
*rt
= NULL
;
1398 struct agg_node
*rn
;
1399 struct rfapi_import_table
*import_table
;
1401 vnc_zlog_debug_verbose("%s: entry", __func__
);
1403 import_table
= rfg
->rfapi_import_table
;
1404 if (!import_table
) {
1405 vnc_zlog_debug_verbose(
1406 "%s: import table not defined, returning", __func__
);
1410 rt
= import_table
->imported_vpn
[afi
];
1412 if (!rfg
->nves
&& rfg
->type
!= RFAPI_GROUP_CFG_VRF
) {
1413 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__
);
1418 * Walk the NVE-Group's VNC Import table
1420 for (rn
= agg_route_top(rt
); rn
; rn
= agg_route_next(rn
))
1422 if (rfg
->type
== RFAPI_GROUP_CFG_VRF
)
1423 vnc_direct_del_rn_group_rd(bgp
, rfg
, rn
, afi
,
1426 struct listnode
*ln
;
1429 * For each NVE that is assigned to the export
1432 * a route with that NVE as its next hop
1434 for (ln
= listhead(rfg
->nves
); ln
;
1435 ln
= listnextnode(ln
))
1436 vnc_direct_del_rn_group_rd(
1444 * Caller is responsible for ensuring that the specified nve-group
1445 * was actually part of the list of exported nve groups.
1447 void vnc_direct_bgp_del_group(struct bgp
*bgp
, struct rfapi_nve_group_cfg
*rfg
)
1449 vnc_direct_bgp_del_group_afi(bgp
, rfg
, AFI_IP
);
1450 vnc_direct_bgp_del_group_afi(bgp
, rfg
, AFI_IP6
);
1453 void vnc_direct_bgp_reexport_group_afi(struct bgp
*bgp
,
1454 struct rfapi_nve_group_cfg
*rfg
,
1457 struct listnode
*node
;
1458 struct rfapi_rfg_name
*rfgn
;
1460 if (VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
1462 * look in the list of currently-exported groups
1464 for (ALL_LIST_ELEMENTS_RO(
1465 bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
1468 if (rfgn
->rfg
== rfg
) {
1470 * If it matches, reexport it
1472 vnc_direct_bgp_del_group_afi(bgp
, rfg
, afi
);
1473 vnc_direct_bgp_add_group_afi(bgp
, rfg
, afi
);
1481 static void vnc_direct_bgp_unexport_table(afi_t afi
, struct agg_table
*rt
,
1482 struct list
*nve_list
)
1486 struct agg_node
*rn
;
1488 for (rn
= agg_route_top(rt
); rn
; rn
= agg_route_next(rn
)) {
1492 struct listnode
*hln
;
1493 struct rfapi_descriptor
*irfd
;
1495 for (ALL_LIST_ELEMENTS_RO(nve_list
, hln
,
1498 bgp_withdraw(irfd
->peer
,
1499 agg_node_get_prefix(rn
),
1501 NULL
, /* attr, ignored */
1503 ZEBRA_ROUTE_VNC_DIRECT
,
1504 BGP_ROUTE_REDISTRIBUTE
,
1505 NULL
, /* RD not used for
1507 NULL
, 0, NULL
); /* tag not
1518 static void import_table_to_nve_list_direct_bgp(struct bgp
*bgp
,
1519 struct rfapi_import_table
*it
,
1523 struct listnode
*node
;
1524 struct rfapi_rfg_name
*rfgn
;
1527 * Loop over the list of NVE-Groups configured for
1528 * exporting to direct-bgp.
1530 * Build a list of NVEs that use this import table
1533 for (ALL_LIST_ELEMENTS_RO(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
1537 * If this NVE-Group's import table matches the current one
1539 if (rfgn
->rfg
&& rfgn
->rfg
->rfapi_import_table
== it
) {
1540 if (rfgn
->rfg
->nves
)
1541 nve_group_to_nve_list(rfgn
->rfg
, nves
, family
);
1542 else if (rfgn
->rfg
->rfd
1543 && rfgn
->rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
1546 listnode_add(*nves
, rfgn
->rfg
->rfd
);
1552 void vnc_direct_bgp_vpn_enable(struct bgp
*bgp
, afi_t afi
)
1554 struct listnode
*rfgn
;
1555 struct rfapi_nve_group_cfg
*rfg
;
1560 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
1561 vnc_zlog_debug_verbose(
1562 "%s: export-to-bgp group mode not enabled, skipping",
1567 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1568 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1573 * Policy is applied per-nve-group, so we need to iterate
1574 * over the groups to add everything.
1576 for (ALL_LIST_ELEMENTS_RO(bgp
->rfapi_cfg
->nve_groups_sequential
, rfgn
,
1580 * contains policy management
1582 vnc_direct_bgp_add_group_afi(bgp
, rfg
, afi
);
1587 void vnc_direct_bgp_vpn_disable(struct bgp
*bgp
, afi_t afi
)
1589 struct rfapi_import_table
*it
;
1590 uint8_t family
= afi2family(afi
);
1592 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
1598 vnc_zlog_debug_verbose("%s: rfapi not initialized", __func__
);
1602 if (!family
|| (afi
!= AFI_IP
&& afi
!= AFI_IP6
)) {
1603 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1607 for (it
= bgp
->rfapi
->imports
; it
; it
= it
->next
) {
1609 struct list
*nve_list
= NULL
;
1611 import_table_to_nve_list_direct_bgp(bgp
, it
, &nve_list
, family
);
1614 vnc_direct_bgp_unexport_table(
1615 afi
, it
->imported_vpn
[afi
], nve_list
);
1616 list_delete(&nve_list
);
1622 /***********************************************************************
1623 * Export methods that proxy nexthop END
1624 ***********************************************************************/
1627 /***********************************************************************
1628 * Export methods that preserve original nexthop BEGIN
1629 * rh = "registering nve"
1630 ***********************************************************************/
1634 * "Adding a Route" export process
1635 * TBD do we need to check bpi->type and bpi->sub_type here, or does
1638 void vnc_direct_bgp_rh_add_route(struct bgp
*bgp
, afi_t afi
,
1639 const struct prefix
*prefix
, struct peer
*peer
,
1642 struct vnc_export_info
*eti
;
1644 struct rfapi_cfg
*hc
;
1648 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of route node",
1653 /* check bgp redist flag for vnc direct ("vpn") routes */
1654 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
1655 vnc_zlog_debug_verbose(
1656 "%s: bgp redistribution of VNC direct routes is off",
1661 if (!(hc
= bgp
->rfapi_cfg
)) {
1662 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1667 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
1668 vnc_zlog_debug_verbose(
1669 "%s: export-to-bgp RH mode not enabled, skipping",
1677 if (hc
->plist_export_bgp
[afi
]) {
1678 if (prefix_list_apply(hc
->plist_export_bgp
[afi
], prefix
)
1684 * Construct new attribute set with NVE's VN addr as
1685 * nexthop and without Tunnel Encap attr
1687 if (encap_attr_export(&hattr
, attr
, NULL
, NULL
))
1689 if (hc
->routemap_export_bgp
) {
1690 struct bgp_path_info info
;
1691 route_map_result_t ret
;
1693 memset(&info
, 0, sizeof(info
));
1696 ret
= route_map_apply(hc
->routemap_export_bgp
, prefix
, &info
);
1697 if (ret
== RMAP_DENYMATCH
) {
1698 bgp_attr_flush(&hattr
);
1703 iattr
= bgp_attr_intern(&hattr
);
1704 bgp_attr_flush(&hattr
);
1707 * record route information that we will need to expire
1710 eti
= vnc_eti_get(bgp
, EXPORT_TYPE_BGP
, prefix
, peer
,
1711 ZEBRA_ROUTE_VNC_DIRECT_RH
, BGP_ROUTE_REDISTRIBUTE
);
1712 rfapiGetVncLifetime(attr
, &eti
->lifetime
);
1713 eti
->lifetime
= rfapiGetHolddownFromLifetime(eti
->lifetime
);
1716 * export expiration timer is already running on
1717 * this route: cancel it
1719 thread_cancel(&eti
->timer
);
1721 bgp_update(peer
, prefix
, /* prefix */
1723 iattr
, /* bgp_update copies this attr */
1724 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT_RH
,
1725 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
1726 NULL
, /* tag not used for unicast, EVPN neither */
1727 0, 0, NULL
); /* EVPN not used */
1728 bgp_attr_unintern(&iattr
);
1731 static int vncExportWithdrawTimer(struct thread
*t
)
1733 struct vnc_export_info
*eti
= t
->arg
;
1734 const struct prefix
*p
= agg_node_get_prefix(eti
->node
);
1737 * withdraw the route
1739 bgp_withdraw(eti
->peer
, p
, 0, /* addpath_id */
1740 NULL
, /* attr, ignored */
1741 family2afi(p
->family
), SAFI_UNICAST
, eti
->type
,
1742 eti
->subtype
, NULL
, /* RD not used for unicast */
1744 NULL
); /* tag not used for unicast, EVPN neither */
1749 vnc_eti_delete(eti
);
1755 * "Withdrawing a Route" export process
1756 * TBD do we need to check bpi->type and bpi->sub_type here, or does
1759 void vnc_direct_bgp_rh_del_route(struct bgp
*bgp
, afi_t afi
,
1760 const struct prefix
*prefix
, struct peer
*peer
)
1762 struct vnc_export_info
*eti
;
1765 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi route node",
1770 /* check bgp redist flag for vnc direct ("vpn") routes */
1771 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
1772 vnc_zlog_debug_verbose(
1773 "%s: bgp redistribution of VNC direct routes is off",
1778 if (!bgp
->rfapi_cfg
) {
1779 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1783 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
1784 vnc_zlog_debug_verbose(
1785 "%s: export-to-bgp group mode not enabled, skipping",
1790 eti
= vnc_eti_get(bgp
, EXPORT_TYPE_BGP
, prefix
, peer
,
1791 ZEBRA_ROUTE_VNC_DIRECT_RH
, BGP_ROUTE_REDISTRIBUTE
);
1793 if (!eti
->timer
&& eti
->lifetime
<= INT32_MAX
) {
1795 thread_add_timer(bm
->master
, vncExportWithdrawTimer
, eti
,
1796 eti
->lifetime
, &eti
->timer
);
1797 vnc_zlog_debug_verbose(
1798 "%s: set expiration timer for %u seconds", __func__
,
1804 void vnc_direct_bgp_rh_vpn_enable(struct bgp
*bgp
, afi_t afi
)
1806 struct prefix_rd prd
;
1807 struct bgp_dest
*pdest
;
1808 struct rfapi_cfg
*hc
;
1810 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
1815 if (!(hc
= bgp
->rfapi_cfg
))
1818 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
1819 vnc_zlog_debug_verbose(
1820 "%s: export of RH routes not enabled, skipping",
1825 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1826 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1831 * Go through the entire BGP VPN table and export to BGP unicast.
1834 vnc_zlog_debug_verbose("%s: starting RD loop", __func__
);
1836 /* Loop over all the RDs */
1837 for (pdest
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); pdest
;
1838 pdest
= bgp_route_next(pdest
)) {
1840 struct bgp_table
*table
;
1841 struct bgp_dest
*dest
;
1842 struct bgp_path_info
*ri
;
1843 const struct prefix
*pdest_p
= bgp_dest_get_prefix(pdest
);
1845 memset(&prd
, 0, sizeof(prd
));
1846 prd
.family
= AF_UNSPEC
;
1848 memcpy(prd
.val
, pdest_p
->u
.val
, 8);
1850 /* This is the per-RD table of prefixes */
1851 table
= bgp_dest_get_bgp_table_info(pdest
);
1856 for (dest
= bgp_table_top(table
); dest
;
1857 dest
= bgp_route_next(dest
)) {
1858 const struct prefix
*dest_p
;
1861 * skip prefix list check if no routes here
1863 if (!bgp_dest_has_bgp_path_info_data(dest
))
1866 vnc_zlog_debug_verbose("%s: checking prefix %pBD",
1869 dest_p
= bgp_dest_get_prefix(dest
);
1874 if (hc
->plist_export_bgp
[afi
]) {
1875 if (prefix_list_apply(hc
->plist_export_bgp
[afi
],
1879 vnc_zlog_debug_verbose(
1880 "%s: prefix list says DENY",
1886 for (ri
= bgp_dest_get_bgp_path_info(dest
); ri
;
1889 vnc_zlog_debug_verbose("%s: ri->sub_type: %d",
1890 __func__
, ri
->sub_type
);
1892 if (ri
->sub_type
== BGP_ROUTE_NORMAL
1893 || ri
->sub_type
== BGP_ROUTE_RFP
) {
1895 struct vnc_export_info
*eti
;
1900 * Construct new attribute set with
1902 * nexthop and without Tunnel Encap attr
1904 if (encap_attr_export(&hattr
, ri
->attr
,
1906 vnc_zlog_debug_verbose(
1907 "%s: encap_attr_export failed",
1912 if (hc
->routemap_export_bgp
) {
1913 struct bgp_path_info info
;
1914 route_map_result_t ret
;
1916 memset(&info
, 0, sizeof(info
));
1917 info
.peer
= ri
->peer
;
1919 ret
= route_map_apply(
1920 hc
->routemap_export_bgp
,
1922 if (ret
== RMAP_DENYMATCH
) {
1923 bgp_attr_flush(&hattr
);
1924 vnc_zlog_debug_verbose(
1925 "%s: route map says DENY",
1931 iattr
= bgp_attr_intern(&hattr
);
1932 bgp_attr_flush(&hattr
);
1935 * record route information that we will
1940 bgp
, EXPORT_TYPE_BGP
, dest_p
,
1942 ZEBRA_ROUTE_VNC_DIRECT_RH
,
1943 BGP_ROUTE_REDISTRIBUTE
);
1944 rfapiGetVncLifetime(ri
->attr
,
1948 * export expiration timer is
1949 * already running on
1950 * this route: cancel it
1952 thread_cancel(&eti
->timer
);
1954 vnc_zlog_debug_verbose(
1955 "%s: calling bgp_update",
1959 ri
->peer
, dest_p
, /* prefix */
1961 iattr
, /* bgp_update copies
1963 AFI_IP
, SAFI_UNICAST
,
1964 ZEBRA_ROUTE_VNC_DIRECT_RH
,
1965 BGP_ROUTE_REDISTRIBUTE
, NULL
,
1966 /* RD not used for unicast */
1968 /* tag not used for unicast,
1970 0, 0, NULL
); /* EVPN not used */
1972 bgp_attr_unintern(&iattr
);
1979 void vnc_direct_bgp_rh_vpn_disable(struct bgp
*bgp
, afi_t afi
)
1981 struct bgp_dest
*dest
;
1983 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
1988 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1989 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1994 * Go through the entire BGP unicast table and remove routes that
1995 * originated from us
1997 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_UNICAST
]); dest
;
1998 dest
= bgp_route_next(dest
)) {
1999 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
2000 struct bgp_path_info
*ri
;
2001 struct bgp_path_info
*next
;
2003 for (ri
= bgp_dest_get_bgp_path_info(dest
), next
= NULL
; ri
;
2008 if (ri
->type
== ZEBRA_ROUTE_VNC_DIRECT_RH
2009 && ri
->sub_type
== BGP_ROUTE_REDISTRIBUTE
) {
2011 struct vnc_export_info
*eti
;
2014 * Delete routes immediately (no timer)
2016 eti
= vnc_eti_checktimer(
2017 bgp
, EXPORT_TYPE_BGP
, dest_p
, ri
->peer
,
2018 ZEBRA_ROUTE_VNC_DIRECT_RH
,
2019 BGP_ROUTE_REDISTRIBUTE
);
2021 thread_cancel(&eti
->timer
);
2022 vnc_eti_delete(eti
);
2025 bgp_withdraw(ri
->peer
, dest_p
, /* prefix */
2028 AFI_IP
, SAFI_UNICAST
,
2029 ZEBRA_ROUTE_VNC_DIRECT_RH
,
2030 BGP_ROUTE_REDISTRIBUTE
,
2031 NULL
, /* RD not used for unicast */
2032 NULL
, 0, NULL
); /* tag not used for
2040 void vnc_direct_bgp_rh_reexport(struct bgp
*bgp
, afi_t afi
)
2042 if (VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
2043 vnc_direct_bgp_rh_vpn_disable(bgp
, afi
);
2044 vnc_direct_bgp_rh_vpn_enable(bgp
, afi
);
2048 /***********************************************************************
2049 * Generic Export methods
2050 ***********************************************************************/
2053 * Assumes the correct mode bits are already turned on. Thus it
2054 * is OK to call this function from, e.g., bgp_redistribute_set()
2055 * without caring if export is enabled or not
2057 void vnc_export_bgp_enable(struct bgp
*bgp
, afi_t afi
)
2059 if (!bgp
->rfapi_cfg
)
2062 switch (bgp
->rfapi_cfg
->flags
& BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS
) {
2063 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE
:
2066 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP
:
2067 vnc_direct_bgp_vpn_enable(bgp
, afi
);
2070 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH
:
2071 vnc_direct_bgp_rh_vpn_enable(bgp
, afi
);
2074 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE
:
2075 vnc_direct_bgp_vpn_enable_ce(bgp
, afi
);
2080 void vnc_export_bgp_disable(struct bgp
*bgp
, afi_t afi
)
2082 if (!bgp
->rfapi_cfg
)
2085 switch (bgp
->rfapi_cfg
->flags
& BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS
) {
2086 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE
:
2089 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP
:
2090 vnc_direct_bgp_vpn_disable(bgp
, afi
);
2093 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH
:
2094 vnc_direct_bgp_rh_vpn_disable(bgp
, afi
);
2097 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE
:
2098 vnc_direct_bgp_vpn_disable_ce(bgp
, afi
);
2103 void vnc_export_bgp_prechange(struct bgp
*bgp
)
2105 vnc_export_bgp_disable(bgp
, AFI_IP
);
2106 vnc_export_bgp_disable(bgp
, AFI_IP6
);
2109 void vnc_export_bgp_postchange(struct bgp
*bgp
)
2111 vnc_export_bgp_enable(bgp
, AFI_IP
);
2112 vnc_export_bgp_enable(bgp
, AFI_IP6
);
2115 void vnc_direct_bgp_reexport(struct bgp
*bgp
, afi_t afi
)
2117 vnc_export_bgp_disable(bgp
, afi
);
2118 vnc_export_bgp_enable(bgp
, afi
);