1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright 2009-2016, LabN Consulting, L.L.C.
9 * File: vnc_export_bgp.c
10 * Purpose: Export routes to BGP directly (not via zebra)
13 #include "lib/zebra.h"
14 #include "lib/prefix.h"
15 #include "lib/agg_table.h"
18 #include "lib/stream.h"
19 #include "lib/memory.h"
20 #include "lib/linklist.h"
21 #include "lib/plist.h"
22 #include "lib/routemap.h"
23 #include "lib/lib_errors.h"
25 #include "bgpd/bgpd.h"
26 #include "bgpd/bgp_ecommunity.h"
27 #include "bgpd/bgp_attr.h"
28 #include "bgpd/bgp_aspath.h"
30 #include "bgpd/rfapi/vnc_export_bgp.h"
31 #include "bgpd/rfapi/vnc_export_bgp_p.h"
32 #include "bgpd/rfapi/vnc_export_table.h"
33 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
34 #include "bgpd/rfapi/rfapi.h"
35 #include "bgpd/rfapi/rfapi_import.h"
36 #include "bgpd/rfapi/rfapi_private.h"
37 #include "bgpd/rfapi/rfapi_backend.h"
38 #include "bgpd/rfapi/rfapi_vty.h"
39 #include "bgpd/rfapi/vnc_debug.h"
42 static void vnc_direct_add_rn_group_rd(struct bgp
*bgp
,
43 struct rfapi_nve_group_cfg
*rfg
,
44 struct agg_node
*rn
, struct attr
*attr
,
46 struct rfapi_descriptor
*irfd
);
48 /***********************************************************************
49 * Export methods that set nexthop to CE (from 5226 roo EC) BEGIN
50 ***********************************************************************/
53 * Memory allocation approach: make a ghost attr that
54 * has non-interned parts for the modifications. ghost attr
55 * memory is allocated by caller.
57 * - extract ce (=5226) EC and use as new nexthop
58 * - strip Tunnel Encap attr
61 static void encap_attr_export_ce(struct attr
*new, struct attr
*orig
,
62 struct prefix
*use_nexthop
)
65 * Make "new" a ghost attr copy of "orig"
67 memset(new, 0, sizeof(struct attr
));
73 switch (use_nexthop
->family
) {
75 new->nexthop
= use_nexthop
->u
.prefix4
;
76 new->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
; /* bytes */
77 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
81 new->mp_nexthop_global
= use_nexthop
->u
.prefix6
;
82 new->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
; /* bytes */
93 * Note that it will be deleted when BGP sends to any eBGP
94 * peer unless PEER_FLAG_MED_UNCHANGED is set:
96 * neighbor NEIGHBOR attribute-unchanged med
98 if (!CHECK_FLAG(new->flag
, BGP_ATTR_MULTI_EXIT_DISC
)) {
99 if (CHECK_FLAG(new->flag
, BGP_ATTR_LOCAL_PREF
)) {
100 if (new->local_pref
> 255)
103 new->med
= 255 - new->local_pref
;
105 new->med
= 255; /* shouldn't happen */
107 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
111 * "new" is now a ghost attr:
112 * - it owns an "extra" struct
113 * - it owns any non-interned parts
114 * - any references to interned parts are not counted
116 * Caller should, after using the attr, call:
117 * - bgp_attr_flush() to free non-interned parts
121 static int getce(struct bgp
*bgp
, struct attr
*attr
, struct prefix
*pfx_ce
)
125 uint16_t localadmin
= bgp
->rfapi_cfg
->resolve_nve_roo_local_admin
;
126 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
128 for (ecp
= ecomm
->val
, i
= 0; i
< ecomm
->size
;
129 ++i
, ecp
+= ECOMMUNITY_SIZE
) {
131 if (VNC_DEBUG(EXPORT_BGP_GETCE
)) {
133 "%s: %02x %02x %02x %02x %02x %02x %02x %02x",
134 __func__
, ecp
[0], ecp
[1], ecp
[2], ecp
[3],
135 ecp
[4], ecp
[5], ecp
[6], ecp
[7]);
141 if (ecp
[0] != 1 || ecp
[1] != 3) {
146 * Match local admin value?
148 if (ecp
[6] != ((localadmin
& 0xff00) >> 8)
149 || ecp
[7] != (localadmin
& 0xff))
152 memset((uint8_t *)pfx_ce
, 0, sizeof(*pfx_ce
));
153 memcpy(&pfx_ce
->u
.prefix4
, ecp
+ 2, 4);
154 pfx_ce
->family
= AF_INET
;
155 pfx_ce
->prefixlen
= IPV4_MAX_BITLEN
;
163 void vnc_direct_bgp_add_route_ce(struct bgp
*bgp
, struct agg_node
*rn
,
164 struct bgp_path_info
*bpi
)
166 struct attr
*attr
= bpi
->attr
;
167 struct peer
*peer
= bpi
->peer
;
168 const struct prefix
*prefix
= agg_node_get_prefix(rn
);
169 afi_t afi
= family2afi(prefix
->family
);
170 struct bgp_dest
*udest
;
171 struct bgp_path_info
*ubpi
;
174 struct prefix ce_nexthop
;
175 struct prefix post_routemap_nexthop
;
179 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of route node",
184 if ((bpi
->type
!= ZEBRA_ROUTE_BGP
)
185 || (bpi
->sub_type
!= BGP_ROUTE_NORMAL
186 && bpi
->sub_type
!= BGP_ROUTE_RFP
187 && bpi
->sub_type
!= BGP_ROUTE_STATIC
)) {
189 vnc_zlog_debug_verbose(
190 "%s: wrong route type/sub_type for export, skipping",
195 /* check bgp redist flag for vnc direct ("vpn") routes */
196 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
197 vnc_zlog_debug_verbose(
198 "%s: bgp redistribution of VNC direct routes is off",
203 if (!bgp
->rfapi_cfg
) {
204 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
209 if (!VNC_EXPORT_BGP_CE_ENABLED(bgp
->rfapi_cfg
)) {
210 vnc_zlog_debug_verbose(
211 "%s: export-to-bgp ce mode not enabled, skipping",
219 if (bgp
->rfapi_cfg
->plist_export_bgp
[afi
]) {
220 if (prefix_list_apply(bgp
->rfapi_cfg
->plist_export_bgp
[afi
],
223 vnc_zlog_debug_verbose(
224 "%s: prefix list denied, skipping", __func__
);
232 * This works only for IPv4 because IPv6 addresses are too big
233 * to fit in an extended community
235 if (getce(bgp
, attr
, &ce_nexthop
)) {
236 vnc_zlog_debug_verbose("%s: EC has no encoded CE, skipping",
242 * Is this route already represented in the unicast RIB?
243 * (look up prefix; compare route type, sub_type, peer, nexthop)
245 udest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
, SAFI_UNICAST
,
247 for (ubpi
= bgp_dest_get_bgp_path_info(udest
); ubpi
;
249 struct prefix unicast_nexthop
;
251 if (CHECK_FLAG(ubpi
->flags
, BGP_PATH_REMOVED
))
254 rfapiUnicastNexthop2Prefix(afi
, ubpi
->attr
, &unicast_nexthop
);
256 if (ubpi
->type
== ZEBRA_ROUTE_VNC_DIRECT
257 && ubpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
258 && ubpi
->peer
== peer
259 && prefix_same(&unicast_nexthop
, &ce_nexthop
)) {
261 vnc_zlog_debug_verbose(
262 "%s: already have matching exported unicast route, skipping",
269 * Construct new attribute set with CE addr as
270 * nexthop and without Tunnel Encap attr
272 encap_attr_export_ce(&hattr
, attr
, &ce_nexthop
);
273 if (bgp
->rfapi_cfg
->routemap_export_bgp
) {
274 struct bgp_path_info info
;
275 route_map_result_t ret
;
277 memset(&info
, 0, sizeof(info
));
280 ret
= route_map_apply(bgp
->rfapi_cfg
->routemap_export_bgp
,
282 if (ret
== RMAP_DENYMATCH
) {
283 bgp_attr_flush(&hattr
);
288 iattr
= bgp_attr_intern(&hattr
);
289 bgp_attr_flush(&hattr
);
292 * Rule: disallow route-map alteration of next-hop, because it
293 * would make it too difficult to keep track of the correspondence
294 * between VPN routes and unicast routes.
296 rfapiUnicastNexthop2Prefix(afi
, iattr
, &post_routemap_nexthop
);
298 if (!prefix_same(&ce_nexthop
, &post_routemap_nexthop
)) {
299 vnc_zlog_debug_verbose(
300 "%s: route-map modification of nexthop not allowed, skipping",
302 bgp_attr_unintern(&iattr
);
306 bgp_update(peer
, prefix
, 0, /* addpath_id */
307 iattr
, /* bgp_update copies this attr */
308 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
309 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
310 NULL
, 0, /* tag not used for unicast */
311 0, NULL
); /* EVPN not used */
312 bgp_attr_unintern(&iattr
);
317 * "Withdrawing a Route" export process
319 void vnc_direct_bgp_del_route_ce(struct bgp
*bgp
, struct agg_node
*rn
,
320 struct bgp_path_info
*bpi
)
322 const struct prefix
*p
= agg_node_get_prefix(rn
);
323 afi_t afi
= family2afi(p
->family
);
324 struct bgp_path_info
*vbpi
;
325 struct prefix ce_nexthop
;
328 flog_err(EC_LIB_DEVELOPMENT
, "%s: bad afi", __func__
);
332 /* check bgp redist flag for vnc direct ("vpn") routes */
333 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
334 vnc_zlog_debug_verbose(
335 "%s: bgp redistribution of VNC direct routes is off",
340 if (!bgp
->rfapi_cfg
) {
341 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
345 if (!VNC_EXPORT_BGP_CE_ENABLED(bgp
->rfapi_cfg
)) {
346 vnc_zlog_debug_verbose(
347 "%s: export-to-bgp ce mode not enabled, skipping",
354 * This works only for IPv4 because IPv6 addresses are too big
355 * to fit in an extended community
357 if (getce(bgp
, bpi
->attr
, &ce_nexthop
)) {
358 vnc_zlog_debug_verbose("%s: EC has no encoded CE, skipping",
364 * Look for other VPN routes with same prefix, same 5226 CE,
365 * same peer. If at least one is present, don't remove the
366 * route from the unicast RIB
369 for (vbpi
= rn
->info
; vbpi
; vbpi
= vbpi
->next
) {
373 if (bpi
->peer
!= vbpi
->peer
)
375 if (getce(bgp
, vbpi
->attr
, &ce
))
377 if (prefix_same(&ce
, &ce_nexthop
)) {
378 vnc_zlog_debug_verbose(
379 "%s: still have a route via CE, not deleting unicast",
388 bgp_withdraw(bpi
->peer
, p
, 0, /* addpath_id */
389 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
390 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
391 NULL
, 0, NULL
); /* tag not used for unicast */
394 static void vnc_direct_bgp_vpn_enable_ce(struct bgp
*bgp
, afi_t afi
)
397 struct bgp_path_info
*ri
;
399 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
404 if (!(bgp
->rfapi_cfg
))
407 if (!VNC_EXPORT_BGP_CE_ENABLED(bgp
->rfapi_cfg
)) {
408 vnc_zlog_debug_verbose(
409 "%s: export of CE routes not enabled, skipping",
414 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
415 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
420 * Go through entire ce import table and export to BGP unicast.
422 for (rn
= agg_route_top(bgp
->rfapi
->it_ce
->imported_vpn
[afi
]); rn
;
423 rn
= agg_route_next(rn
)) {
427 vnc_zlog_debug_verbose("%s: checking prefix %pRN", __func__
,
430 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
432 vnc_zlog_debug_verbose("%s: ri->sub_type: %d", __func__
,
435 if (ri
->sub_type
== BGP_ROUTE_NORMAL
436 || ri
->sub_type
== BGP_ROUTE_RFP
437 || ri
->sub_type
== BGP_ROUTE_STATIC
) {
439 vnc_direct_bgp_add_route_ce(bgp
, rn
, ri
);
445 static void vnc_direct_bgp_vpn_disable_ce(struct bgp
*bgp
, afi_t afi
)
447 struct bgp_dest
*dest
;
449 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
454 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
455 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
460 * Go through the entire BGP unicast table and remove routes that
463 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_UNICAST
]); dest
;
464 dest
= bgp_route_next(dest
)) {
466 struct bgp_path_info
*ri
;
467 struct bgp_path_info
*next
;
469 for (ri
= bgp_dest_get_bgp_path_info(dest
), next
= NULL
; ri
;
474 if (ri
->type
== ZEBRA_ROUTE_VNC_DIRECT
475 && ri
->sub_type
== BGP_ROUTE_REDISTRIBUTE
) {
478 ri
->peer
, bgp_dest_get_prefix(dest
),
480 AFI_IP
, SAFI_UNICAST
,
481 ZEBRA_ROUTE_VNC_DIRECT
,
482 BGP_ROUTE_REDISTRIBUTE
,
483 NULL
, /* RD not used for unicast */
485 NULL
); /* tag not used for unicast */
491 /***********************************************************************
492 * Export methods that set nexthop to CE (from 5226 roo EC) END
493 ***********************************************************************/
495 /***********************************************************************
496 * Export methods that proxy nexthop BEGIN
497 ***********************************************************************/
499 static struct ecommunity
*vnc_route_origin_ecom(struct agg_node
*rn
)
501 struct ecommunity
*new;
502 struct bgp_path_info
*bpi
;
507 new = ecommunity_new();
509 for (bpi
= rn
->info
; bpi
; bpi
= bpi
->next
) {
511 struct ecommunity_val roec
;
513 switch (BGP_MP_NEXTHOP_FAMILY(bpi
->attr
->mp_nexthop_len
)) {
515 memset(&roec
, 0, sizeof(roec
));
519 &bpi
->attr
->mp_nexthop_global_in
.s_addr
, 4);
522 ecommunity_add_val(new, &roec
, false, false);
525 /* No support for IPv6 addresses in extended communities
532 ecommunity_free(&new);
539 static struct ecommunity
*vnc_route_origin_ecom_single(struct in_addr
*origin
)
541 struct ecommunity
*new;
542 struct ecommunity_val roec
;
544 memset(&roec
, 0, sizeof(roec
));
547 memcpy(roec
.val
+ 2, &origin
->s_addr
, 4);
551 new = ecommunity_new();
552 ecommunity_add_val(new, &roec
, false, false);
555 ecommunity_free(&new);
564 * New memory allocation approach: make a ghost attr that
565 * has non-interned parts for the modifications. ghost attr
566 * memory is allocated by caller.
569 encap_attr_export(struct attr
*new, struct attr
*orig
,
570 struct prefix
*new_nexthop
,
571 struct agg_node
*rn
) /* for VN addrs for ecom list */
572 /* if rn is 0, use route's nexthop */
574 struct prefix orig_nexthop
;
575 struct prefix
*use_nexthop
;
576 static struct ecommunity
*ecom_ro
;
579 use_nexthop
= new_nexthop
;
581 use_nexthop
= &orig_nexthop
;
582 orig_nexthop
.family
=
583 BGP_MP_NEXTHOP_FAMILY(orig
->mp_nexthop_len
);
584 if (orig_nexthop
.family
== AF_INET
) {
585 orig_nexthop
.prefixlen
= IPV4_MAX_BITLEN
;
586 orig_nexthop
.u
.prefix4
= orig
->mp_nexthop_global_in
;
587 } else if (orig_nexthop
.family
== AF_INET6
) {
588 orig_nexthop
.prefixlen
= IPV6_MAX_BITLEN
;
589 orig_nexthop
.u
.prefix6
= orig
->mp_nexthop_global
;
591 return -1; /* FAIL - can't compute nexthop */
597 * Make "new" a ghost attr copy of "orig"
599 memset(new, 0, sizeof(struct attr
));
605 switch (use_nexthop
->family
) {
607 new->nexthop
= use_nexthop
->u
.prefix4
;
608 new->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
; /* bytes */
609 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
613 new->mp_nexthop_global
= use_nexthop
->u
.prefix6
;
614 new->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
; /* bytes */
623 ecom_ro
= vnc_route_origin_ecom(rn
);
625 /* TBD use lcom for IPv6 */
626 ecom_ro
= vnc_route_origin_ecom_single(&use_nexthop
->u
.prefix4
);
628 if (bgp_attr_get_ecommunity(new)) {
630 bgp_attr_set_ecommunity(
632 ecommunity_merge(ecom_ro
,
633 bgp_attr_get_ecommunity(new)));
635 bgp_attr_set_ecommunity(new, ecom_ro
);
641 * Note that it will be deleted when BGP sends to any eBGP
642 * peer unless PEER_FLAG_MED_UNCHANGED is set:
644 * neighbor NEIGHBOR attribute-unchanged med
646 if (!CHECK_FLAG(new->flag
, BGP_ATTR_MULTI_EXIT_DISC
)) {
647 if (CHECK_FLAG(new->flag
, BGP_ATTR_LOCAL_PREF
)) {
648 if (new->local_pref
> 255)
651 new->med
= 255 - new->local_pref
;
653 new->med
= 255; /* shouldn't happen */
655 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
659 * "new" is now a ghost attr:
660 * - it owns an "extra" struct
661 * - it owns any non-interned parts
662 * - any references to interned parts are not counted
664 * Caller should, after using the attr, call:
665 * - bgp_attr_flush() to free non-interned parts
672 * "Adding a Route" export process
674 void vnc_direct_bgp_add_prefix(struct bgp
*bgp
,
675 struct rfapi_import_table
*import_table
,
678 struct attr attr
= {0};
679 struct listnode
*node
, *nnode
;
680 struct rfapi_rfg_name
*rfgn
;
681 const struct prefix
*p
= agg_node_get_prefix(rn
);
682 afi_t afi
= family2afi(p
->family
);
685 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of route node",
690 /* check bgp redist flag for vnc direct ("vpn") routes */
691 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
692 vnc_zlog_debug_verbose(
693 "%s: bgp redistribution of VNC direct routes is off",
698 if (!bgp
->rfapi_cfg
) {
699 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
704 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
705 vnc_zlog_debug_verbose(
706 "%s: export-to-bgp group mode not enabled, skipping",
711 if (!listcount(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
)) {
712 vnc_zlog_debug_verbose(
713 "%s: no bgp-direct export nve group, skipping",
718 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
719 /* TBD set some configured med, see add_vnc_route() */
721 vnc_zlog_debug_verbose(
722 "%s: looping over nve-groups in direct-bgp export list",
725 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
731 * If nve group is not defined yet, skip it
737 * If the nve group uses a different import table, skip it
739 if (import_table
!= rfgn
->rfg
->rfapi_import_table
)
743 * if no NVEs currently associated with this group, skip it
745 if (rfgn
->rfg
->type
!= RFAPI_GROUP_CFG_VRF
&& !rfgn
->rfg
->nves
)
749 * per-nve-group prefix list check
751 if (rfgn
->rfg
->plist_export_bgp
[afi
]) {
752 if (prefix_list_apply(rfgn
->rfg
->plist_export_bgp
[afi
],
759 if (rfgn
->rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
760 vnc_direct_add_rn_group_rd(bgp
, rfgn
->rfg
, rn
, &attr
,
761 afi
, rfgn
->rfg
->rfd
);
764 * - but consistent with rest of function
769 * For each NVE that is assigned to the export nve group,
771 * a route with that NVE as its next hop
773 for (ln
= listhead(rfgn
->rfg
->nves
); ln
;
774 ln
= listnextnode(ln
)) {
775 vnc_direct_add_rn_group_rd(bgp
, rfgn
->rfg
, rn
, &attr
,
776 afi
, listgetdata(ln
));
780 aspath_unintern(&attr
.aspath
);
784 * "Withdrawing a Route" export process
786 void vnc_direct_bgp_del_prefix(struct bgp
*bgp
,
787 struct rfapi_import_table
*import_table
,
790 struct listnode
*node
, *nnode
;
791 struct rfapi_rfg_name
*rfgn
;
792 const struct prefix
*p
= agg_node_get_prefix(rn
);
793 afi_t afi
= family2afi(p
->family
);
796 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi route node",
801 /* check bgp redist flag for vnc direct ("vpn") routes */
802 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
803 vnc_zlog_debug_verbose(
804 "%s: bgp redistribution of VNC direct routes is off",
809 if (!bgp
->rfapi_cfg
) {
810 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
815 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
816 vnc_zlog_debug_verbose(
817 "%s: export-to-bgp group mode not enabled, skipping",
822 if (!listcount(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
)) {
823 vnc_zlog_debug_verbose(
824 "%s: no bgp-direct export nve group, skipping",
829 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
835 * If nve group is not defined yet, skip it
841 * if no NVEs currently associated with this group, skip it
843 if (rfgn
->rfg
->type
!= RFAPI_GROUP_CFG_VRF
&& !rfgn
->rfg
->nves
)
847 * If the nve group uses a different import table,
850 if (import_table
!= rfgn
->rfg
->rfapi_import_table
)
853 if (rfgn
->rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
855 struct rfapi_descriptor
*irfd
;
857 irfd
= rfgn
->rfg
->rfd
;
859 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
, &nhp
))
862 bgp_withdraw(irfd
->peer
, p
, /* prefix */
864 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
865 BGP_ROUTE_REDISTRIBUTE
,
866 NULL
, /* RD not used for unicast */
868 NULL
); /* tag not used for unicast */
871 * - but consistent with rest of function
876 * For each NVE that is assigned to the export nve group,
878 * a route with that NVE as its next hop
880 for (ln
= listhead(rfgn
->rfg
->nves
); ln
;
881 ln
= listnextnode(ln
)) {
884 struct rfapi_descriptor
*irfd
;
886 irfd
= listgetdata(ln
);
888 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
, &nhp
))
891 bgp_withdraw(irfd
->peer
, p
, /* prefix */
893 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
894 BGP_ROUTE_REDISTRIBUTE
,
895 NULL
, /* RD not used for unicast */
897 NULL
); /* tag not used for unicast */
902 void vnc_direct_bgp_add_nve(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
)
904 struct listnode
*node
, *nnode
;
905 struct rfapi_rfg_name
*rfgn
;
906 struct rfapi_nve_group_cfg
*rfg
= rfd
->rfg
;
907 afi_t afi
= family2afi(rfd
->vn_addr
.addr_family
);
910 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of nve vn addr",
917 if (!bgp
->rfapi_cfg
) {
918 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
922 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
923 vnc_zlog_debug_verbose(
924 "%s: export-to-bgp group mode not enabled, skipping",
929 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
930 vnc_zlog_debug_verbose(
931 "%s: bgp redistribution of VNC direct routes is off",
937 * Loop over the list of NVE-Groups configured for
938 * exporting to direct-bgp and see if this new NVE's
939 * group is among them.
941 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
945 * Yes, this NVE's group is configured for export to direct-bgp
947 if (rfgn
->rfg
== rfg
) {
949 struct agg_table
*rt
= NULL
;
951 struct attr attr
= {0};
952 struct rfapi_import_table
*import_table
;
955 import_table
= rfg
->rfapi_import_table
;
957 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
958 rt
= import_table
->imported_vpn
[afi
];
960 flog_err(EC_LIB_DEVELOPMENT
, "%s: bad afi %d",
965 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
966 /* TBD set some configured med, see add_vnc_route() */
969 * Walk the NVE-Group's VNC Import table
971 for (rn
= agg_route_top(rt
); rn
;
972 rn
= agg_route_next(rn
)) {
977 struct rfapi_descriptor
*irfd
= rfd
;
980 struct bgp_path_info info
;
981 const struct prefix
*p
=
982 agg_node_get_prefix(rn
);
984 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
,
989 * per-nve-group prefix list check
991 if (rfgn
->rfg
->plist_export_bgp
[afi
]) {
992 if (prefix_list_apply(
993 rfgn
->rfg
->plist_export_bgp
1003 * Construct new attribute set with
1005 * nexthop and without Tunnel Encap attr
1007 if (encap_attr_export(&hattr
, &attr
,
1011 if (rfgn
->rfg
->routemap_export_bgp
) {
1012 route_map_result_t ret
;
1013 info
.peer
= irfd
->peer
;
1015 ret
= route_map_apply(
1017 ->routemap_export_bgp
,
1019 if (ret
== RMAP_DENYMATCH
) {
1020 bgp_attr_flush(&hattr
);
1025 iattr
= bgp_attr_intern(&hattr
);
1026 bgp_attr_flush(&hattr
);
1028 irfd
->peer
, p
, /* prefix */
1030 iattr
, /* bgp_update copies
1033 ZEBRA_ROUTE_VNC_DIRECT
,
1034 BGP_ROUTE_REDISTRIBUTE
, NULL
,
1035 /* RD not used for unicast */
1037 /* tag not used for unicast */
1038 0, 0, NULL
); /* EVPN not used */
1040 bgp_attr_unintern(&iattr
);
1044 aspath_unintern(&attr
.aspath
);
1050 void vnc_direct_bgp_del_nve(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
)
1052 struct listnode
*node
, *nnode
;
1053 struct rfapi_rfg_name
*rfgn
;
1054 struct rfapi_nve_group_cfg
*rfg
= rfd
->rfg
;
1055 afi_t afi
= family2afi(rfd
->vn_addr
.addr_family
);
1058 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of nve vn addr",
1065 if (!bgp
->rfapi_cfg
) {
1066 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1070 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
1071 vnc_zlog_debug_verbose(
1072 "%s: export-to-bgp group mode not enabled, skipping",
1077 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
1078 vnc_zlog_debug_verbose(
1079 "%s: bgp redistribution of VNC direct routes is off",
1085 * Loop over the list of NVE-Groups configured for
1086 * exporting to direct-bgp and see if this new NVE's
1087 * group is among them.
1089 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
1093 * Yes, this NVE's group is configured for export to direct-bgp
1095 if (rfg
&& rfgn
->rfg
== rfg
) {
1097 struct agg_table
*rt
= NULL
;
1098 struct agg_node
*rn
;
1099 struct rfapi_import_table
*import_table
;
1101 import_table
= rfg
->rfapi_import_table
;
1103 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
1104 rt
= import_table
->imported_vpn
[afi
];
1106 flog_err(EC_LIB_DEVELOPMENT
, "%s: bad afi %d",
1112 * Walk the NVE-Group's VNC Import table
1114 for (rn
= agg_route_top(rt
); rn
;
1115 rn
= agg_route_next(rn
)) {
1118 const struct prefix
*p
=
1119 agg_node_get_prefix(rn
);
1121 struct rfapi_descriptor
*irfd
= rfd
;
1123 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
,
1127 bgp_withdraw(irfd
->peer
, p
, /* prefix */
1130 ZEBRA_ROUTE_VNC_DIRECT
,
1131 BGP_ROUTE_REDISTRIBUTE
,
1132 NULL
, /* RD not used for
1134 NULL
, 0, NULL
); /* tag not
1143 static void vnc_direct_add_rn_group_rd(struct bgp
*bgp
,
1144 struct rfapi_nve_group_cfg
*rfg
,
1145 struct agg_node
*rn
, struct attr
*attr
,
1146 afi_t afi
, struct rfapi_descriptor
*irfd
)
1149 struct bgp_path_info info
;
1152 const struct prefix
*p
= agg_node_get_prefix(rn
);
1154 if (irfd
== NULL
&& rfg
->type
!= RFAPI_GROUP_CFG_VRF
) {
1155 /* need new rfapi_handle, for peer strcture
1156 * -- based on vnc_add_vrf_prefi */
1157 assert(rfg
->rfd
== NULL
);
1159 if (!rfg
->rt_export_list
|| !rfg
->rfapi_import_table
) {
1160 vnc_zlog_debug_verbose(
1161 "%s: VRF \"%s\" is missing RT import/export configuration.",
1162 __func__
, rfg
->name
);
1165 if (!rfg
->rd
.prefixlen
) {
1166 vnc_zlog_debug_verbose(
1167 "%s: VRF \"%s\" is missing RD configuration.",
1168 __func__
, rfg
->name
);
1171 if (rfg
->label
> MPLS_LABEL_MAX
) {
1172 vnc_zlog_debug_verbose(
1173 "%s: VRF \"%s\" is missing default label configuration.",
1174 __func__
, rfg
->name
);
1178 irfd
= XCALLOC(MTYPE_RFAPI_DESC
,
1179 sizeof(struct rfapi_descriptor
));
1183 * leave most fields empty as will get from (dynamic) config
1186 irfd
->default_tunneltype_option
.type
= BGP_ENCAP_TYPE_MPLS
;
1188 if (rfg
->vn_prefix
.family
1189 && !CHECK_FLAG(rfg
->flags
, RFAPI_RFG_VPN_NH_SELF
)) {
1190 rfapiQprefix2Raddr(&rfg
->vn_prefix
, &irfd
->vn_addr
);
1192 memset(&irfd
->vn_addr
, 0, sizeof(struct rfapi_ip_addr
));
1193 irfd
->vn_addr
.addr_family
= AF_INET
;
1194 irfd
->vn_addr
.addr
.v4
= bgp
->router_id
;
1196 irfd
->un_addr
= irfd
->vn_addr
; /* sigh, need something in UN for
1198 vnc_zlog_debug_verbose("%s: Opening RFD for VRF %s", __func__
,
1200 rfapi_init_and_open(bgp
, irfd
, rfg
);
1203 if (irfd
== NULL
|| rfapiRaddr2Qprefix(&irfd
->vn_addr
, &nhp
))
1207 * Construct new attribute set with NVE's VN
1209 * nexthop and without Tunnel Encap attr
1211 if (encap_attr_export(&hattr
, attr
, &nhp
, rn
))
1214 if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD
)) {
1215 vnc_zlog_debug_any("%s: attr follows", __func__
);
1216 rfapiPrintAttrPtrs(NULL
, attr
);
1217 vnc_zlog_debug_any("%s: hattr follows", __func__
);
1218 rfapiPrintAttrPtrs(NULL
, &hattr
);
1221 if (rfg
->routemap_export_bgp
) {
1222 route_map_result_t ret
;
1224 info
.peer
= irfd
->peer
;
1226 ret
= route_map_apply(rfg
->routemap_export_bgp
, p
, &info
);
1227 if (ret
== RMAP_DENYMATCH
) {
1228 bgp_attr_flush(&hattr
);
1229 vnc_zlog_debug_verbose(
1230 "%s: route map says DENY, so not calling bgp_update",
1236 if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD
)) {
1237 vnc_zlog_debug_any("%s: hattr after route_map_apply:",
1239 rfapiPrintAttrPtrs(NULL
, &hattr
);
1241 iattr
= bgp_attr_intern(&hattr
);
1242 bgp_attr_flush(&hattr
);
1244 bgp_update(irfd
->peer
, p
, /* prefix */
1246 iattr
, /* bgp_update copies it */
1247 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
1248 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
1249 NULL
, /* tag not used for unicast */
1250 0, 0, NULL
); /* EVPN not used */
1252 bgp_attr_unintern(&iattr
);
1258 * Caller is responsible for ensuring that the specified nve-group
1259 * is actually part of the list of exported nve groups.
1261 static void vnc_direct_bgp_add_group_afi(struct bgp
*bgp
,
1262 struct rfapi_nve_group_cfg
*rfg
,
1265 struct agg_table
*rt
= NULL
;
1266 struct agg_node
*rn
;
1267 struct attr attr
= {0};
1268 struct rfapi_import_table
*import_table
;
1270 vnc_zlog_debug_verbose("%s: entry", __func__
);
1272 import_table
= rfg
->rfapi_import_table
;
1273 if (!import_table
) {
1274 vnc_zlog_debug_verbose(
1275 "%s: import table not defined, returning", __func__
);
1279 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
1280 rt
= import_table
->imported_vpn
[afi
];
1282 flog_err(EC_LIB_DEVELOPMENT
, "%s: bad afi %d", __func__
, afi
);
1286 if (!rfg
->nves
&& rfg
->type
!= RFAPI_GROUP_CFG_VRF
) {
1287 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__
);
1291 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
1292 /* TBD set some configured med, see add_vnc_route() */
1295 * Walk the NVE-Group's VNC Import table
1297 for (rn
= agg_route_top(rt
); rn
; rn
= agg_route_next(rn
)) {
1300 const struct prefix
*p
= agg_node_get_prefix(rn
);
1301 struct listnode
*ln
;
1304 * per-nve-group prefix list check
1306 if (rfg
->plist_export_bgp
[afi
]) {
1307 if (prefix_list_apply(
1308 rfg
->plist_export_bgp
[afi
], p
)
1313 if (rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
1314 vnc_direct_add_rn_group_rd(bgp
, rfg
, rn
, &attr
,
1318 * - but consistent with rest of function
1323 * For each NVE that is assigned to the export nve
1325 * a route with that NVE as its next hop
1327 for (ln
= listhead(rfg
->nves
); ln
;
1328 ln
= listnextnode(ln
)) {
1329 vnc_direct_add_rn_group_rd(bgp
, rfg
, rn
, &attr
,
1336 aspath_unintern(&attr
.aspath
);
1341 * Caller is responsible for ensuring that the specified nve-group
1342 * is actually part of the list of exported nve groups.
1344 void vnc_direct_bgp_add_group(struct bgp
*bgp
, struct rfapi_nve_group_cfg
*rfg
)
1346 vnc_direct_bgp_add_group_afi(bgp
, rfg
, AFI_IP
);
1347 vnc_direct_bgp_add_group_afi(bgp
, rfg
, AFI_IP6
);
1350 static void vnc_direct_del_rn_group_rd(struct bgp
*bgp
,
1351 struct rfapi_nve_group_cfg
*rfg
,
1352 struct agg_node
*rn
, afi_t afi
,
1353 struct rfapi_descriptor
*irfd
)
1358 bgp_withdraw(irfd
->peer
, agg_node_get_prefix(rn
), /* prefix */
1360 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
1361 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
1362 NULL
, 0, NULL
); /* tag not used for unicast */
1367 * Caller is responsible for ensuring that the specified nve-group
1368 * was actually part of the list of exported nve groups.
1370 static void vnc_direct_bgp_del_group_afi(struct bgp
*bgp
,
1371 struct rfapi_nve_group_cfg
*rfg
,
1374 struct agg_table
*rt
= NULL
;
1375 struct agg_node
*rn
;
1376 struct rfapi_import_table
*import_table
;
1378 vnc_zlog_debug_verbose("%s: entry", __func__
);
1380 import_table
= rfg
->rfapi_import_table
;
1381 if (!import_table
) {
1382 vnc_zlog_debug_verbose(
1383 "%s: import table not defined, returning", __func__
);
1387 rt
= import_table
->imported_vpn
[afi
];
1389 if (!rfg
->nves
&& rfg
->type
!= RFAPI_GROUP_CFG_VRF
) {
1390 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__
);
1395 * Walk the NVE-Group's VNC Import table
1397 for (rn
= agg_route_top(rt
); rn
; rn
= agg_route_next(rn
))
1399 if (rfg
->type
== RFAPI_GROUP_CFG_VRF
)
1400 vnc_direct_del_rn_group_rd(bgp
, rfg
, rn
, afi
,
1403 struct listnode
*ln
;
1406 * For each NVE that is assigned to the export
1409 * a route with that NVE as its next hop
1411 for (ln
= listhead(rfg
->nves
); ln
;
1412 ln
= listnextnode(ln
))
1413 vnc_direct_del_rn_group_rd(
1421 * Caller is responsible for ensuring that the specified nve-group
1422 * was actually part of the list of exported nve groups.
1424 void vnc_direct_bgp_del_group(struct bgp
*bgp
, struct rfapi_nve_group_cfg
*rfg
)
1426 vnc_direct_bgp_del_group_afi(bgp
, rfg
, AFI_IP
);
1427 vnc_direct_bgp_del_group_afi(bgp
, rfg
, AFI_IP6
);
1430 void vnc_direct_bgp_reexport_group_afi(struct bgp
*bgp
,
1431 struct rfapi_nve_group_cfg
*rfg
,
1434 struct listnode
*node
;
1435 struct rfapi_rfg_name
*rfgn
;
1437 if (VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
1439 * look in the list of currently-exported groups
1441 for (ALL_LIST_ELEMENTS_RO(
1442 bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
1445 if (rfgn
->rfg
== rfg
) {
1447 * If it matches, reexport it
1449 vnc_direct_bgp_del_group_afi(bgp
, rfg
, afi
);
1450 vnc_direct_bgp_add_group_afi(bgp
, rfg
, afi
);
1458 static void vnc_direct_bgp_unexport_table(afi_t afi
, struct agg_table
*rt
,
1459 struct list
*nve_list
)
1463 struct agg_node
*rn
;
1465 for (rn
= agg_route_top(rt
); rn
; rn
= agg_route_next(rn
)) {
1469 struct listnode
*hln
;
1470 struct rfapi_descriptor
*irfd
;
1472 for (ALL_LIST_ELEMENTS_RO(nve_list
, hln
,
1475 bgp_withdraw(irfd
->peer
,
1476 agg_node_get_prefix(rn
),
1479 ZEBRA_ROUTE_VNC_DIRECT
,
1480 BGP_ROUTE_REDISTRIBUTE
,
1481 NULL
, /* RD not used for
1483 NULL
, 0, NULL
); /* tag not
1494 static void import_table_to_nve_list_direct_bgp(struct bgp
*bgp
,
1495 struct rfapi_import_table
*it
,
1499 struct listnode
*node
;
1500 struct rfapi_rfg_name
*rfgn
;
1503 * Loop over the list of NVE-Groups configured for
1504 * exporting to direct-bgp.
1506 * Build a list of NVEs that use this import table
1509 for (ALL_LIST_ELEMENTS_RO(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
1513 * If this NVE-Group's import table matches the current one
1515 if (rfgn
->rfg
&& rfgn
->rfg
->rfapi_import_table
== it
) {
1516 if (rfgn
->rfg
->nves
)
1517 nve_group_to_nve_list(rfgn
->rfg
, nves
, family
);
1518 else if (rfgn
->rfg
->rfd
1519 && rfgn
->rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
1522 listnode_add(*nves
, rfgn
->rfg
->rfd
);
1528 void vnc_direct_bgp_vpn_enable(struct bgp
*bgp
, afi_t afi
)
1530 struct listnode
*rfgn
;
1531 struct rfapi_nve_group_cfg
*rfg
;
1536 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
1537 vnc_zlog_debug_verbose(
1538 "%s: export-to-bgp group mode not enabled, skipping",
1543 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1544 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1549 * Policy is applied per-nve-group, so we need to iterate
1550 * over the groups to add everything.
1552 for (ALL_LIST_ELEMENTS_RO(bgp
->rfapi_cfg
->nve_groups_sequential
, rfgn
,
1556 * contains policy management
1558 vnc_direct_bgp_add_group_afi(bgp
, rfg
, afi
);
1563 void vnc_direct_bgp_vpn_disable(struct bgp
*bgp
, afi_t afi
)
1565 struct rfapi_import_table
*it
;
1566 uint8_t family
= afi2family(afi
);
1568 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
1574 vnc_zlog_debug_verbose("%s: rfapi not initialized", __func__
);
1578 if (!family
|| (afi
!= AFI_IP
&& afi
!= AFI_IP6
)) {
1579 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1583 for (it
= bgp
->rfapi
->imports
; it
; it
= it
->next
) {
1585 struct list
*nve_list
= NULL
;
1587 import_table_to_nve_list_direct_bgp(bgp
, it
, &nve_list
, family
);
1590 vnc_direct_bgp_unexport_table(
1591 afi
, it
->imported_vpn
[afi
], nve_list
);
1592 list_delete(&nve_list
);
1598 /***********************************************************************
1599 * Export methods that proxy nexthop END
1600 ***********************************************************************/
1603 /***********************************************************************
1604 * Export methods that preserve original nexthop BEGIN
1605 * rh = "registering nve"
1606 ***********************************************************************/
1610 * "Adding a Route" export process
1611 * TBD do we need to check bpi->type and bpi->sub_type here, or does
1614 void vnc_direct_bgp_rh_add_route(struct bgp
*bgp
, afi_t afi
,
1615 const struct prefix
*prefix
, struct peer
*peer
,
1618 struct vnc_export_info
*eti
;
1620 struct rfapi_cfg
*hc
;
1624 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of route node",
1629 /* check bgp redist flag for vnc direct ("vpn") routes */
1630 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
1631 vnc_zlog_debug_verbose(
1632 "%s: bgp redistribution of VNC direct routes is off",
1637 if (!(hc
= bgp
->rfapi_cfg
)) {
1638 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1643 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
1644 vnc_zlog_debug_verbose(
1645 "%s: export-to-bgp RH mode not enabled, skipping",
1653 if (hc
->plist_export_bgp
[afi
]) {
1654 if (prefix_list_apply(hc
->plist_export_bgp
[afi
], prefix
)
1660 * Construct new attribute set with NVE's VN addr as
1661 * nexthop and without Tunnel Encap attr
1663 if (encap_attr_export(&hattr
, attr
, NULL
, NULL
))
1665 if (hc
->routemap_export_bgp
) {
1666 struct bgp_path_info info
;
1667 route_map_result_t ret
;
1669 memset(&info
, 0, sizeof(info
));
1672 ret
= route_map_apply(hc
->routemap_export_bgp
, prefix
, &info
);
1673 if (ret
== RMAP_DENYMATCH
) {
1674 bgp_attr_flush(&hattr
);
1679 iattr
= bgp_attr_intern(&hattr
);
1680 bgp_attr_flush(&hattr
);
1683 * record route information that we will need to expire
1686 eti
= vnc_eti_get(bgp
, EXPORT_TYPE_BGP
, prefix
, peer
,
1687 ZEBRA_ROUTE_VNC_DIRECT_RH
, BGP_ROUTE_REDISTRIBUTE
);
1688 rfapiGetVncLifetime(attr
, &eti
->lifetime
);
1689 eti
->lifetime
= rfapiGetHolddownFromLifetime(eti
->lifetime
);
1692 * export expiration timer is already running on
1693 * this route: cancel it
1695 THREAD_OFF(eti
->timer
);
1697 bgp_update(peer
, prefix
, /* prefix */
1699 iattr
, /* bgp_update copies this attr */
1700 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT_RH
,
1701 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
1702 NULL
, /* tag not used for unicast, EVPN neither */
1703 0, 0, NULL
); /* EVPN not used */
1704 bgp_attr_unintern(&iattr
);
1707 static void vncExportWithdrawTimer(struct thread
*t
)
1709 struct vnc_export_info
*eti
= THREAD_ARG(t
);
1710 const struct prefix
*p
= agg_node_get_prefix(eti
->node
);
1713 * withdraw the route
1715 bgp_withdraw(eti
->peer
, p
, 0, /* addpath_id */
1716 family2afi(p
->family
), SAFI_UNICAST
, eti
->type
,
1717 eti
->subtype
, NULL
, /* RD not used for unicast */
1719 NULL
); /* tag not used for unicast, EVPN neither */
1724 vnc_eti_delete(eti
);
1728 * "Withdrawing a Route" export process
1729 * TBD do we need to check bpi->type and bpi->sub_type here, or does
1732 void vnc_direct_bgp_rh_del_route(struct bgp
*bgp
, afi_t afi
,
1733 const struct prefix
*prefix
, struct peer
*peer
)
1735 struct vnc_export_info
*eti
;
1738 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi route node",
1743 /* check bgp redist flag for vnc direct ("vpn") routes */
1744 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
1745 vnc_zlog_debug_verbose(
1746 "%s: bgp redistribution of VNC direct routes is off",
1751 if (!bgp
->rfapi_cfg
) {
1752 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1756 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
1757 vnc_zlog_debug_verbose(
1758 "%s: export-to-bgp group mode not enabled, skipping",
1763 eti
= vnc_eti_get(bgp
, EXPORT_TYPE_BGP
, prefix
, peer
,
1764 ZEBRA_ROUTE_VNC_DIRECT_RH
, BGP_ROUTE_REDISTRIBUTE
);
1766 if (!eti
->timer
&& eti
->lifetime
<= INT32_MAX
) {
1768 thread_add_timer(bm
->master
, vncExportWithdrawTimer
, eti
,
1769 eti
->lifetime
, &eti
->timer
);
1770 vnc_zlog_debug_verbose(
1771 "%s: set expiration timer for %u seconds", __func__
,
1777 void vnc_direct_bgp_rh_vpn_enable(struct bgp
*bgp
, afi_t afi
)
1779 struct prefix_rd prd
;
1780 struct bgp_dest
*pdest
;
1781 struct rfapi_cfg
*hc
;
1783 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
1788 if (!(hc
= bgp
->rfapi_cfg
))
1791 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
1792 vnc_zlog_debug_verbose(
1793 "%s: export of RH routes not enabled, skipping",
1798 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1799 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1804 * Go through the entire BGP VPN table and export to BGP unicast.
1807 vnc_zlog_debug_verbose("%s: starting RD loop", __func__
);
1809 /* Loop over all the RDs */
1810 for (pdest
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); pdest
;
1811 pdest
= bgp_route_next(pdest
)) {
1813 struct bgp_table
*table
;
1814 struct bgp_dest
*dest
;
1815 struct bgp_path_info
*ri
;
1816 const struct prefix
*pdest_p
= bgp_dest_get_prefix(pdest
);
1818 memset(&prd
, 0, sizeof(prd
));
1819 prd
.family
= AF_UNSPEC
;
1821 memcpy(prd
.val
, pdest_p
->u
.val
, 8);
1823 /* This is the per-RD table of prefixes */
1824 table
= bgp_dest_get_bgp_table_info(pdest
);
1829 for (dest
= bgp_table_top(table
); dest
;
1830 dest
= bgp_route_next(dest
)) {
1831 const struct prefix
*dest_p
;
1834 * skip prefix list check if no routes here
1836 if (!bgp_dest_has_bgp_path_info_data(dest
))
1839 vnc_zlog_debug_verbose("%s: checking prefix %pBD",
1842 dest_p
= bgp_dest_get_prefix(dest
);
1847 if (hc
->plist_export_bgp
[afi
]) {
1848 if (prefix_list_apply(hc
->plist_export_bgp
[afi
],
1852 vnc_zlog_debug_verbose(
1853 "%s: prefix list says DENY",
1859 for (ri
= bgp_dest_get_bgp_path_info(dest
); ri
;
1862 vnc_zlog_debug_verbose("%s: ri->sub_type: %d",
1863 __func__
, ri
->sub_type
);
1865 if (ri
->sub_type
== BGP_ROUTE_NORMAL
1866 || ri
->sub_type
== BGP_ROUTE_RFP
) {
1868 struct vnc_export_info
*eti
;
1873 * Construct new attribute set with
1875 * nexthop and without Tunnel Encap attr
1877 if (encap_attr_export(&hattr
, ri
->attr
,
1879 vnc_zlog_debug_verbose(
1880 "%s: encap_attr_export failed",
1885 if (hc
->routemap_export_bgp
) {
1886 struct bgp_path_info info
;
1887 route_map_result_t ret
;
1889 memset(&info
, 0, sizeof(info
));
1890 info
.peer
= ri
->peer
;
1892 ret
= route_map_apply(
1893 hc
->routemap_export_bgp
,
1895 if (ret
== RMAP_DENYMATCH
) {
1896 bgp_attr_flush(&hattr
);
1897 vnc_zlog_debug_verbose(
1898 "%s: route map says DENY",
1904 iattr
= bgp_attr_intern(&hattr
);
1905 bgp_attr_flush(&hattr
);
1908 * record route information that we will
1913 bgp
, EXPORT_TYPE_BGP
, dest_p
,
1915 ZEBRA_ROUTE_VNC_DIRECT_RH
,
1916 BGP_ROUTE_REDISTRIBUTE
);
1917 rfapiGetVncLifetime(ri
->attr
,
1921 * export expiration timer is
1922 * already running on
1923 * this route: cancel it
1925 THREAD_OFF(eti
->timer
);
1927 vnc_zlog_debug_verbose(
1928 "%s: calling bgp_update",
1932 ri
->peer
, dest_p
, /* prefix */
1934 iattr
, /* bgp_update copies
1936 AFI_IP
, SAFI_UNICAST
,
1937 ZEBRA_ROUTE_VNC_DIRECT_RH
,
1938 BGP_ROUTE_REDISTRIBUTE
, NULL
,
1939 /* RD not used for unicast */
1941 /* tag not used for unicast,
1943 0, 0, NULL
); /* EVPN not used */
1945 bgp_attr_unintern(&iattr
);
1952 void vnc_direct_bgp_rh_vpn_disable(struct bgp
*bgp
, afi_t afi
)
1954 struct bgp_dest
*dest
;
1956 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
1961 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1962 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1967 * Go through the entire BGP unicast table and remove routes that
1968 * originated from us
1970 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_UNICAST
]); dest
;
1971 dest
= bgp_route_next(dest
)) {
1972 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
1973 struct bgp_path_info
*ri
;
1974 struct bgp_path_info
*next
;
1976 for (ri
= bgp_dest_get_bgp_path_info(dest
), next
= NULL
; ri
;
1981 if (ri
->type
== ZEBRA_ROUTE_VNC_DIRECT_RH
1982 && ri
->sub_type
== BGP_ROUTE_REDISTRIBUTE
) {
1984 struct vnc_export_info
*eti
;
1987 * Delete routes immediately (no timer)
1989 eti
= vnc_eti_checktimer(
1990 bgp
, EXPORT_TYPE_BGP
, dest_p
, ri
->peer
,
1991 ZEBRA_ROUTE_VNC_DIRECT_RH
,
1992 BGP_ROUTE_REDISTRIBUTE
);
1994 THREAD_OFF(eti
->timer
);
1995 vnc_eti_delete(eti
);
1998 bgp_withdraw(ri
->peer
, dest_p
, /* prefix */
2000 AFI_IP
, SAFI_UNICAST
,
2001 ZEBRA_ROUTE_VNC_DIRECT_RH
,
2002 BGP_ROUTE_REDISTRIBUTE
,
2003 NULL
, /* RD not used for unicast */
2004 NULL
, 0, NULL
); /* tag not used for
2012 void vnc_direct_bgp_rh_reexport(struct bgp
*bgp
, afi_t afi
)
2014 if (VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
2015 vnc_direct_bgp_rh_vpn_disable(bgp
, afi
);
2016 vnc_direct_bgp_rh_vpn_enable(bgp
, afi
);
2020 /***********************************************************************
2021 * Generic Export methods
2022 ***********************************************************************/
2025 * Assumes the correct mode bits are already turned on. Thus it
2026 * is OK to call this function from, e.g., bgp_redistribute_set()
2027 * without caring if export is enabled or not
2029 void vnc_export_bgp_enable(struct bgp
*bgp
, afi_t afi
)
2031 if (!bgp
->rfapi_cfg
)
2034 switch (bgp
->rfapi_cfg
->flags
& BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS
) {
2035 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE
:
2038 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP
:
2039 vnc_direct_bgp_vpn_enable(bgp
, afi
);
2042 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH
:
2043 vnc_direct_bgp_rh_vpn_enable(bgp
, afi
);
2046 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE
:
2047 vnc_direct_bgp_vpn_enable_ce(bgp
, afi
);
2052 void vnc_export_bgp_disable(struct bgp
*bgp
, afi_t afi
)
2054 if (!bgp
->rfapi_cfg
)
2057 switch (bgp
->rfapi_cfg
->flags
& BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS
) {
2058 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE
:
2061 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP
:
2062 vnc_direct_bgp_vpn_disable(bgp
, afi
);
2065 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH
:
2066 vnc_direct_bgp_rh_vpn_disable(bgp
, afi
);
2069 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE
:
2070 vnc_direct_bgp_vpn_disable_ce(bgp
, afi
);
2075 void vnc_export_bgp_prechange(struct bgp
*bgp
)
2077 vnc_export_bgp_disable(bgp
, AFI_IP
);
2078 vnc_export_bgp_disable(bgp
, AFI_IP6
);
2081 void vnc_export_bgp_postchange(struct bgp
*bgp
)
2083 vnc_export_bgp_enable(bgp
, AFI_IP
);
2084 vnc_export_bgp_enable(bgp
, AFI_IP6
);
2087 void vnc_direct_bgp_reexport(struct bgp
*bgp
, afi_t afi
)
2089 vnc_export_bgp_disable(bgp
, afi
);
2090 vnc_export_bgp_enable(bgp
, afi
);