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 NULL
, /* attr, ignored */
390 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
391 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
392 NULL
, 0, NULL
); /* tag not used for unicast */
395 static void vnc_direct_bgp_vpn_enable_ce(struct bgp
*bgp
, afi_t afi
)
398 struct bgp_path_info
*ri
;
400 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
405 if (!(bgp
->rfapi_cfg
))
408 if (!VNC_EXPORT_BGP_CE_ENABLED(bgp
->rfapi_cfg
)) {
409 vnc_zlog_debug_verbose(
410 "%s: export of CE routes not enabled, skipping",
415 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
416 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
421 * Go through entire ce import table and export to BGP unicast.
423 for (rn
= agg_route_top(bgp
->rfapi
->it_ce
->imported_vpn
[afi
]); rn
;
424 rn
= agg_route_next(rn
)) {
428 vnc_zlog_debug_verbose("%s: checking prefix %pRN", __func__
,
431 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
433 vnc_zlog_debug_verbose("%s: ri->sub_type: %d", __func__
,
436 if (ri
->sub_type
== BGP_ROUTE_NORMAL
437 || ri
->sub_type
== BGP_ROUTE_RFP
438 || ri
->sub_type
== BGP_ROUTE_STATIC
) {
440 vnc_direct_bgp_add_route_ce(bgp
, rn
, ri
);
446 static void vnc_direct_bgp_vpn_disable_ce(struct bgp
*bgp
, afi_t afi
)
448 struct bgp_dest
*dest
;
450 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
455 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
456 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
461 * Go through the entire BGP unicast table and remove routes that
464 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_UNICAST
]); dest
;
465 dest
= bgp_route_next(dest
)) {
467 struct bgp_path_info
*ri
;
468 struct bgp_path_info
*next
;
470 for (ri
= bgp_dest_get_bgp_path_info(dest
), next
= NULL
; ri
;
475 if (ri
->type
== ZEBRA_ROUTE_VNC_DIRECT
476 && ri
->sub_type
== BGP_ROUTE_REDISTRIBUTE
) {
479 ri
->peer
, bgp_dest_get_prefix(dest
),
482 AFI_IP
, SAFI_UNICAST
,
483 ZEBRA_ROUTE_VNC_DIRECT
,
484 BGP_ROUTE_REDISTRIBUTE
,
485 NULL
, /* RD not used for unicast */
487 NULL
); /* tag not used for unicast */
493 /***********************************************************************
494 * Export methods that set nexthop to CE (from 5226 roo EC) END
495 ***********************************************************************/
497 /***********************************************************************
498 * Export methods that proxy nexthop BEGIN
499 ***********************************************************************/
501 static struct ecommunity
*vnc_route_origin_ecom(struct agg_node
*rn
)
503 struct ecommunity
*new;
504 struct bgp_path_info
*bpi
;
509 new = ecommunity_new();
511 for (bpi
= rn
->info
; bpi
; bpi
= bpi
->next
) {
513 struct ecommunity_val roec
;
515 switch (BGP_MP_NEXTHOP_FAMILY(bpi
->attr
->mp_nexthop_len
)) {
517 memset(&roec
, 0, sizeof(roec
));
521 &bpi
->attr
->mp_nexthop_global_in
.s_addr
, 4);
524 ecommunity_add_val(new, &roec
, false, false);
527 /* No support for IPv6 addresses in extended communities
534 ecommunity_free(&new);
541 static struct ecommunity
*vnc_route_origin_ecom_single(struct in_addr
*origin
)
543 struct ecommunity
*new;
544 struct ecommunity_val roec
;
546 memset(&roec
, 0, sizeof(roec
));
549 memcpy(roec
.val
+ 2, &origin
->s_addr
, 4);
553 new = ecommunity_new();
554 ecommunity_add_val(new, &roec
, false, false);
557 ecommunity_free(&new);
566 * New memory allocation approach: make a ghost attr that
567 * has non-interned parts for the modifications. ghost attr
568 * memory is allocated by caller.
571 encap_attr_export(struct attr
*new, struct attr
*orig
,
572 struct prefix
*new_nexthop
,
573 struct agg_node
*rn
) /* for VN addrs for ecom list */
574 /* if rn is 0, use route's nexthop */
576 struct prefix orig_nexthop
;
577 struct prefix
*use_nexthop
;
578 static struct ecommunity
*ecom_ro
;
581 use_nexthop
= new_nexthop
;
583 use_nexthop
= &orig_nexthop
;
584 orig_nexthop
.family
=
585 BGP_MP_NEXTHOP_FAMILY(orig
->mp_nexthop_len
);
586 if (orig_nexthop
.family
== AF_INET
) {
587 orig_nexthop
.prefixlen
= IPV4_MAX_BITLEN
;
588 orig_nexthop
.u
.prefix4
= orig
->mp_nexthop_global_in
;
589 } else if (orig_nexthop
.family
== AF_INET6
) {
590 orig_nexthop
.prefixlen
= IPV6_MAX_BITLEN
;
591 orig_nexthop
.u
.prefix6
= orig
->mp_nexthop_global
;
593 return -1; /* FAIL - can't compute nexthop */
599 * Make "new" a ghost attr copy of "orig"
601 memset(new, 0, sizeof(struct attr
));
607 switch (use_nexthop
->family
) {
609 new->nexthop
= use_nexthop
->u
.prefix4
;
610 new->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
; /* bytes */
611 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
615 new->mp_nexthop_global
= use_nexthop
->u
.prefix6
;
616 new->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
; /* bytes */
625 ecom_ro
= vnc_route_origin_ecom(rn
);
627 /* TBD use lcom for IPv6 */
628 ecom_ro
= vnc_route_origin_ecom_single(&use_nexthop
->u
.prefix4
);
630 if (bgp_attr_get_ecommunity(new)) {
632 bgp_attr_set_ecommunity(
634 ecommunity_merge(ecom_ro
,
635 bgp_attr_get_ecommunity(new)));
637 bgp_attr_set_ecommunity(new, ecom_ro
);
643 * Note that it will be deleted when BGP sends to any eBGP
644 * peer unless PEER_FLAG_MED_UNCHANGED is set:
646 * neighbor NEIGHBOR attribute-unchanged med
648 if (!CHECK_FLAG(new->flag
, BGP_ATTR_MULTI_EXIT_DISC
)) {
649 if (CHECK_FLAG(new->flag
, BGP_ATTR_LOCAL_PREF
)) {
650 if (new->local_pref
> 255)
653 new->med
= 255 - new->local_pref
;
655 new->med
= 255; /* shouldn't happen */
657 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
661 * "new" is now a ghost attr:
662 * - it owns an "extra" struct
663 * - it owns any non-interned parts
664 * - any references to interned parts are not counted
666 * Caller should, after using the attr, call:
667 * - bgp_attr_flush() to free non-interned parts
674 * "Adding a Route" export process
676 void vnc_direct_bgp_add_prefix(struct bgp
*bgp
,
677 struct rfapi_import_table
*import_table
,
680 struct attr attr
= {0};
681 struct listnode
*node
, *nnode
;
682 struct rfapi_rfg_name
*rfgn
;
683 const struct prefix
*p
= agg_node_get_prefix(rn
);
684 afi_t afi
= family2afi(p
->family
);
687 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of route node",
692 /* check bgp redist flag for vnc direct ("vpn") routes */
693 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
694 vnc_zlog_debug_verbose(
695 "%s: bgp redistribution of VNC direct routes is off",
700 if (!bgp
->rfapi_cfg
) {
701 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
706 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
707 vnc_zlog_debug_verbose(
708 "%s: export-to-bgp group mode not enabled, skipping",
713 if (!listcount(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
)) {
714 vnc_zlog_debug_verbose(
715 "%s: no bgp-direct export nve group, skipping",
720 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
721 /* TBD set some configured med, see add_vnc_route() */
723 vnc_zlog_debug_verbose(
724 "%s: looping over nve-groups in direct-bgp export list",
727 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
733 * If nve group is not defined yet, skip it
739 * If the nve group uses a different import table, skip it
741 if (import_table
!= rfgn
->rfg
->rfapi_import_table
)
745 * if no NVEs currently associated with this group, skip it
747 if (rfgn
->rfg
->type
!= RFAPI_GROUP_CFG_VRF
&& !rfgn
->rfg
->nves
)
751 * per-nve-group prefix list check
753 if (rfgn
->rfg
->plist_export_bgp
[afi
]) {
754 if (prefix_list_apply(rfgn
->rfg
->plist_export_bgp
[afi
],
761 if (rfgn
->rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
762 vnc_direct_add_rn_group_rd(bgp
, rfgn
->rfg
, rn
, &attr
,
763 afi
, rfgn
->rfg
->rfd
);
766 * - but consistent with rest of function
771 * For each NVE that is assigned to the export nve group,
773 * a route with that NVE as its next hop
775 for (ln
= listhead(rfgn
->rfg
->nves
); ln
;
776 ln
= listnextnode(ln
)) {
777 vnc_direct_add_rn_group_rd(bgp
, rfgn
->rfg
, rn
, &attr
,
778 afi
, listgetdata(ln
));
782 aspath_unintern(&attr
.aspath
);
786 * "Withdrawing a Route" export process
788 void vnc_direct_bgp_del_prefix(struct bgp
*bgp
,
789 struct rfapi_import_table
*import_table
,
792 struct listnode
*node
, *nnode
;
793 struct rfapi_rfg_name
*rfgn
;
794 const struct prefix
*p
= agg_node_get_prefix(rn
);
795 afi_t afi
= family2afi(p
->family
);
798 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi route node",
803 /* check bgp redist flag for vnc direct ("vpn") routes */
804 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
805 vnc_zlog_debug_verbose(
806 "%s: bgp redistribution of VNC direct routes is off",
811 if (!bgp
->rfapi_cfg
) {
812 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
817 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
818 vnc_zlog_debug_verbose(
819 "%s: export-to-bgp group mode not enabled, skipping",
824 if (!listcount(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
)) {
825 vnc_zlog_debug_verbose(
826 "%s: no bgp-direct export nve group, skipping",
831 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
837 * If nve group is not defined yet, skip it
843 * if no NVEs currently associated with this group, skip it
845 if (rfgn
->rfg
->type
!= RFAPI_GROUP_CFG_VRF
&& !rfgn
->rfg
->nves
)
849 * If the nve group uses a different import table,
852 if (import_table
!= rfgn
->rfg
->rfapi_import_table
)
855 if (rfgn
->rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
857 struct rfapi_descriptor
*irfd
;
859 irfd
= rfgn
->rfg
->rfd
;
861 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
, &nhp
))
864 bgp_withdraw(irfd
->peer
, p
, /* prefix */
866 NULL
, /* attr, ignored */
867 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
868 BGP_ROUTE_REDISTRIBUTE
,
869 NULL
, /* RD not used for unicast */
871 NULL
); /* tag not used for unicast */
874 * - but consistent with rest of function
879 * For each NVE that is assigned to the export nve group,
881 * a route with that NVE as its next hop
883 for (ln
= listhead(rfgn
->rfg
->nves
); ln
;
884 ln
= listnextnode(ln
)) {
887 struct rfapi_descriptor
*irfd
;
889 irfd
= listgetdata(ln
);
891 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
, &nhp
))
894 bgp_withdraw(irfd
->peer
, p
, /* prefix */
896 NULL
, /* attr, ignored */
897 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
898 BGP_ROUTE_REDISTRIBUTE
,
899 NULL
, /* RD not used for unicast */
901 NULL
); /* tag not used for unicast */
906 void vnc_direct_bgp_add_nve(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
)
908 struct listnode
*node
, *nnode
;
909 struct rfapi_rfg_name
*rfgn
;
910 struct rfapi_nve_group_cfg
*rfg
= rfd
->rfg
;
911 afi_t afi
= family2afi(rfd
->vn_addr
.addr_family
);
914 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of nve vn addr",
921 if (!bgp
->rfapi_cfg
) {
922 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
926 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
927 vnc_zlog_debug_verbose(
928 "%s: export-to-bgp group mode not enabled, skipping",
933 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
934 vnc_zlog_debug_verbose(
935 "%s: bgp redistribution of VNC direct routes is off",
941 * Loop over the list of NVE-Groups configured for
942 * exporting to direct-bgp and see if this new NVE's
943 * group is among them.
945 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
949 * Yes, this NVE's group is configured for export to direct-bgp
951 if (rfgn
->rfg
== rfg
) {
953 struct agg_table
*rt
= NULL
;
955 struct attr attr
= {0};
956 struct rfapi_import_table
*import_table
;
959 import_table
= rfg
->rfapi_import_table
;
961 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
962 rt
= import_table
->imported_vpn
[afi
];
964 flog_err(EC_LIB_DEVELOPMENT
, "%s: bad afi %d",
969 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
970 /* TBD set some configured med, see add_vnc_route() */
973 * Walk the NVE-Group's VNC Import table
975 for (rn
= agg_route_top(rt
); rn
;
976 rn
= agg_route_next(rn
)) {
981 struct rfapi_descriptor
*irfd
= rfd
;
984 struct bgp_path_info info
;
985 const struct prefix
*p
=
986 agg_node_get_prefix(rn
);
988 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
,
993 * per-nve-group prefix list check
995 if (rfgn
->rfg
->plist_export_bgp
[afi
]) {
996 if (prefix_list_apply(
997 rfgn
->rfg
->plist_export_bgp
1007 * Construct new attribute set with
1009 * nexthop and without Tunnel Encap attr
1011 if (encap_attr_export(&hattr
, &attr
,
1015 if (rfgn
->rfg
->routemap_export_bgp
) {
1016 route_map_result_t ret
;
1017 info
.peer
= irfd
->peer
;
1019 ret
= route_map_apply(
1021 ->routemap_export_bgp
,
1023 if (ret
== RMAP_DENYMATCH
) {
1024 bgp_attr_flush(&hattr
);
1029 iattr
= bgp_attr_intern(&hattr
);
1030 bgp_attr_flush(&hattr
);
1032 irfd
->peer
, p
, /* prefix */
1034 iattr
, /* bgp_update copies
1037 ZEBRA_ROUTE_VNC_DIRECT
,
1038 BGP_ROUTE_REDISTRIBUTE
, NULL
,
1039 /* RD not used for unicast */
1041 /* tag not used for unicast */
1042 0, 0, NULL
); /* EVPN not used */
1044 bgp_attr_unintern(&iattr
);
1048 aspath_unintern(&attr
.aspath
);
1054 void vnc_direct_bgp_del_nve(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
)
1056 struct listnode
*node
, *nnode
;
1057 struct rfapi_rfg_name
*rfgn
;
1058 struct rfapi_nve_group_cfg
*rfg
= rfd
->rfg
;
1059 afi_t afi
= family2afi(rfd
->vn_addr
.addr_family
);
1062 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of nve vn addr",
1069 if (!bgp
->rfapi_cfg
) {
1070 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1074 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
1075 vnc_zlog_debug_verbose(
1076 "%s: export-to-bgp group mode not enabled, skipping",
1081 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
1082 vnc_zlog_debug_verbose(
1083 "%s: bgp redistribution of VNC direct routes is off",
1089 * Loop over the list of NVE-Groups configured for
1090 * exporting to direct-bgp and see if this new NVE's
1091 * group is among them.
1093 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
1097 * Yes, this NVE's group is configured for export to direct-bgp
1099 if (rfg
&& rfgn
->rfg
== rfg
) {
1101 struct agg_table
*rt
= NULL
;
1102 struct agg_node
*rn
;
1103 struct rfapi_import_table
*import_table
;
1105 import_table
= rfg
->rfapi_import_table
;
1107 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
1108 rt
= import_table
->imported_vpn
[afi
];
1110 flog_err(EC_LIB_DEVELOPMENT
, "%s: bad afi %d",
1116 * Walk the NVE-Group's VNC Import table
1118 for (rn
= agg_route_top(rt
); rn
;
1119 rn
= agg_route_next(rn
)) {
1122 const struct prefix
*p
=
1123 agg_node_get_prefix(rn
);
1125 struct rfapi_descriptor
*irfd
= rfd
;
1127 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
,
1131 bgp_withdraw(irfd
->peer
, p
, /* prefix */
1133 NULL
, /* attr, ignored */
1135 ZEBRA_ROUTE_VNC_DIRECT
,
1136 BGP_ROUTE_REDISTRIBUTE
,
1137 NULL
, /* RD not used for
1139 NULL
, 0, NULL
); /* tag not
1148 static void vnc_direct_add_rn_group_rd(struct bgp
*bgp
,
1149 struct rfapi_nve_group_cfg
*rfg
,
1150 struct agg_node
*rn
, struct attr
*attr
,
1151 afi_t afi
, struct rfapi_descriptor
*irfd
)
1154 struct bgp_path_info info
;
1157 const struct prefix
*p
= agg_node_get_prefix(rn
);
1159 if (irfd
== NULL
&& rfg
->type
!= RFAPI_GROUP_CFG_VRF
) {
1160 /* need new rfapi_handle, for peer strcture
1161 * -- based on vnc_add_vrf_prefi */
1162 assert(rfg
->rfd
== NULL
);
1164 if (!rfg
->rt_export_list
|| !rfg
->rfapi_import_table
) {
1165 vnc_zlog_debug_verbose(
1166 "%s: VRF \"%s\" is missing RT import/export configuration.",
1167 __func__
, rfg
->name
);
1170 if (!rfg
->rd
.prefixlen
) {
1171 vnc_zlog_debug_verbose(
1172 "%s: VRF \"%s\" is missing RD configuration.",
1173 __func__
, rfg
->name
);
1176 if (rfg
->label
> MPLS_LABEL_MAX
) {
1177 vnc_zlog_debug_verbose(
1178 "%s: VRF \"%s\" is missing default label configuration.",
1179 __func__
, rfg
->name
);
1183 irfd
= XCALLOC(MTYPE_RFAPI_DESC
,
1184 sizeof(struct rfapi_descriptor
));
1188 * leave most fields empty as will get from (dynamic) config
1191 irfd
->default_tunneltype_option
.type
= BGP_ENCAP_TYPE_MPLS
;
1193 if (rfg
->vn_prefix
.family
1194 && !CHECK_FLAG(rfg
->flags
, RFAPI_RFG_VPN_NH_SELF
)) {
1195 rfapiQprefix2Raddr(&rfg
->vn_prefix
, &irfd
->vn_addr
);
1197 memset(&irfd
->vn_addr
, 0, sizeof(struct rfapi_ip_addr
));
1198 irfd
->vn_addr
.addr_family
= AF_INET
;
1199 irfd
->vn_addr
.addr
.v4
= bgp
->router_id
;
1201 irfd
->un_addr
= irfd
->vn_addr
; /* sigh, need something in UN for
1203 vnc_zlog_debug_verbose("%s: Opening RFD for VRF %s", __func__
,
1205 rfapi_init_and_open(bgp
, irfd
, rfg
);
1208 if (irfd
== NULL
|| rfapiRaddr2Qprefix(&irfd
->vn_addr
, &nhp
))
1212 * Construct new attribute set with NVE's VN
1214 * nexthop and without Tunnel Encap attr
1216 if (encap_attr_export(&hattr
, attr
, &nhp
, rn
))
1219 if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD
)) {
1220 vnc_zlog_debug_any("%s: attr follows", __func__
);
1221 rfapiPrintAttrPtrs(NULL
, attr
);
1222 vnc_zlog_debug_any("%s: hattr follows", __func__
);
1223 rfapiPrintAttrPtrs(NULL
, &hattr
);
1226 if (rfg
->routemap_export_bgp
) {
1227 route_map_result_t ret
;
1229 info
.peer
= irfd
->peer
;
1231 ret
= route_map_apply(rfg
->routemap_export_bgp
, p
, &info
);
1232 if (ret
== RMAP_DENYMATCH
) {
1233 bgp_attr_flush(&hattr
);
1234 vnc_zlog_debug_verbose(
1235 "%s: route map says DENY, so not calling bgp_update",
1241 if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD
)) {
1242 vnc_zlog_debug_any("%s: hattr after route_map_apply:",
1244 rfapiPrintAttrPtrs(NULL
, &hattr
);
1246 iattr
= bgp_attr_intern(&hattr
);
1247 bgp_attr_flush(&hattr
);
1249 bgp_update(irfd
->peer
, p
, /* prefix */
1251 iattr
, /* bgp_update copies it */
1252 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
1253 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
1254 NULL
, /* tag not used for unicast */
1255 0, 0, NULL
); /* EVPN not used */
1257 bgp_attr_unintern(&iattr
);
1263 * Caller is responsible for ensuring that the specified nve-group
1264 * is actually part of the list of exported nve groups.
1266 static void vnc_direct_bgp_add_group_afi(struct bgp
*bgp
,
1267 struct rfapi_nve_group_cfg
*rfg
,
1270 struct agg_table
*rt
= NULL
;
1271 struct agg_node
*rn
;
1272 struct attr attr
= {0};
1273 struct rfapi_import_table
*import_table
;
1275 vnc_zlog_debug_verbose("%s: entry", __func__
);
1277 import_table
= rfg
->rfapi_import_table
;
1278 if (!import_table
) {
1279 vnc_zlog_debug_verbose(
1280 "%s: import table not defined, returning", __func__
);
1284 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
1285 rt
= import_table
->imported_vpn
[afi
];
1287 flog_err(EC_LIB_DEVELOPMENT
, "%s: bad afi %d", __func__
, afi
);
1291 if (!rfg
->nves
&& rfg
->type
!= RFAPI_GROUP_CFG_VRF
) {
1292 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__
);
1296 bgp_attr_default_set(&attr
, bgp
, BGP_ORIGIN_INCOMPLETE
);
1297 /* TBD set some configured med, see add_vnc_route() */
1300 * Walk the NVE-Group's VNC Import table
1302 for (rn
= agg_route_top(rt
); rn
; rn
= agg_route_next(rn
)) {
1305 const struct prefix
*p
= agg_node_get_prefix(rn
);
1306 struct listnode
*ln
;
1309 * per-nve-group prefix list check
1311 if (rfg
->plist_export_bgp
[afi
]) {
1312 if (prefix_list_apply(
1313 rfg
->plist_export_bgp
[afi
], p
)
1318 if (rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
1319 vnc_direct_add_rn_group_rd(bgp
, rfg
, rn
, &attr
,
1323 * - but consistent with rest of function
1328 * For each NVE that is assigned to the export nve
1330 * a route with that NVE as its next hop
1332 for (ln
= listhead(rfg
->nves
); ln
;
1333 ln
= listnextnode(ln
)) {
1334 vnc_direct_add_rn_group_rd(bgp
, rfg
, rn
, &attr
,
1341 aspath_unintern(&attr
.aspath
);
1346 * Caller is responsible for ensuring that the specified nve-group
1347 * is actually part of the list of exported nve groups.
1349 void vnc_direct_bgp_add_group(struct bgp
*bgp
, struct rfapi_nve_group_cfg
*rfg
)
1351 vnc_direct_bgp_add_group_afi(bgp
, rfg
, AFI_IP
);
1352 vnc_direct_bgp_add_group_afi(bgp
, rfg
, AFI_IP6
);
1355 static void vnc_direct_del_rn_group_rd(struct bgp
*bgp
,
1356 struct rfapi_nve_group_cfg
*rfg
,
1357 struct agg_node
*rn
, afi_t afi
,
1358 struct rfapi_descriptor
*irfd
)
1363 bgp_withdraw(irfd
->peer
, agg_node_get_prefix(rn
), /* prefix */
1365 NULL
, /* attr, ignored */
1366 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
1367 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
1368 NULL
, 0, NULL
); /* tag not used for unicast */
1373 * Caller is responsible for ensuring that the specified nve-group
1374 * was actually part of the list of exported nve groups.
1376 static void vnc_direct_bgp_del_group_afi(struct bgp
*bgp
,
1377 struct rfapi_nve_group_cfg
*rfg
,
1380 struct agg_table
*rt
= NULL
;
1381 struct agg_node
*rn
;
1382 struct rfapi_import_table
*import_table
;
1384 vnc_zlog_debug_verbose("%s: entry", __func__
);
1386 import_table
= rfg
->rfapi_import_table
;
1387 if (!import_table
) {
1388 vnc_zlog_debug_verbose(
1389 "%s: import table not defined, returning", __func__
);
1393 rt
= import_table
->imported_vpn
[afi
];
1395 if (!rfg
->nves
&& rfg
->type
!= RFAPI_GROUP_CFG_VRF
) {
1396 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__
);
1401 * Walk the NVE-Group's VNC Import table
1403 for (rn
= agg_route_top(rt
); rn
; rn
= agg_route_next(rn
))
1405 if (rfg
->type
== RFAPI_GROUP_CFG_VRF
)
1406 vnc_direct_del_rn_group_rd(bgp
, rfg
, rn
, afi
,
1409 struct listnode
*ln
;
1412 * For each NVE that is assigned to the export
1415 * a route with that NVE as its next hop
1417 for (ln
= listhead(rfg
->nves
); ln
;
1418 ln
= listnextnode(ln
))
1419 vnc_direct_del_rn_group_rd(
1427 * Caller is responsible for ensuring that the specified nve-group
1428 * was actually part of the list of exported nve groups.
1430 void vnc_direct_bgp_del_group(struct bgp
*bgp
, struct rfapi_nve_group_cfg
*rfg
)
1432 vnc_direct_bgp_del_group_afi(bgp
, rfg
, AFI_IP
);
1433 vnc_direct_bgp_del_group_afi(bgp
, rfg
, AFI_IP6
);
1436 void vnc_direct_bgp_reexport_group_afi(struct bgp
*bgp
,
1437 struct rfapi_nve_group_cfg
*rfg
,
1440 struct listnode
*node
;
1441 struct rfapi_rfg_name
*rfgn
;
1443 if (VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
1445 * look in the list of currently-exported groups
1447 for (ALL_LIST_ELEMENTS_RO(
1448 bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
1451 if (rfgn
->rfg
== rfg
) {
1453 * If it matches, reexport it
1455 vnc_direct_bgp_del_group_afi(bgp
, rfg
, afi
);
1456 vnc_direct_bgp_add_group_afi(bgp
, rfg
, afi
);
1464 static void vnc_direct_bgp_unexport_table(afi_t afi
, struct agg_table
*rt
,
1465 struct list
*nve_list
)
1469 struct agg_node
*rn
;
1471 for (rn
= agg_route_top(rt
); rn
; rn
= agg_route_next(rn
)) {
1475 struct listnode
*hln
;
1476 struct rfapi_descriptor
*irfd
;
1478 for (ALL_LIST_ELEMENTS_RO(nve_list
, hln
,
1481 bgp_withdraw(irfd
->peer
,
1482 agg_node_get_prefix(rn
),
1484 NULL
, /* attr, ignored */
1486 ZEBRA_ROUTE_VNC_DIRECT
,
1487 BGP_ROUTE_REDISTRIBUTE
,
1488 NULL
, /* RD not used for
1490 NULL
, 0, NULL
); /* tag not
1501 static void import_table_to_nve_list_direct_bgp(struct bgp
*bgp
,
1502 struct rfapi_import_table
*it
,
1506 struct listnode
*node
;
1507 struct rfapi_rfg_name
*rfgn
;
1510 * Loop over the list of NVE-Groups configured for
1511 * exporting to direct-bgp.
1513 * Build a list of NVEs that use this import table
1516 for (ALL_LIST_ELEMENTS_RO(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
1520 * If this NVE-Group's import table matches the current one
1522 if (rfgn
->rfg
&& rfgn
->rfg
->rfapi_import_table
== it
) {
1523 if (rfgn
->rfg
->nves
)
1524 nve_group_to_nve_list(rfgn
->rfg
, nves
, family
);
1525 else if (rfgn
->rfg
->rfd
1526 && rfgn
->rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
1529 listnode_add(*nves
, rfgn
->rfg
->rfd
);
1535 void vnc_direct_bgp_vpn_enable(struct bgp
*bgp
, afi_t afi
)
1537 struct listnode
*rfgn
;
1538 struct rfapi_nve_group_cfg
*rfg
;
1543 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
1544 vnc_zlog_debug_verbose(
1545 "%s: export-to-bgp group mode not enabled, skipping",
1550 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1551 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1556 * Policy is applied per-nve-group, so we need to iterate
1557 * over the groups to add everything.
1559 for (ALL_LIST_ELEMENTS_RO(bgp
->rfapi_cfg
->nve_groups_sequential
, rfgn
,
1563 * contains policy management
1565 vnc_direct_bgp_add_group_afi(bgp
, rfg
, afi
);
1570 void vnc_direct_bgp_vpn_disable(struct bgp
*bgp
, afi_t afi
)
1572 struct rfapi_import_table
*it
;
1573 uint8_t family
= afi2family(afi
);
1575 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
1581 vnc_zlog_debug_verbose("%s: rfapi not initialized", __func__
);
1585 if (!family
|| (afi
!= AFI_IP
&& afi
!= AFI_IP6
)) {
1586 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1590 for (it
= bgp
->rfapi
->imports
; it
; it
= it
->next
) {
1592 struct list
*nve_list
= NULL
;
1594 import_table_to_nve_list_direct_bgp(bgp
, it
, &nve_list
, family
);
1597 vnc_direct_bgp_unexport_table(
1598 afi
, it
->imported_vpn
[afi
], nve_list
);
1599 list_delete(&nve_list
);
1605 /***********************************************************************
1606 * Export methods that proxy nexthop END
1607 ***********************************************************************/
1610 /***********************************************************************
1611 * Export methods that preserve original nexthop BEGIN
1612 * rh = "registering nve"
1613 ***********************************************************************/
1617 * "Adding a Route" export process
1618 * TBD do we need to check bpi->type and bpi->sub_type here, or does
1621 void vnc_direct_bgp_rh_add_route(struct bgp
*bgp
, afi_t afi
,
1622 const struct prefix
*prefix
, struct peer
*peer
,
1625 struct vnc_export_info
*eti
;
1627 struct rfapi_cfg
*hc
;
1631 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of route node",
1636 /* check bgp redist flag for vnc direct ("vpn") routes */
1637 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
1638 vnc_zlog_debug_verbose(
1639 "%s: bgp redistribution of VNC direct routes is off",
1644 if (!(hc
= bgp
->rfapi_cfg
)) {
1645 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1650 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
1651 vnc_zlog_debug_verbose(
1652 "%s: export-to-bgp RH mode not enabled, skipping",
1660 if (hc
->plist_export_bgp
[afi
]) {
1661 if (prefix_list_apply(hc
->plist_export_bgp
[afi
], prefix
)
1667 * Construct new attribute set with NVE's VN addr as
1668 * nexthop and without Tunnel Encap attr
1670 if (encap_attr_export(&hattr
, attr
, NULL
, NULL
))
1672 if (hc
->routemap_export_bgp
) {
1673 struct bgp_path_info info
;
1674 route_map_result_t ret
;
1676 memset(&info
, 0, sizeof(info
));
1679 ret
= route_map_apply(hc
->routemap_export_bgp
, prefix
, &info
);
1680 if (ret
== RMAP_DENYMATCH
) {
1681 bgp_attr_flush(&hattr
);
1686 iattr
= bgp_attr_intern(&hattr
);
1687 bgp_attr_flush(&hattr
);
1690 * record route information that we will need to expire
1693 eti
= vnc_eti_get(bgp
, EXPORT_TYPE_BGP
, prefix
, peer
,
1694 ZEBRA_ROUTE_VNC_DIRECT_RH
, BGP_ROUTE_REDISTRIBUTE
);
1695 rfapiGetVncLifetime(attr
, &eti
->lifetime
);
1696 eti
->lifetime
= rfapiGetHolddownFromLifetime(eti
->lifetime
);
1699 * export expiration timer is already running on
1700 * this route: cancel it
1702 THREAD_OFF(eti
->timer
);
1704 bgp_update(peer
, prefix
, /* prefix */
1706 iattr
, /* bgp_update copies this attr */
1707 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT_RH
,
1708 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
1709 NULL
, /* tag not used for unicast, EVPN neither */
1710 0, 0, NULL
); /* EVPN not used */
1711 bgp_attr_unintern(&iattr
);
1714 static void vncExportWithdrawTimer(struct thread
*t
)
1716 struct vnc_export_info
*eti
= THREAD_ARG(t
);
1717 const struct prefix
*p
= agg_node_get_prefix(eti
->node
);
1720 * withdraw the route
1722 bgp_withdraw(eti
->peer
, p
, 0, /* addpath_id */
1723 NULL
, /* attr, ignored */
1724 family2afi(p
->family
), SAFI_UNICAST
, eti
->type
,
1725 eti
->subtype
, NULL
, /* RD not used for unicast */
1727 NULL
); /* tag not used for unicast, EVPN neither */
1732 vnc_eti_delete(eti
);
1736 * "Withdrawing a Route" export process
1737 * TBD do we need to check bpi->type and bpi->sub_type here, or does
1740 void vnc_direct_bgp_rh_del_route(struct bgp
*bgp
, afi_t afi
,
1741 const struct prefix
*prefix
, struct peer
*peer
)
1743 struct vnc_export_info
*eti
;
1746 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi route node",
1751 /* check bgp redist flag for vnc direct ("vpn") routes */
1752 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
1753 vnc_zlog_debug_verbose(
1754 "%s: bgp redistribution of VNC direct routes is off",
1759 if (!bgp
->rfapi_cfg
) {
1760 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1764 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
1765 vnc_zlog_debug_verbose(
1766 "%s: export-to-bgp group mode not enabled, skipping",
1771 eti
= vnc_eti_get(bgp
, EXPORT_TYPE_BGP
, prefix
, peer
,
1772 ZEBRA_ROUTE_VNC_DIRECT_RH
, BGP_ROUTE_REDISTRIBUTE
);
1774 if (!eti
->timer
&& eti
->lifetime
<= INT32_MAX
) {
1776 thread_add_timer(bm
->master
, vncExportWithdrawTimer
, eti
,
1777 eti
->lifetime
, &eti
->timer
);
1778 vnc_zlog_debug_verbose(
1779 "%s: set expiration timer for %u seconds", __func__
,
1785 void vnc_direct_bgp_rh_vpn_enable(struct bgp
*bgp
, afi_t afi
)
1787 struct prefix_rd prd
;
1788 struct bgp_dest
*pdest
;
1789 struct rfapi_cfg
*hc
;
1791 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
1796 if (!(hc
= bgp
->rfapi_cfg
))
1799 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
1800 vnc_zlog_debug_verbose(
1801 "%s: export of RH routes not enabled, skipping",
1806 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1807 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1812 * Go through the entire BGP VPN table and export to BGP unicast.
1815 vnc_zlog_debug_verbose("%s: starting RD loop", __func__
);
1817 /* Loop over all the RDs */
1818 for (pdest
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); pdest
;
1819 pdest
= bgp_route_next(pdest
)) {
1821 struct bgp_table
*table
;
1822 struct bgp_dest
*dest
;
1823 struct bgp_path_info
*ri
;
1824 const struct prefix
*pdest_p
= bgp_dest_get_prefix(pdest
);
1826 memset(&prd
, 0, sizeof(prd
));
1827 prd
.family
= AF_UNSPEC
;
1829 memcpy(prd
.val
, pdest_p
->u
.val
, 8);
1831 /* This is the per-RD table of prefixes */
1832 table
= bgp_dest_get_bgp_table_info(pdest
);
1837 for (dest
= bgp_table_top(table
); dest
;
1838 dest
= bgp_route_next(dest
)) {
1839 const struct prefix
*dest_p
;
1842 * skip prefix list check if no routes here
1844 if (!bgp_dest_has_bgp_path_info_data(dest
))
1847 vnc_zlog_debug_verbose("%s: checking prefix %pBD",
1850 dest_p
= bgp_dest_get_prefix(dest
);
1855 if (hc
->plist_export_bgp
[afi
]) {
1856 if (prefix_list_apply(hc
->plist_export_bgp
[afi
],
1860 vnc_zlog_debug_verbose(
1861 "%s: prefix list says DENY",
1867 for (ri
= bgp_dest_get_bgp_path_info(dest
); ri
;
1870 vnc_zlog_debug_verbose("%s: ri->sub_type: %d",
1871 __func__
, ri
->sub_type
);
1873 if (ri
->sub_type
== BGP_ROUTE_NORMAL
1874 || ri
->sub_type
== BGP_ROUTE_RFP
) {
1876 struct vnc_export_info
*eti
;
1881 * Construct new attribute set with
1883 * nexthop and without Tunnel Encap attr
1885 if (encap_attr_export(&hattr
, ri
->attr
,
1887 vnc_zlog_debug_verbose(
1888 "%s: encap_attr_export failed",
1893 if (hc
->routemap_export_bgp
) {
1894 struct bgp_path_info info
;
1895 route_map_result_t ret
;
1897 memset(&info
, 0, sizeof(info
));
1898 info
.peer
= ri
->peer
;
1900 ret
= route_map_apply(
1901 hc
->routemap_export_bgp
,
1903 if (ret
== RMAP_DENYMATCH
) {
1904 bgp_attr_flush(&hattr
);
1905 vnc_zlog_debug_verbose(
1906 "%s: route map says DENY",
1912 iattr
= bgp_attr_intern(&hattr
);
1913 bgp_attr_flush(&hattr
);
1916 * record route information that we will
1921 bgp
, EXPORT_TYPE_BGP
, dest_p
,
1923 ZEBRA_ROUTE_VNC_DIRECT_RH
,
1924 BGP_ROUTE_REDISTRIBUTE
);
1925 rfapiGetVncLifetime(ri
->attr
,
1929 * export expiration timer is
1930 * already running on
1931 * this route: cancel it
1933 THREAD_OFF(eti
->timer
);
1935 vnc_zlog_debug_verbose(
1936 "%s: calling bgp_update",
1940 ri
->peer
, dest_p
, /* prefix */
1942 iattr
, /* bgp_update copies
1944 AFI_IP
, SAFI_UNICAST
,
1945 ZEBRA_ROUTE_VNC_DIRECT_RH
,
1946 BGP_ROUTE_REDISTRIBUTE
, NULL
,
1947 /* RD not used for unicast */
1949 /* tag not used for unicast,
1951 0, 0, NULL
); /* EVPN not used */
1953 bgp_attr_unintern(&iattr
);
1960 void vnc_direct_bgp_rh_vpn_disable(struct bgp
*bgp
, afi_t afi
)
1962 struct bgp_dest
*dest
;
1964 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
1969 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1970 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1975 * Go through the entire BGP unicast table and remove routes that
1976 * originated from us
1978 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_UNICAST
]); dest
;
1979 dest
= bgp_route_next(dest
)) {
1980 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
1981 struct bgp_path_info
*ri
;
1982 struct bgp_path_info
*next
;
1984 for (ri
= bgp_dest_get_bgp_path_info(dest
), next
= NULL
; ri
;
1989 if (ri
->type
== ZEBRA_ROUTE_VNC_DIRECT_RH
1990 && ri
->sub_type
== BGP_ROUTE_REDISTRIBUTE
) {
1992 struct vnc_export_info
*eti
;
1995 * Delete routes immediately (no timer)
1997 eti
= vnc_eti_checktimer(
1998 bgp
, EXPORT_TYPE_BGP
, dest_p
, ri
->peer
,
1999 ZEBRA_ROUTE_VNC_DIRECT_RH
,
2000 BGP_ROUTE_REDISTRIBUTE
);
2002 THREAD_OFF(eti
->timer
);
2003 vnc_eti_delete(eti
);
2006 bgp_withdraw(ri
->peer
, dest_p
, /* prefix */
2009 AFI_IP
, SAFI_UNICAST
,
2010 ZEBRA_ROUTE_VNC_DIRECT_RH
,
2011 BGP_ROUTE_REDISTRIBUTE
,
2012 NULL
, /* RD not used for unicast */
2013 NULL
, 0, NULL
); /* tag not used for
2021 void vnc_direct_bgp_rh_reexport(struct bgp
*bgp
, afi_t afi
)
2023 if (VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
2024 vnc_direct_bgp_rh_vpn_disable(bgp
, afi
);
2025 vnc_direct_bgp_rh_vpn_enable(bgp
, afi
);
2029 /***********************************************************************
2030 * Generic Export methods
2031 ***********************************************************************/
2034 * Assumes the correct mode bits are already turned on. Thus it
2035 * is OK to call this function from, e.g., bgp_redistribute_set()
2036 * without caring if export is enabled or not
2038 void vnc_export_bgp_enable(struct bgp
*bgp
, afi_t afi
)
2040 if (!bgp
->rfapi_cfg
)
2043 switch (bgp
->rfapi_cfg
->flags
& BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS
) {
2044 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE
:
2047 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP
:
2048 vnc_direct_bgp_vpn_enable(bgp
, afi
);
2051 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH
:
2052 vnc_direct_bgp_rh_vpn_enable(bgp
, afi
);
2055 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE
:
2056 vnc_direct_bgp_vpn_enable_ce(bgp
, afi
);
2061 void vnc_export_bgp_disable(struct bgp
*bgp
, afi_t afi
)
2063 if (!bgp
->rfapi_cfg
)
2066 switch (bgp
->rfapi_cfg
->flags
& BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS
) {
2067 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE
:
2070 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP
:
2071 vnc_direct_bgp_vpn_disable(bgp
, afi
);
2074 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH
:
2075 vnc_direct_bgp_rh_vpn_disable(bgp
, afi
);
2078 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE
:
2079 vnc_direct_bgp_vpn_disable_ce(bgp
, afi
);
2084 void vnc_export_bgp_prechange(struct bgp
*bgp
)
2086 vnc_export_bgp_disable(bgp
, AFI_IP
);
2087 vnc_export_bgp_disable(bgp
, AFI_IP6
);
2090 void vnc_export_bgp_postchange(struct bgp
*bgp
)
2092 vnc_export_bgp_enable(bgp
, AFI_IP
);
2093 vnc_export_bgp_enable(bgp
, AFI_IP6
);
2096 void vnc_direct_bgp_reexport(struct bgp
*bgp
, afi_t afi
)
2098 vnc_export_bgp_disable(bgp
, afi
);
2099 vnc_export_bgp_enable(bgp
, afi
);