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
));
81 bgp_attr_dup(new, orig
);
86 switch (use_nexthop
->family
) {
88 new->nexthop
= use_nexthop
->u
.prefix4
;
89 new->mp_nexthop_len
= 4; /* 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
= 16; /* 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
;
140 for (ecp
= attr
->ecommunity
->val
, i
= 0; i
< attr
->ecommunity
->size
;
141 ++i
, ecp
+= ECOMMUNITY_SIZE
) {
143 if (VNC_DEBUG(EXPORT_BGP_GETCE
)) {
145 "%s: %02x %02x %02x %02x %02x %02x %02x %02x",
146 __func__
, ecp
[0], ecp
[1], ecp
[2], ecp
[3],
147 ecp
[4], ecp
[5], ecp
[6], ecp
[7]);
153 if (ecp
[0] != 1 || ecp
[1] != 3) {
158 * Match local admin value?
160 if (ecp
[6] != ((localadmin
& 0xff00) >> 8)
161 || ecp
[7] != (localadmin
& 0xff))
164 memset((uint8_t *)pfx_ce
, 0, sizeof(*pfx_ce
));
165 memcpy(&pfx_ce
->u
.prefix4
, ecp
+ 2, 4);
166 pfx_ce
->family
= AF_INET
;
167 pfx_ce
->prefixlen
= 32;
175 void vnc_direct_bgp_add_route_ce(struct bgp
*bgp
, struct agg_node
*rn
,
178 struct attr
*attr
= bi
->attr
;
179 struct peer
*peer
= bi
->peer
;
180 struct prefix
*prefix
= &rn
->p
;
181 afi_t afi
= family2afi(prefix
->family
);
182 struct bgp_node
*urn
;
183 struct bgp_info
*ubi
;
186 struct prefix ce_nexthop
;
187 struct prefix post_routemap_nexthop
;
191 flog_err(EC_LIB_DEVELOPMENT
,
192 "%s: can't get afi of route node", __func__
);
196 if ((bi
->type
!= ZEBRA_ROUTE_BGP
)
197 || (bi
->sub_type
!= BGP_ROUTE_NORMAL
198 && bi
->sub_type
!= BGP_ROUTE_RFP
199 && bi
->sub_type
!= BGP_ROUTE_STATIC
)) {
201 vnc_zlog_debug_verbose(
202 "%s: wrong route type/sub_type for export, skipping",
207 /* check bgp redist flag for vnc direct ("vpn") routes */
208 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
209 vnc_zlog_debug_verbose(
210 "%s: bgp redistribution of VNC direct routes is off",
215 if (!bgp
->rfapi_cfg
) {
216 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
221 if (!VNC_EXPORT_BGP_CE_ENABLED(bgp
->rfapi_cfg
)) {
222 vnc_zlog_debug_verbose(
223 "%s: export-to-bgp ce mode not enabled, skipping",
231 if (bgp
->rfapi_cfg
->plist_export_bgp
[afi
]) {
232 if (prefix_list_apply(bgp
->rfapi_cfg
->plist_export_bgp
[afi
],
235 vnc_zlog_debug_verbose(
236 "%s: prefix list denied, skipping", __func__
);
244 * This works only for IPv4 because IPv6 addresses are too big
245 * to fit in an extended community
247 if (getce(bgp
, attr
, &ce_nexthop
)) {
248 vnc_zlog_debug_verbose("%s: EC has no encoded CE, skipping",
254 * Is this route already represented in the unicast RIB?
255 * (look up prefix; compare route type, sub_type, peer, nexthop)
257 urn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
, SAFI_UNICAST
,
259 for (ubi
= urn
->info
; ubi
; ubi
= ubi
->next
) {
260 struct prefix unicast_nexthop
;
262 if (CHECK_FLAG(ubi
->flags
, BGP_INFO_REMOVED
))
265 rfapiUnicastNexthop2Prefix(afi
, ubi
->attr
, &unicast_nexthop
);
267 if (ubi
->type
== ZEBRA_ROUTE_VNC_DIRECT
268 && ubi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
270 && prefix_same(&unicast_nexthop
, &ce_nexthop
)) {
272 vnc_zlog_debug_verbose(
273 "%s: already have matching exported unicast route, skipping",
280 * Construct new attribute set with CE addr as
281 * nexthop and without Tunnel Encap attr
283 encap_attr_export_ce(&hattr
, attr
, &ce_nexthop
);
284 if (bgp
->rfapi_cfg
->routemap_export_bgp
) {
285 struct bgp_info info
;
286 route_map_result_t ret
;
288 memset(&info
, 0, sizeof(info
));
291 ret
= route_map_apply(bgp
->rfapi_cfg
->routemap_export_bgp
,
292 prefix
, RMAP_BGP
, &info
);
293 if (ret
== RMAP_DENYMATCH
) {
294 bgp_attr_flush(&hattr
);
299 iattr
= bgp_attr_intern(&hattr
);
300 bgp_attr_flush(&hattr
);
303 * Rule: disallow route-map alteration of next-hop, because it
304 * would make it too difficult to keep track of the correspondence
305 * between VPN routes and unicast routes.
307 rfapiUnicastNexthop2Prefix(afi
, iattr
, &post_routemap_nexthop
);
309 if (!prefix_same(&ce_nexthop
, &post_routemap_nexthop
)) {
310 vnc_zlog_debug_verbose(
311 "%s: route-map modification of nexthop not allowed, skipping",
313 bgp_attr_unintern(&iattr
);
317 bgp_update(peer
, prefix
, 0, /* addpath_id */
318 iattr
, /* bgp_update copies this attr */
319 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
320 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
321 NULL
, 0, /* tag not used for unicast */
322 0, NULL
); /* EVPN not used */
323 bgp_attr_unintern(&iattr
);
328 * "Withdrawing a Route" export process
330 void vnc_direct_bgp_del_route_ce(struct bgp
*bgp
, struct agg_node
*rn
,
333 afi_t afi
= family2afi(rn
->p
.family
);
334 struct bgp_info
*vbi
;
335 struct prefix ce_nexthop
;
338 flog_err(EC_LIB_DEVELOPMENT
, "%s: bad afi", __func__
);
342 /* check bgp redist flag for vnc direct ("vpn") routes */
343 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
344 vnc_zlog_debug_verbose(
345 "%s: bgp redistribution of VNC direct routes is off",
350 if (!bgp
->rfapi_cfg
) {
351 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
355 if (!VNC_EXPORT_BGP_CE_ENABLED(bgp
->rfapi_cfg
)) {
356 vnc_zlog_debug_verbose(
357 "%s: export-to-bgp ce mode not enabled, skipping",
364 * This works only for IPv4 because IPv6 addresses are too big
365 * to fit in an extended community
367 if (getce(bgp
, bi
->attr
, &ce_nexthop
)) {
368 vnc_zlog_debug_verbose("%s: EC has no encoded CE, skipping",
374 * Look for other VPN routes with same prefix, same 5226 CE,
375 * same peer. If at least one is present, don't remove the
376 * route from the unicast RIB
379 for (vbi
= rn
->info
; vbi
; vbi
= vbi
->next
) {
383 if (bi
->peer
!= vbi
->peer
)
385 if (getce(bgp
, vbi
->attr
, &ce
))
387 if (prefix_same(&ce
, &ce_nexthop
)) {
388 vnc_zlog_debug_verbose(
389 "%s: still have a route via CE, not deleting unicast",
398 bgp_withdraw(bi
->peer
, &rn
->p
, 0, /* addpath_id */
399 NULL
, /* attr, ignored */
400 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
401 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
402 NULL
, 0, NULL
); /* tag not used for unicast */
405 static void vnc_direct_bgp_vpn_enable_ce(struct bgp
*bgp
, afi_t afi
)
410 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
415 if (!(bgp
->rfapi_cfg
))
418 if (!VNC_EXPORT_BGP_CE_ENABLED(bgp
->rfapi_cfg
)) {
419 vnc_zlog_debug_verbose(
420 "%s: export of CE routes not enabled, skipping",
425 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
426 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
431 * Go through entire ce import table and export to BGP unicast.
433 for (rn
= agg_route_top(bgp
->rfapi
->it_ce
->imported_vpn
[afi
]); rn
;
434 rn
= agg_route_next(rn
)) {
440 char prefixstr
[PREFIX_STRLEN
];
442 prefix2str(&rn
->p
, prefixstr
, sizeof(prefixstr
));
443 vnc_zlog_debug_verbose("%s: checking prefix %s",
444 __func__
, prefixstr
);
447 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
449 vnc_zlog_debug_verbose("%s: ri->sub_type: %d", __func__
,
452 if (ri
->sub_type
== BGP_ROUTE_NORMAL
453 || ri
->sub_type
== BGP_ROUTE_RFP
454 || ri
->sub_type
== BGP_ROUTE_STATIC
) {
456 vnc_direct_bgp_add_route_ce(bgp
, rn
, ri
);
462 static void vnc_direct_bgp_vpn_disable_ce(struct bgp
*bgp
, afi_t afi
)
466 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
471 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
472 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
477 * Go through the entire BGP unicast table and remove routes that
480 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_UNICAST
]); rn
;
481 rn
= bgp_route_next(rn
)) {
484 struct bgp_info
*next
;
486 for (ri
= rn
->info
, next
= NULL
; ri
; ri
= next
) {
490 if (ri
->type
== ZEBRA_ROUTE_VNC_DIRECT
491 && ri
->sub_type
== BGP_ROUTE_REDISTRIBUTE
) {
494 ri
->peer
, &rn
->p
, /* prefix */
497 AFI_IP
, SAFI_UNICAST
,
498 ZEBRA_ROUTE_VNC_DIRECT
,
499 BGP_ROUTE_REDISTRIBUTE
,
500 NULL
, /* RD not used for unicast */
502 NULL
); /* tag not used for unicast */
508 /***********************************************************************
509 * Export methods that set nexthop to CE (from 5226 roo EC) END
510 ***********************************************************************/
512 /***********************************************************************
513 * Export methods that proxy nexthop BEGIN
514 ***********************************************************************/
516 static struct ecommunity
*vnc_route_origin_ecom(struct agg_node
*rn
)
518 struct ecommunity
*new;
524 new = ecommunity_new();
526 for (bi
= rn
->info
; bi
; bi
= bi
->next
) {
528 struct ecommunity_val roec
;
530 switch (BGP_MP_NEXTHOP_FAMILY(bi
->attr
->mp_nexthop_len
)) {
532 memset(&roec
, 0, sizeof(roec
));
536 &bi
->attr
->mp_nexthop_global_in
.s_addr
, 4);
539 ecommunity_add_val(new, &roec
);
542 /* No support for IPv6 addresses in extended communities
549 ecommunity_free(&new);
556 static struct ecommunity
*vnc_route_origin_ecom_single(struct in_addr
*origin
)
558 struct ecommunity
*new;
559 struct ecommunity_val roec
;
561 memset(&roec
, 0, sizeof(roec
));
564 memcpy(roec
.val
+ 2, &origin
->s_addr
, 4);
568 new = ecommunity_new();
570 ecommunity_add_val(new, &roec
);
573 ecommunity_free(&new);
582 * New memory allocation approach: make a ghost attr that
583 * has non-interned parts for the modifications. ghost attr
584 * memory is allocated by caller.
587 encap_attr_export(struct attr
*new, struct attr
*orig
,
588 struct prefix
*new_nexthop
,
589 struct agg_node
*rn
) /* for VN addrs for ecom list */
590 /* if rn is 0, use route's nexthop */
592 struct prefix orig_nexthop
;
593 struct prefix
*use_nexthop
;
594 static struct ecommunity
*ecom_ro
;
597 use_nexthop
= new_nexthop
;
599 use_nexthop
= &orig_nexthop
;
600 orig_nexthop
.family
=
601 BGP_MP_NEXTHOP_FAMILY(orig
->mp_nexthop_len
);
602 if (orig_nexthop
.family
== AF_INET
) {
603 orig_nexthop
.prefixlen
= 32;
604 orig_nexthop
.u
.prefix4
= orig
->mp_nexthop_global_in
;
605 } else if (orig_nexthop
.family
== AF_INET6
) {
606 orig_nexthop
.prefixlen
= 128;
607 orig_nexthop
.u
.prefix6
= orig
->mp_nexthop_global
;
609 return -1; /* FAIL - can't compute nexthop */
615 * Make "new" a ghost attr copy of "orig"
617 memset(new, 0, sizeof(struct attr
));
618 bgp_attr_dup(new, orig
);
623 switch (use_nexthop
->family
) {
625 new->nexthop
= use_nexthop
->u
.prefix4
;
626 new->mp_nexthop_len
= 4; /* bytes */
627 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
631 new->mp_nexthop_global
= use_nexthop
->u
.prefix6
;
632 new->mp_nexthop_len
= 16; /* bytes */
641 ecom_ro
= vnc_route_origin_ecom(rn
);
643 /* TBD use lcom for IPv6 */
644 ecom_ro
= vnc_route_origin_ecom_single(&use_nexthop
->u
.prefix4
);
646 if (new->ecommunity
) {
649 ecommunity_merge(ecom_ro
, new->ecommunity
);
651 new->ecommunity
= 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 afi_t afi
= family2afi(rn
->p
.family
);
703 flog_err(EC_LIB_DEVELOPMENT
,
704 "%s: can't get afi of route node", __func__
);
708 /* check bgp redist flag for vnc direct ("vpn") routes */
709 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
710 vnc_zlog_debug_verbose(
711 "%s: bgp redistribution of VNC direct routes is off",
716 if (!bgp
->rfapi_cfg
) {
717 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
722 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
723 vnc_zlog_debug_verbose(
724 "%s: export-to-bgp group mode not enabled, skipping",
729 if (!listcount(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
)) {
730 vnc_zlog_debug_verbose(
731 "%s: no bgp-direct export nve group, skipping",
736 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
737 /* TBD set some configured med, see add_vnc_route() */
739 vnc_zlog_debug_verbose(
740 "%s: looping over nve-groups in direct-bgp export list",
743 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
749 * If nve group is not defined yet, skip it
755 * If the nve group uses a different import table, skip it
757 if (import_table
!= rfgn
->rfg
->rfapi_import_table
)
761 * if no NVEs currently associated with this group, skip it
763 if (rfgn
->rfg
->type
!= RFAPI_GROUP_CFG_VRF
&& !rfgn
->rfg
->nves
)
767 * per-nve-group prefix list check
769 if (rfgn
->rfg
->plist_export_bgp
[afi
]) {
770 if (prefix_list_apply(rfgn
->rfg
->plist_export_bgp
[afi
],
777 if (rfgn
->rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
778 vnc_direct_add_rn_group_rd(bgp
, rfgn
->rfg
, rn
, &attr
,
779 afi
, rfgn
->rfg
->rfd
);
782 * - but consistent with rest of function
787 * For each NVE that is assigned to the export nve group,
789 * a route with that NVE as its next hop
791 for (ln
= listhead(rfgn
->rfg
->nves
); ln
;
792 ln
= listnextnode(ln
)) {
793 vnc_direct_add_rn_group_rd(bgp
, rfgn
->rfg
, rn
, &attr
,
794 afi
, listgetdata(ln
));
798 aspath_unintern(&attr
.aspath
);
802 * "Withdrawing a Route" export process
804 void vnc_direct_bgp_del_prefix(struct bgp
*bgp
,
805 struct rfapi_import_table
*import_table
,
808 struct listnode
*node
, *nnode
;
809 struct rfapi_rfg_name
*rfgn
;
810 afi_t afi
= family2afi(rn
->p
.family
);
813 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi route node",
818 /* check bgp redist flag for vnc direct ("vpn") routes */
819 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
820 vnc_zlog_debug_verbose(
821 "%s: bgp redistribution of VNC direct routes is off",
826 if (!bgp
->rfapi_cfg
) {
827 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
832 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
833 vnc_zlog_debug_verbose(
834 "%s: export-to-bgp group mode not enabled, skipping",
839 if (!listcount(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
)) {
840 vnc_zlog_debug_verbose(
841 "%s: no bgp-direct export nve group, skipping",
846 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
852 * If nve group is not defined yet, skip it
858 * if no NVEs currently associated with this group, skip it
860 if (rfgn
->rfg
->type
!= RFAPI_GROUP_CFG_VRF
&& !rfgn
->rfg
->nves
)
864 * If the nve group uses a different import table,
867 if (import_table
!= rfgn
->rfg
->rfapi_import_table
)
870 if (rfgn
->rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
872 struct rfapi_descriptor
*irfd
;
874 irfd
= rfgn
->rfg
->rfd
;
876 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
, &nhp
))
879 bgp_withdraw(irfd
->peer
, &rn
->p
, /* prefix */
881 NULL
, /* attr, ignored */
882 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
883 BGP_ROUTE_REDISTRIBUTE
,
884 NULL
, /* RD not used for unicast */
886 NULL
); /* tag not used for unicast */
889 * - but consistent with rest of function
894 * For each NVE that is assigned to the export nve group,
896 * a route with that NVE as its next hop
898 for (ln
= listhead(rfgn
->rfg
->nves
); ln
;
899 ln
= listnextnode(ln
)) {
902 struct rfapi_descriptor
*irfd
;
904 irfd
= listgetdata(ln
);
906 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
, &nhp
))
909 bgp_withdraw(irfd
->peer
, &rn
->p
, /* prefix */
911 NULL
, /* attr, ignored */
912 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
913 BGP_ROUTE_REDISTRIBUTE
,
914 NULL
, /* RD not used for unicast */
916 NULL
); /* tag not used for unicast */
921 void vnc_direct_bgp_add_nve(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
)
923 struct listnode
*node
, *nnode
;
924 struct rfapi_rfg_name
*rfgn
;
925 struct rfapi_nve_group_cfg
*rfg
= rfd
->rfg
;
926 afi_t afi
= family2afi(rfd
->vn_addr
.addr_family
);
929 flog_err(EC_LIB_DEVELOPMENT
,
930 "%s: can't get afi of nve vn addr", __func__
);
936 if (!bgp
->rfapi_cfg
) {
937 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
941 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
942 vnc_zlog_debug_verbose(
943 "%s: export-to-bgp group mode not enabled, skipping",
948 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
949 vnc_zlog_debug_verbose(
950 "%s: bgp redistribution of VNC direct routes is off",
956 * Loop over the list of NVE-Groups configured for
957 * exporting to direct-bgp and see if this new NVE's
958 * group is among them.
960 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
964 * Yes, this NVE's group is configured for export to direct-bgp
966 if (rfgn
->rfg
== rfg
) {
968 struct agg_table
*rt
= NULL
;
970 struct attr attr
= {0};
971 struct rfapi_import_table
*import_table
;
974 import_table
= rfg
->rfapi_import_table
;
976 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
977 /* TBD set some configured med, see add_vnc_route() */
979 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
980 rt
= import_table
->imported_vpn
[afi
];
982 flog_err(EC_LIB_DEVELOPMENT
, "%s: bad afi %d",
988 * Walk the NVE-Group's VNC Import table
990 for (rn
= agg_route_top(rt
); rn
;
991 rn
= agg_route_next(rn
)) {
996 struct rfapi_descriptor
*irfd
= rfd
;
999 struct bgp_info info
;
1001 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
,
1006 * per-nve-group prefix list check
1008 if (rfgn
->rfg
->plist_export_bgp
[afi
]) {
1009 if (prefix_list_apply(
1010 rfgn
->rfg
->plist_export_bgp
1020 * Construct new attribute set with
1022 * nexthop and without Tunnel Encap attr
1024 if (encap_attr_export(&hattr
, &attr
,
1028 if (rfgn
->rfg
->routemap_export_bgp
) {
1029 route_map_result_t ret
;
1030 info
.peer
= irfd
->peer
;
1032 ret
= route_map_apply(
1034 ->routemap_export_bgp
,
1037 if (ret
== RMAP_DENYMATCH
) {
1038 bgp_attr_flush(&hattr
);
1043 iattr
= bgp_attr_intern(&hattr
);
1044 bgp_attr_flush(&hattr
);
1046 irfd
->peer
, &rn
->p
, /* prefix */
1048 iattr
, /* bgp_update copies
1051 ZEBRA_ROUTE_VNC_DIRECT
,
1052 BGP_ROUTE_REDISTRIBUTE
, NULL
,
1053 /* RD not used for unicast */
1055 /* tag not used for unicast */
1056 0, 0, NULL
); /* EVPN not used */
1058 bgp_attr_unintern(&iattr
);
1062 aspath_unintern(&attr
.aspath
);
1068 void vnc_direct_bgp_del_nve(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
)
1070 struct listnode
*node
, *nnode
;
1071 struct rfapi_rfg_name
*rfgn
;
1072 struct rfapi_nve_group_cfg
*rfg
= rfd
->rfg
;
1073 afi_t afi
= family2afi(rfd
->vn_addr
.addr_family
);
1076 flog_err(EC_LIB_DEVELOPMENT
,
1077 "%s: can't get afi of nve vn addr", __func__
);
1083 if (!bgp
->rfapi_cfg
) {
1084 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1088 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
1089 vnc_zlog_debug_verbose(
1090 "%s: export-to-bgp group mode not enabled, skipping",
1095 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
1096 vnc_zlog_debug_verbose(
1097 "%s: bgp redistribution of VNC direct routes is off",
1103 * Loop over the list of NVE-Groups configured for
1104 * exporting to direct-bgp and see if this new NVE's
1105 * group is among them.
1107 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
1111 * Yes, this NVE's group is configured for export to direct-bgp
1113 if (rfg
&& rfgn
->rfg
== rfg
) {
1115 struct agg_table
*rt
= NULL
;
1116 struct agg_node
*rn
;
1117 struct rfapi_import_table
*import_table
;
1119 import_table
= rfg
->rfapi_import_table
;
1121 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
1122 rt
= import_table
->imported_vpn
[afi
];
1124 flog_err(EC_LIB_DEVELOPMENT
, "%s: bad afi %d",
1130 * Walk the NVE-Group's VNC Import table
1132 for (rn
= agg_route_top(rt
); rn
;
1133 rn
= agg_route_next(rn
)) {
1138 struct rfapi_descriptor
*irfd
= rfd
;
1140 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
,
1144 bgp_withdraw(irfd
->peer
,
1145 &rn
->p
, /* prefix */
1147 NULL
, /* attr, ignored */
1149 ZEBRA_ROUTE_VNC_DIRECT
,
1150 BGP_ROUTE_REDISTRIBUTE
,
1151 NULL
, /* RD not used for
1153 NULL
, 0, NULL
); /* tag not
1162 static void vnc_direct_add_rn_group_rd(struct bgp
*bgp
,
1163 struct rfapi_nve_group_cfg
*rfg
,
1164 struct agg_node
*rn
, struct attr
*attr
,
1165 afi_t afi
, struct rfapi_descriptor
*irfd
)
1168 struct bgp_info info
;
1172 if (irfd
== NULL
&& rfg
->type
!= RFAPI_GROUP_CFG_VRF
) {
1173 /* need new rfapi_handle, for peer strcture
1174 * -- based on vnc_add_vrf_prefi */
1175 assert(rfg
->rfd
== NULL
);
1177 if (!rfg
->rt_export_list
|| !rfg
->rfapi_import_table
) {
1178 vnc_zlog_debug_verbose(
1179 "%s: VRF \"%s\" is missing RT import/export configuration.\n",
1180 __func__
, rfg
->name
);
1183 if (!rfg
->rd
.prefixlen
) {
1184 vnc_zlog_debug_verbose(
1185 "%s: VRF \"%s\" is missing RD configuration.\n",
1186 __func__
, rfg
->name
);
1189 if (rfg
->label
> MPLS_LABEL_MAX
) {
1190 vnc_zlog_debug_verbose(
1191 "%s: VRF \"%s\" is missing defaul label configuration.\n",
1192 __func__
, rfg
->name
);
1196 irfd
= XCALLOC(MTYPE_RFAPI_DESC
,
1197 sizeof(struct rfapi_descriptor
));
1201 * leave most fields empty as will get from (dynamic) config
1204 irfd
->default_tunneltype_option
.type
= BGP_ENCAP_TYPE_MPLS
;
1206 if (rfg
->vn_prefix
.family
1207 && !CHECK_FLAG(rfg
->flags
, RFAPI_RFG_VPN_NH_SELF
)) {
1208 rfapiQprefix2Raddr(&rfg
->vn_prefix
, &irfd
->vn_addr
);
1210 memset(&irfd
->vn_addr
, 0, sizeof(struct rfapi_ip_addr
));
1211 irfd
->vn_addr
.addr_family
= AF_INET
;
1212 irfd
->vn_addr
.addr
.v4
= bgp
->router_id
;
1214 irfd
->un_addr
= irfd
->vn_addr
; /* sigh, need something in UN for
1216 vnc_zlog_debug_verbose("%s: Opening RFD for VRF %s", __func__
,
1218 rfapi_init_and_open(bgp
, irfd
, rfg
);
1221 if (irfd
== NULL
|| rfapiRaddr2Qprefix(&irfd
->vn_addr
, &nhp
))
1225 * Construct new attribute set with NVE's VN
1227 * nexthop and without Tunnel Encap attr
1229 if (encap_attr_export(&hattr
, attr
, &nhp
, rn
))
1232 if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD
)) {
1233 vnc_zlog_debug_any("%s: attr follows", __func__
);
1234 rfapiPrintAttrPtrs(NULL
, attr
);
1235 vnc_zlog_debug_any("%s: hattr follows", __func__
);
1236 rfapiPrintAttrPtrs(NULL
, &hattr
);
1239 if (rfg
->routemap_export_bgp
) {
1240 route_map_result_t ret
;
1242 info
.peer
= irfd
->peer
;
1244 ret
= route_map_apply(rfg
->routemap_export_bgp
, &rn
->p
,
1246 if (ret
== RMAP_DENYMATCH
) {
1247 bgp_attr_flush(&hattr
);
1248 vnc_zlog_debug_verbose(
1249 "%s: route map says DENY, so not calling bgp_update",
1255 if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD
)) {
1256 vnc_zlog_debug_any("%s: hattr after route_map_apply:",
1258 rfapiPrintAttrPtrs(NULL
, &hattr
);
1260 iattr
= bgp_attr_intern(&hattr
);
1261 bgp_attr_flush(&hattr
);
1263 bgp_update(irfd
->peer
, &rn
->p
, /* prefix */
1265 iattr
, /* bgp_update copies it */
1266 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
1267 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
1268 NULL
, /* tag not used for unicast */
1269 0, 0, NULL
); /* EVPN not used */
1271 bgp_attr_unintern(&iattr
);
1277 * Caller is responsible for ensuring that the specified nve-group
1278 * is actually part of the list of exported nve groups.
1280 static void vnc_direct_bgp_add_group_afi(struct bgp
*bgp
,
1281 struct rfapi_nve_group_cfg
*rfg
,
1284 struct agg_table
*rt
= NULL
;
1285 struct agg_node
*rn
;
1286 struct attr attr
= {0};
1287 struct rfapi_import_table
*import_table
;
1289 vnc_zlog_debug_verbose("%s: entry", __func__
);
1291 import_table
= rfg
->rfapi_import_table
;
1292 if (!import_table
) {
1293 vnc_zlog_debug_verbose(
1294 "%s: import table not defined, returning", __func__
);
1298 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
1299 rt
= import_table
->imported_vpn
[afi
];
1301 flog_err(EC_LIB_DEVELOPMENT
, "%s: bad afi %d", __func__
, afi
);
1305 if (!rfg
->nves
&& rfg
->type
!= RFAPI_GROUP_CFG_VRF
) {
1306 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__
);
1310 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
1311 /* TBD set some configured med, see add_vnc_route() */
1314 * Walk the NVE-Group's VNC Import table
1316 for (rn
= agg_route_top(rt
); rn
; rn
= agg_route_next(rn
)) {
1320 struct listnode
*ln
;
1323 * per-nve-group prefix list check
1325 if (rfg
->plist_export_bgp
[afi
]) {
1326 if (prefix_list_apply(
1327 rfg
->plist_export_bgp
[afi
], &rn
->p
)
1332 if (rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
1333 vnc_direct_add_rn_group_rd(bgp
, rfg
, rn
, &attr
,
1337 * - but consistent with rest of function
1342 * For each NVE that is assigned to the export nve
1344 * a route with that NVE as its next hop
1346 for (ln
= listhead(rfg
->nves
); ln
;
1347 ln
= listnextnode(ln
)) {
1348 vnc_direct_add_rn_group_rd(bgp
, rfg
, rn
, &attr
,
1355 aspath_unintern(&attr
.aspath
);
1360 * Caller is responsible for ensuring that the specified nve-group
1361 * is actually part of the list of exported nve groups.
1363 void vnc_direct_bgp_add_group(struct bgp
*bgp
, struct rfapi_nve_group_cfg
*rfg
)
1365 vnc_direct_bgp_add_group_afi(bgp
, rfg
, AFI_IP
);
1366 vnc_direct_bgp_add_group_afi(bgp
, rfg
, AFI_IP6
);
1369 static void vnc_direct_del_rn_group_rd(struct bgp
*bgp
,
1370 struct rfapi_nve_group_cfg
*rfg
,
1371 struct agg_node
*rn
, afi_t afi
,
1372 struct rfapi_descriptor
*irfd
)
1376 bgp_withdraw(irfd
->peer
, &rn
->p
, /* prefix */
1378 NULL
, /* attr, ignored */
1379 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
1380 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
1381 NULL
, 0, NULL
); /* tag not used for unicast */
1386 * Caller is responsible for ensuring that the specified nve-group
1387 * was actually part of the list of exported nve groups.
1389 static void vnc_direct_bgp_del_group_afi(struct bgp
*bgp
,
1390 struct rfapi_nve_group_cfg
*rfg
,
1393 struct agg_table
*rt
= NULL
;
1394 struct agg_node
*rn
;
1395 struct rfapi_import_table
*import_table
;
1397 vnc_zlog_debug_verbose("%s: entry", __func__
);
1399 import_table
= rfg
->rfapi_import_table
;
1400 if (!import_table
) {
1401 vnc_zlog_debug_verbose(
1402 "%s: import table not defined, returning", __func__
);
1406 assert(afi
== AFI_IP
|| afi
== AFI_IP6
);
1407 rt
= import_table
->imported_vpn
[afi
];
1409 if (!rfg
->nves
&& rfg
->type
!= RFAPI_GROUP_CFG_VRF
) {
1410 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__
);
1415 * Walk the NVE-Group's VNC Import table
1417 for (rn
= agg_route_top(rt
); rn
; rn
= agg_route_next(rn
))
1419 if (rfg
->type
== RFAPI_GROUP_CFG_VRF
)
1420 vnc_direct_del_rn_group_rd(bgp
, rfg
, rn
, afi
,
1423 struct listnode
*ln
;
1426 * For each NVE that is assigned to the export
1429 * a route with that NVE as its next hop
1431 for (ln
= listhead(rfg
->nves
); ln
;
1432 ln
= listnextnode(ln
))
1433 vnc_direct_del_rn_group_rd(
1441 * Caller is responsible for ensuring that the specified nve-group
1442 * was actually part of the list of exported nve groups.
1444 void vnc_direct_bgp_del_group(struct bgp
*bgp
, struct rfapi_nve_group_cfg
*rfg
)
1446 vnc_direct_bgp_del_group_afi(bgp
, rfg
, AFI_IP
);
1447 vnc_direct_bgp_del_group_afi(bgp
, rfg
, AFI_IP6
);
1450 void vnc_direct_bgp_reexport_group_afi(struct bgp
*bgp
,
1451 struct rfapi_nve_group_cfg
*rfg
,
1454 struct listnode
*node
;
1455 struct rfapi_rfg_name
*rfgn
;
1457 if (VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
1459 * look in the list of currently-exported groups
1461 for (ALL_LIST_ELEMENTS_RO(
1462 bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
1465 if (rfgn
->rfg
== rfg
) {
1467 * If it matches, reexport it
1469 vnc_direct_bgp_del_group_afi(bgp
, rfg
, afi
);
1470 vnc_direct_bgp_add_group_afi(bgp
, rfg
, afi
);
1478 static void vnc_direct_bgp_unexport_table(afi_t afi
, struct agg_table
*rt
,
1479 struct list
*nve_list
)
1483 struct agg_node
*rn
;
1485 for (rn
= agg_route_top(rt
); rn
; rn
= agg_route_next(rn
)) {
1489 struct listnode
*hln
;
1490 struct rfapi_descriptor
*irfd
;
1492 for (ALL_LIST_ELEMENTS_RO(nve_list
, hln
,
1495 bgp_withdraw(irfd
->peer
,
1496 &rn
->p
, /* prefix */
1498 NULL
, /* attr, ignored */
1500 ZEBRA_ROUTE_VNC_DIRECT
,
1501 BGP_ROUTE_REDISTRIBUTE
,
1502 NULL
, /* RD not used for
1504 NULL
, 0, NULL
); /* tag not
1515 static void import_table_to_nve_list_direct_bgp(struct bgp
*bgp
,
1516 struct rfapi_import_table
*it
,
1520 struct listnode
*node
;
1521 struct rfapi_rfg_name
*rfgn
;
1524 * Loop over the list of NVE-Groups configured for
1525 * exporting to direct-bgp.
1527 * Build a list of NVEs that use this import table
1530 for (ALL_LIST_ELEMENTS_RO(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
1534 * If this NVE-Group's import table matches the current one
1536 if (rfgn
->rfg
&& rfgn
->rfg
->rfapi_import_table
== it
) {
1537 if (rfgn
->rfg
->nves
)
1538 nve_group_to_nve_list(rfgn
->rfg
, nves
, family
);
1539 else if (rfgn
->rfg
->rfd
1540 && rfgn
->rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
1543 listnode_add(*nves
, rfgn
->rfg
->rfd
);
1549 void vnc_direct_bgp_vpn_enable(struct bgp
*bgp
, afi_t afi
)
1551 struct listnode
*rfgn
;
1552 struct rfapi_nve_group_cfg
*rfg
;
1557 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
1558 vnc_zlog_debug_verbose(
1559 "%s: export-to-bgp group mode not enabled, skipping",
1564 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1565 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1570 * Policy is applied per-nve-group, so we need to iterate
1571 * over the groups to add everything.
1573 for (ALL_LIST_ELEMENTS_RO(bgp
->rfapi_cfg
->nve_groups_sequential
, rfgn
,
1577 * contains policy management
1579 vnc_direct_bgp_add_group_afi(bgp
, rfg
, afi
);
1584 void vnc_direct_bgp_vpn_disable(struct bgp
*bgp
, afi_t afi
)
1586 struct rfapi_import_table
*it
;
1587 uint8_t family
= afi2family(afi
);
1589 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
1595 vnc_zlog_debug_verbose("%s: rfapi not initialized", __func__
);
1599 if (!family
|| (afi
!= AFI_IP
&& afi
!= AFI_IP6
)) {
1600 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1604 for (it
= bgp
->rfapi
->imports
; it
; it
= it
->next
) {
1606 struct list
*nve_list
= NULL
;
1608 import_table_to_nve_list_direct_bgp(bgp
, it
, &nve_list
, family
);
1611 vnc_direct_bgp_unexport_table(
1612 afi
, it
->imported_vpn
[afi
], nve_list
);
1613 list_delete_and_null(&nve_list
);
1619 /***********************************************************************
1620 * Export methods that proxy nexthop END
1621 ***********************************************************************/
1624 /***********************************************************************
1625 * Export methods that preserve original nexthop BEGIN
1626 * rh = "registering nve"
1627 ***********************************************************************/
1631 * "Adding a Route" export process
1632 * TBD do we need to check bi->type and bi->sub_type here, or does
1635 void vnc_direct_bgp_rh_add_route(struct bgp
*bgp
, afi_t afi
,
1636 struct prefix
*prefix
, struct peer
*peer
,
1639 struct vnc_export_info
*eti
;
1641 struct rfapi_cfg
*hc
;
1645 flog_err(EC_LIB_DEVELOPMENT
,
1646 "%s: can't get afi of route node", __func__
);
1650 /* check bgp redist flag for vnc direct ("vpn") routes */
1651 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
1652 vnc_zlog_debug_verbose(
1653 "%s: bgp redistribution of VNC direct routes is off",
1658 if (!(hc
= bgp
->rfapi_cfg
)) {
1659 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1664 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
1665 vnc_zlog_debug_verbose(
1666 "%s: export-to-bgp RH mode not enabled, skipping",
1674 if (hc
->plist_export_bgp
[afi
]) {
1675 if (prefix_list_apply(hc
->plist_export_bgp
[afi
], prefix
)
1681 * Construct new attribute set with NVE's VN addr as
1682 * nexthop and without Tunnel Encap attr
1684 if (encap_attr_export(&hattr
, attr
, NULL
, NULL
))
1686 if (hc
->routemap_export_bgp
) {
1687 struct bgp_info info
;
1688 route_map_result_t ret
;
1690 memset(&info
, 0, sizeof(info
));
1693 ret
= route_map_apply(hc
->routemap_export_bgp
, prefix
, RMAP_BGP
,
1695 if (ret
== RMAP_DENYMATCH
) {
1696 bgp_attr_flush(&hattr
);
1701 iattr
= bgp_attr_intern(&hattr
);
1702 bgp_attr_flush(&hattr
);
1705 * record route information that we will need to expire
1708 eti
= vnc_eti_get(bgp
, EXPORT_TYPE_BGP
, prefix
, peer
,
1709 ZEBRA_ROUTE_VNC_DIRECT_RH
, BGP_ROUTE_REDISTRIBUTE
);
1710 rfapiGetVncLifetime(attr
, &eti
->lifetime
);
1711 eti
->lifetime
= rfapiGetHolddownFromLifetime(eti
->lifetime
);
1715 * export expiration timer is already running on
1716 * this route: cancel it
1718 thread_cancel(eti
->timer
);
1722 bgp_update(peer
, prefix
, /* prefix */
1724 iattr
, /* bgp_update copies this attr */
1725 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT_RH
,
1726 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
1727 NULL
, /* tag not used for unicast, EVPN neither */
1728 0, 0, NULL
); /* EVPN not used */
1729 bgp_attr_unintern(&iattr
);
1732 static int vncExportWithdrawTimer(struct thread
*t
)
1734 struct vnc_export_info
*eti
= t
->arg
;
1737 * withdraw the route
1739 bgp_withdraw(eti
->peer
, &eti
->node
->p
, 0, /* addpath_id */
1740 NULL
, /* attr, ignored */
1741 family2afi(eti
->node
->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 bi->type and bi->sub_type here, or does
1759 void vnc_direct_bgp_rh_del_route(struct bgp
*bgp
, afi_t afi
,
1760 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_node
*prn
;
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 (prn
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); prn
;
1838 prn
= bgp_route_next(prn
)) {
1840 struct bgp_table
*table
;
1841 struct bgp_node
*rn
;
1842 struct bgp_info
*ri
;
1844 memset(&prd
, 0, sizeof(prd
));
1845 prd
.family
= AF_UNSPEC
;
1847 memcpy(prd
.val
, prn
->p
.u
.val
, 8);
1849 /* This is the per-RD table of prefixes */
1855 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
1858 * skip prefix list check if no routes here
1864 char prefixstr
[PREFIX_STRLEN
];
1866 prefix2str(&rn
->p
, prefixstr
,
1868 vnc_zlog_debug_verbose("%s: checking prefix %s",
1869 __func__
, prefixstr
);
1875 if (hc
->plist_export_bgp
[afi
]) {
1876 if (prefix_list_apply(hc
->plist_export_bgp
[afi
],
1880 vnc_zlog_debug_verbose(
1881 "%s: prefix list says DENY",
1887 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
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_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
,
1923 if (ret
== RMAP_DENYMATCH
) {
1924 bgp_attr_flush(&hattr
);
1925 vnc_zlog_debug_verbose(
1926 "%s: route map says DENY",
1932 iattr
= bgp_attr_intern(&hattr
);
1933 bgp_attr_flush(&hattr
);
1936 * record route information that we will
1941 bgp
, EXPORT_TYPE_BGP
, &rn
->p
,
1943 ZEBRA_ROUTE_VNC_DIRECT_RH
,
1944 BGP_ROUTE_REDISTRIBUTE
);
1945 rfapiGetVncLifetime(ri
->attr
,
1950 * export expiration timer is
1951 * already running on
1952 * this route: cancel it
1954 thread_cancel(eti
->timer
);
1958 vnc_zlog_debug_verbose(
1959 "%s: calling bgp_update",
1963 ri
->peer
, &rn
->p
, /* prefix */
1965 iattr
, /* bgp_update copies
1967 AFI_IP
, SAFI_UNICAST
,
1968 ZEBRA_ROUTE_VNC_DIRECT_RH
,
1969 BGP_ROUTE_REDISTRIBUTE
, NULL
,
1970 /* RD not used for unicast */
1972 /* tag not used for unicast,
1974 0, 0, NULL
); /* EVPN not used */
1976 bgp_attr_unintern(&iattr
);
1983 void vnc_direct_bgp_rh_vpn_disable(struct bgp
*bgp
, afi_t afi
)
1985 struct bgp_node
*rn
;
1987 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
1992 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1993 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1998 * Go through the entire BGP unicast table and remove routes that
1999 * originated from us
2001 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_UNICAST
]); rn
;
2002 rn
= bgp_route_next(rn
)) {
2004 struct bgp_info
*ri
;
2005 struct bgp_info
*next
;
2007 for (ri
= rn
->info
, next
= NULL
; ri
; ri
= next
) {
2011 if (ri
->type
== ZEBRA_ROUTE_VNC_DIRECT_RH
2012 && ri
->sub_type
== BGP_ROUTE_REDISTRIBUTE
) {
2014 struct vnc_export_info
*eti
;
2017 * Delete routes immediately (no timer)
2019 eti
= vnc_eti_checktimer(
2020 bgp
, EXPORT_TYPE_BGP
, &rn
->p
, ri
->peer
,
2021 ZEBRA_ROUTE_VNC_DIRECT_RH
,
2022 BGP_ROUTE_REDISTRIBUTE
);
2025 thread_cancel(eti
->timer
);
2026 vnc_eti_delete(eti
);
2029 bgp_withdraw(ri
->peer
, &rn
->p
, /* prefix */
2032 AFI_IP
, SAFI_UNICAST
,
2033 ZEBRA_ROUTE_VNC_DIRECT_RH
,
2034 BGP_ROUTE_REDISTRIBUTE
,
2035 NULL
, /* RD not used for unicast */
2036 NULL
, 0, NULL
); /* tag not used for
2044 void vnc_direct_bgp_rh_reexport(struct bgp
*bgp
, afi_t afi
)
2046 if (VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
2047 vnc_direct_bgp_rh_vpn_disable(bgp
, afi
);
2048 vnc_direct_bgp_rh_vpn_enable(bgp
, afi
);
2052 /***********************************************************************
2053 * Generic Export methods
2054 ***********************************************************************/
2057 * Assumes the correct mode bits are already turned on. Thus it
2058 * is OK to call this function from, e.g., bgp_redistribute_set()
2059 * without caring if export is enabled or not
2061 void vnc_export_bgp_enable(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_enable(bgp
, afi
);
2074 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH
:
2075 vnc_direct_bgp_rh_vpn_enable(bgp
, afi
);
2078 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE
:
2079 vnc_direct_bgp_vpn_enable_ce(bgp
, afi
);
2084 void vnc_export_bgp_disable(struct bgp
*bgp
, afi_t afi
)
2086 if (!bgp
->rfapi_cfg
)
2089 switch (bgp
->rfapi_cfg
->flags
& BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS
) {
2090 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE
:
2093 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP
:
2094 vnc_direct_bgp_vpn_disable(bgp
, afi
);
2097 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH
:
2098 vnc_direct_bgp_rh_vpn_disable(bgp
, afi
);
2101 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE
:
2102 vnc_direct_bgp_vpn_disable_ce(bgp
, afi
);
2107 void vnc_export_bgp_prechange(struct bgp
*bgp
)
2109 vnc_export_bgp_disable(bgp
, AFI_IP
);
2110 vnc_export_bgp_disable(bgp
, AFI_IP6
);
2113 void vnc_export_bgp_postchange(struct bgp
*bgp
)
2115 vnc_export_bgp_enable(bgp
, AFI_IP
);
2116 vnc_export_bgp_enable(bgp
, AFI_IP6
);
2119 void vnc_direct_bgp_reexport(struct bgp
*bgp
, afi_t afi
)
2121 vnc_export_bgp_disable(bgp
, afi
);
2122 vnc_export_bgp_enable(bgp
, afi
);