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/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"
37 #include "bgpd/bgpd.h"
38 #include "bgpd/bgp_ecommunity.h"
39 #include "bgpd/bgp_attr.h"
40 #include "bgpd/bgp_aspath.h"
42 #include "bgpd/rfapi/vnc_export_bgp.h"
43 #include "bgpd/rfapi/vnc_export_bgp_p.h"
44 #include "bgpd/rfapi/vnc_export_table.h"
45 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
46 #include "bgpd/rfapi/rfapi.h"
47 #include "bgpd/rfapi/rfapi_import.h"
48 #include "bgpd/rfapi/rfapi_private.h"
49 #include "bgpd/rfapi/rfapi_backend.h"
50 #include "bgpd/rfapi/rfapi_vty.h"
51 #include "bgpd/rfapi/vnc_debug.h"
54 static void vnc_direct_add_rn_group_rd(struct bgp
*bgp
,
55 struct rfapi_nve_group_cfg
*rfg
,
56 struct route_node
*rn
, struct attr
*attr
,
58 struct rfapi_descriptor
*irfd
);
60 /***********************************************************************
61 * Export methods that set nexthop to CE (from 5226 roo EC) BEGIN
62 ***********************************************************************/
65 * Memory allocation approach: make a ghost attr that
66 * has non-interned parts for the modifications. ghost attr
67 * memory is allocated by caller.
69 * - extract ce (=5226) EC and use as new nexthop
70 * - strip Tunnel Encap attr
73 static void encap_attr_export_ce(struct attr
*new, struct attr
*orig
,
74 struct prefix
*use_nexthop
)
77 * Make "new" a ghost attr copy of "orig"
79 memset(new, 0, sizeof(struct attr
));
80 bgp_attr_dup(new, orig
);
85 switch (use_nexthop
->family
) {
87 new->nexthop
= use_nexthop
->u
.prefix4
;
88 new->mp_nexthop_len
= 4; /* bytes */
89 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
93 new->mp_nexthop_global
= use_nexthop
->u
.prefix6
;
94 new->mp_nexthop_len
= 16; /* bytes */
105 * Note that it will be deleted when BGP sends to any eBGP
106 * peer unless PEER_FLAG_MED_UNCHANGED is set:
108 * neighbor NEIGHBOR attribute-unchanged med
110 if (!CHECK_FLAG(new->flag
, BGP_ATTR_MULTI_EXIT_DISC
)) {
111 if (CHECK_FLAG(new->flag
, BGP_ATTR_LOCAL_PREF
)) {
112 if (new->local_pref
> 255)
115 new->med
= 255 - new->local_pref
;
117 new->med
= 255; /* shouldn't happen */
119 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
123 * "new" is now a ghost attr:
124 * - it owns an "extra" struct
125 * - it owns any non-interned parts
126 * - any references to interned parts are not counted
128 * Caller should, after using the attr, call:
129 * - bgp_attr_flush() to free non-interned parts
133 static int getce(struct bgp
*bgp
, struct attr
*attr
, struct prefix
*pfx_ce
)
137 uint16_t localadmin
= bgp
->rfapi_cfg
->resolve_nve_roo_local_admin
;
139 for (ecp
= attr
->ecommunity
->val
, i
= 0; i
< attr
->ecommunity
->size
;
140 ++i
, ecp
+= ECOMMUNITY_SIZE
) {
142 if (VNC_DEBUG(EXPORT_BGP_GETCE
)) {
144 "%s: %02x %02x %02x %02x %02x %02x %02x %02x",
145 __func__
, ecp
[0], ecp
[1], ecp
[2], ecp
[3],
146 ecp
[4], ecp
[5], ecp
[6], ecp
[7]);
152 if (ecp
[0] != 1 || ecp
[1] != 3) {
157 * Match local admin value?
159 if (ecp
[6] != ((localadmin
& 0xff00) >> 8)
160 || ecp
[7] != (localadmin
& 0xff))
163 memset((uint8_t *)pfx_ce
, 0, sizeof(*pfx_ce
));
164 memcpy(&pfx_ce
->u
.prefix4
, ecp
+ 2, 4);
165 pfx_ce
->family
= AF_INET
;
166 pfx_ce
->prefixlen
= 32;
174 void vnc_direct_bgp_add_route_ce(struct bgp
*bgp
, struct route_node
*rn
,
177 struct attr
*attr
= bi
->attr
;
178 struct peer
*peer
= bi
->peer
;
179 struct prefix
*prefix
= &rn
->p
;
180 afi_t afi
= family2afi(prefix
->family
);
181 struct bgp_node
*urn
;
182 struct bgp_info
*ubi
;
185 struct prefix ce_nexthop
;
186 struct prefix post_routemap_nexthop
;
190 zlog_err("%s: can't get afi of route node", __func__
);
194 if ((bi
->type
!= ZEBRA_ROUTE_BGP
)
195 || (bi
->sub_type
!= BGP_ROUTE_NORMAL
196 && bi
->sub_type
!= BGP_ROUTE_RFP
197 && bi
->sub_type
!= BGP_ROUTE_STATIC
)) {
199 vnc_zlog_debug_verbose(
200 "%s: wrong route type/sub_type for export, skipping",
205 /* check bgp redist flag for vnc direct ("vpn") routes */
206 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
207 vnc_zlog_debug_verbose(
208 "%s: bgp redistribution of VNC direct routes is off",
213 if (!bgp
->rfapi_cfg
) {
214 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
219 if (!VNC_EXPORT_BGP_CE_ENABLED(bgp
->rfapi_cfg
)) {
220 vnc_zlog_debug_verbose(
221 "%s: export-to-bgp ce mode not enabled, skipping",
229 if (bgp
->rfapi_cfg
->plist_export_bgp
[afi
]) {
230 if (prefix_list_apply(bgp
->rfapi_cfg
->plist_export_bgp
[afi
],
233 vnc_zlog_debug_verbose(
234 "%s: prefix list denied, skipping", __func__
);
242 * This works only for IPv4 because IPv6 addresses are too big
243 * to fit in an extended community
245 if (getce(bgp
, attr
, &ce_nexthop
)) {
246 vnc_zlog_debug_verbose("%s: EC has no encoded CE, skipping",
252 * Is this route already represented in the unicast RIB?
253 * (look up prefix; compare route type, sub_type, peer, nexthop)
255 urn
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
, SAFI_UNICAST
,
257 for (ubi
= urn
->info
; ubi
; ubi
= ubi
->next
) {
258 struct prefix unicast_nexthop
;
260 if (CHECK_FLAG(ubi
->flags
, BGP_INFO_REMOVED
))
263 rfapiUnicastNexthop2Prefix(afi
, ubi
->attr
, &unicast_nexthop
);
265 if (ubi
->type
== ZEBRA_ROUTE_VNC_DIRECT
266 && ubi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
268 && prefix_same(&unicast_nexthop
, &ce_nexthop
)) {
270 vnc_zlog_debug_verbose(
271 "%s: already have matching exported unicast route, skipping",
278 * Construct new attribute set with CE addr as
279 * nexthop and without Tunnel Encap attr
281 encap_attr_export_ce(&hattr
, attr
, &ce_nexthop
);
282 if (bgp
->rfapi_cfg
->routemap_export_bgp
) {
283 struct bgp_info info
;
284 route_map_result_t ret
;
286 memset(&info
, 0, sizeof(info
));
289 ret
= route_map_apply(bgp
->rfapi_cfg
->routemap_export_bgp
,
290 prefix
, RMAP_BGP
, &info
);
291 if (ret
== RMAP_DENYMATCH
) {
292 bgp_attr_flush(&hattr
);
297 iattr
= bgp_attr_intern(&hattr
);
298 bgp_attr_flush(&hattr
);
301 * Rule: disallow route-map alteration of next-hop, because it
302 * would make it too difficult to keep track of the correspondence
303 * between VPN routes and unicast routes.
305 rfapiUnicastNexthop2Prefix(afi
, iattr
, &post_routemap_nexthop
);
307 if (!prefix_same(&ce_nexthop
, &post_routemap_nexthop
)) {
308 vnc_zlog_debug_verbose(
309 "%s: route-map modification of nexthop not allowed, skipping",
311 bgp_attr_unintern(&iattr
);
315 bgp_update(peer
, prefix
, 0, /* addpath_id */
316 iattr
, /* bgp_update copies this attr */
317 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
318 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
319 NULL
, 0, /* tag not used for unicast */
320 0, NULL
); /* EVPN not used */
321 bgp_attr_unintern(&iattr
);
326 * "Withdrawing a Route" export process
328 void vnc_direct_bgp_del_route_ce(struct bgp
*bgp
, struct route_node
*rn
,
331 afi_t afi
= family2afi(rn
->p
.family
);
332 struct bgp_info
*vbi
;
333 struct prefix ce_nexthop
;
336 zlog_err("%s: bad afi", __func__
);
340 /* check bgp redist flag for vnc direct ("vpn") routes */
341 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
342 vnc_zlog_debug_verbose(
343 "%s: bgp redistribution of VNC direct routes is off",
348 if (!bgp
->rfapi_cfg
) {
349 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
353 if (!VNC_EXPORT_BGP_CE_ENABLED(bgp
->rfapi_cfg
)) {
354 vnc_zlog_debug_verbose(
355 "%s: export-to-bgp ce mode not enabled, skipping",
362 * This works only for IPv4 because IPv6 addresses are too big
363 * to fit in an extended community
365 if (getce(bgp
, bi
->attr
, &ce_nexthop
)) {
366 vnc_zlog_debug_verbose("%s: EC has no encoded CE, skipping",
372 * Look for other VPN routes with same prefix, same 5226 CE,
373 * same peer. If at least one is present, don't remove the
374 * route from the unicast RIB
377 for (vbi
= rn
->info
; vbi
; vbi
= vbi
->next
) {
381 if (bi
->peer
!= vbi
->peer
)
383 if (getce(bgp
, vbi
->attr
, &ce
))
385 if (prefix_same(&ce
, &ce_nexthop
)) {
386 vnc_zlog_debug_verbose(
387 "%s: still have a route via CE, not deleting unicast",
396 bgp_withdraw(bi
->peer
, &rn
->p
, 0, /* addpath_id */
397 NULL
, /* attr, ignored */
398 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
399 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
400 NULL
, 0, NULL
); /* tag not used for unicast */
403 static void vnc_direct_bgp_vpn_enable_ce(struct bgp
*bgp
, afi_t afi
)
405 struct route_node
*rn
;
408 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
413 if (!(bgp
->rfapi_cfg
))
416 if (!VNC_EXPORT_BGP_CE_ENABLED(bgp
->rfapi_cfg
)) {
417 vnc_zlog_debug_verbose(
418 "%s: export of CE routes not enabled, skipping",
423 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
424 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
429 * Go through entire ce import table and export to BGP unicast.
431 for (rn
= route_top(bgp
->rfapi
->it_ce
->imported_vpn
[afi
]); rn
;
432 rn
= route_next(rn
)) {
438 char prefixstr
[PREFIX_STRLEN
];
440 prefix2str(&rn
->p
, prefixstr
, sizeof(prefixstr
));
441 vnc_zlog_debug_verbose("%s: checking prefix %s",
442 __func__
, prefixstr
);
445 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
447 vnc_zlog_debug_verbose("%s: ri->sub_type: %d", __func__
,
450 if (ri
->sub_type
== BGP_ROUTE_NORMAL
451 || ri
->sub_type
== BGP_ROUTE_RFP
452 || ri
->sub_type
== BGP_ROUTE_STATIC
) {
454 vnc_direct_bgp_add_route_ce(bgp
, rn
, ri
);
460 static void vnc_direct_bgp_vpn_disable_ce(struct bgp
*bgp
, afi_t afi
)
464 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
469 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
470 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
475 * Go through the entire BGP unicast table and remove routes that
478 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_UNICAST
]); rn
;
479 rn
= bgp_route_next(rn
)) {
482 struct bgp_info
*next
;
484 for (ri
= rn
->info
, next
= NULL
; ri
; ri
= next
) {
488 if (ri
->type
== ZEBRA_ROUTE_VNC_DIRECT
489 && ri
->sub_type
== BGP_ROUTE_REDISTRIBUTE
) {
492 ri
->peer
, &rn
->p
, /* prefix */
495 AFI_IP
, SAFI_UNICAST
,
496 ZEBRA_ROUTE_VNC_DIRECT
,
497 BGP_ROUTE_REDISTRIBUTE
,
498 NULL
, /* RD not used for unicast */
500 NULL
); /* tag not used for unicast */
506 /***********************************************************************
507 * Export methods that set nexthop to CE (from 5226 roo EC) END
508 ***********************************************************************/
510 /***********************************************************************
511 * Export methods that proxy nexthop BEGIN
512 ***********************************************************************/
514 static struct ecommunity
*vnc_route_origin_ecom(struct route_node
*rn
)
516 struct ecommunity
*new;
522 new = ecommunity_new();
524 for (bi
= rn
->info
; bi
; bi
= bi
->next
) {
526 struct ecommunity_val roec
;
528 switch (BGP_MP_NEXTHOP_FAMILY(bi
->attr
->mp_nexthop_len
)) {
530 memset(&roec
, 0, sizeof(roec
));
534 &bi
->attr
->mp_nexthop_global_in
.s_addr
, 4);
537 ecommunity_add_val(new, &roec
);
540 /* No support for IPv6 addresses in extended communities
547 ecommunity_free(&new);
554 static struct ecommunity
*vnc_route_origin_ecom_single(struct in_addr
*origin
)
556 struct ecommunity
*new;
557 struct ecommunity_val roec
;
559 memset(&roec
, 0, sizeof(roec
));
562 memcpy(roec
.val
+ 2, &origin
->s_addr
, 4);
566 new = ecommunity_new();
568 ecommunity_add_val(new, &roec
);
571 ecommunity_free(&new);
580 * New memory allocation approach: make a ghost attr that
581 * has non-interned parts for the modifications. ghost attr
582 * memory is allocated by caller.
585 encap_attr_export(struct attr
*new, struct attr
*orig
,
586 struct prefix
*new_nexthop
,
587 struct route_node
*rn
) /* for VN addrs for ecom list */
588 /* if rn is 0, use route's nexthop */
590 struct prefix orig_nexthop
;
591 struct prefix
*use_nexthop
;
592 static struct ecommunity
*ecom_ro
;
595 use_nexthop
= new_nexthop
;
597 use_nexthop
= &orig_nexthop
;
598 orig_nexthop
.family
=
599 BGP_MP_NEXTHOP_FAMILY(orig
->mp_nexthop_len
);
600 if (orig_nexthop
.family
== AF_INET
) {
601 orig_nexthop
.prefixlen
= 32;
602 orig_nexthop
.u
.prefix4
= orig
->mp_nexthop_global_in
;
603 } else if (orig_nexthop
.family
== AF_INET6
) {
604 orig_nexthop
.prefixlen
= 128;
605 orig_nexthop
.u
.prefix6
= orig
->mp_nexthop_global
;
607 return -1; /* FAIL - can't compute nexthop */
613 * Make "new" a ghost attr copy of "orig"
615 memset(new, 0, sizeof(struct attr
));
616 bgp_attr_dup(new, orig
);
621 switch (use_nexthop
->family
) {
623 new->nexthop
= use_nexthop
->u
.prefix4
;
624 new->mp_nexthop_len
= 4; /* bytes */
625 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
629 new->mp_nexthop_global
= use_nexthop
->u
.prefix6
;
630 new->mp_nexthop_len
= 16; /* bytes */
639 ecom_ro
= vnc_route_origin_ecom(rn
);
641 /* TBD use lcom for IPv6 */
642 ecom_ro
= vnc_route_origin_ecom_single(&use_nexthop
->u
.prefix4
);
644 if (new->ecommunity
) {
647 ecommunity_merge(ecom_ro
, new->ecommunity
);
649 new->ecommunity
= ecom_ro
;
652 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
658 * Note that it will be deleted when BGP sends to any eBGP
659 * peer unless PEER_FLAG_MED_UNCHANGED is set:
661 * neighbor NEIGHBOR attribute-unchanged med
663 if (!CHECK_FLAG(new->flag
, BGP_ATTR_MULTI_EXIT_DISC
)) {
664 if (CHECK_FLAG(new->flag
, BGP_ATTR_LOCAL_PREF
)) {
665 if (new->local_pref
> 255)
668 new->med
= 255 - new->local_pref
;
670 new->med
= 255; /* shouldn't happen */
672 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
676 * "new" is now a ghost attr:
677 * - it owns an "extra" struct
678 * - it owns any non-interned parts
679 * - any references to interned parts are not counted
681 * Caller should, after using the attr, call:
682 * - bgp_attr_flush() to free non-interned parts
689 * "Adding a Route" export process
691 void vnc_direct_bgp_add_prefix(struct bgp
*bgp
,
692 struct rfapi_import_table
*import_table
,
693 struct route_node
*rn
)
695 struct attr attr
= {0};
696 struct listnode
*node
, *nnode
;
697 struct rfapi_rfg_name
*rfgn
;
698 afi_t afi
= family2afi(rn
->p
.family
);
701 zlog_err("%s: can't get afi of route node", __func__
);
705 /* check bgp redist flag for vnc direct ("vpn") routes */
706 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
707 vnc_zlog_debug_verbose(
708 "%s: bgp redistribution of VNC direct routes is off",
713 if (!bgp
->rfapi_cfg
) {
714 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
719 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
720 vnc_zlog_debug_verbose(
721 "%s: export-to-bgp group mode not enabled, skipping",
726 if (!listcount(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
)) {
727 vnc_zlog_debug_verbose(
728 "%s: no bgp-direct export nve group, skipping",
733 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
734 /* TBD set some configured med, see add_vnc_route() */
736 vnc_zlog_debug_verbose(
737 "%s: looping over nve-groups in direct-bgp export list",
740 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
746 * If nve group is not defined yet, skip it
752 * If the nve group uses a different import table, skip it
754 if (import_table
!= rfgn
->rfg
->rfapi_import_table
)
758 * if no NVEs currently associated with this group, skip it
760 if (rfgn
->rfg
->type
!= RFAPI_GROUP_CFG_VRF
&& !rfgn
->rfg
->nves
)
764 * per-nve-group prefix list check
766 if (rfgn
->rfg
->plist_export_bgp
[afi
]) {
767 if (prefix_list_apply(rfgn
->rfg
->plist_export_bgp
[afi
],
774 if (rfgn
->rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
775 vnc_direct_add_rn_group_rd(bgp
, rfgn
->rfg
, rn
, &attr
,
776 afi
, rfgn
->rfg
->rfd
);
779 * - but consistent with rest of function
784 * For each NVE that is assigned to the export nve group,
786 * a route with that NVE as its next hop
788 for (ln
= listhead(rfgn
->rfg
->nves
); ln
;
789 ln
= listnextnode(ln
)) {
790 vnc_direct_add_rn_group_rd(bgp
, rfgn
->rfg
, rn
, &attr
,
791 afi
, listgetdata(ln
));
795 aspath_unintern(&attr
.aspath
);
799 * "Withdrawing a Route" export process
801 void vnc_direct_bgp_del_prefix(struct bgp
*bgp
,
802 struct rfapi_import_table
*import_table
,
803 struct route_node
*rn
)
805 struct listnode
*node
, *nnode
;
806 struct rfapi_rfg_name
*rfgn
;
807 afi_t afi
= family2afi(rn
->p
.family
);
810 zlog_err("%s: can't get afi route node", __func__
);
814 /* check bgp redist flag for vnc direct ("vpn") routes */
815 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
816 vnc_zlog_debug_verbose(
817 "%s: bgp redistribution of VNC direct routes is off",
822 if (!bgp
->rfapi_cfg
) {
823 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
828 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
829 vnc_zlog_debug_verbose(
830 "%s: export-to-bgp group mode not enabled, skipping",
835 if (!listcount(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
)) {
836 vnc_zlog_debug_verbose(
837 "%s: no bgp-direct export nve group, skipping",
842 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
848 * If nve group is not defined yet, skip it
854 * if no NVEs currently associated with this group, skip it
856 if (rfgn
->rfg
->type
!= RFAPI_GROUP_CFG_VRF
&& !rfgn
->rfg
->nves
)
860 * If the nve group uses a different import table,
863 if (import_table
!= rfgn
->rfg
->rfapi_import_table
)
866 if (rfgn
->rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
868 struct rfapi_descriptor
*irfd
;
870 irfd
= rfgn
->rfg
->rfd
;
872 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
, &nhp
))
875 bgp_withdraw(irfd
->peer
, &rn
->p
, /* prefix */
877 NULL
, /* attr, ignored */
878 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
879 BGP_ROUTE_REDISTRIBUTE
,
880 NULL
, /* RD not used for unicast */
882 NULL
); /* tag not used for unicast */
885 * - but consistent with rest of function
890 * For each NVE that is assigned to the export nve group,
892 * a route with that NVE as its next hop
894 for (ln
= listhead(rfgn
->rfg
->nves
); ln
;
895 ln
= listnextnode(ln
)) {
898 struct rfapi_descriptor
*irfd
;
900 irfd
= listgetdata(ln
);
902 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
, &nhp
))
905 bgp_withdraw(irfd
->peer
, &rn
->p
, /* prefix */
907 NULL
, /* attr, ignored */
908 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
909 BGP_ROUTE_REDISTRIBUTE
,
910 NULL
, /* RD not used for unicast */
912 NULL
); /* tag not used for unicast */
917 void vnc_direct_bgp_add_nve(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
)
919 struct listnode
*node
, *nnode
;
920 struct rfapi_rfg_name
*rfgn
;
921 struct rfapi_nve_group_cfg
*rfg
= rfd
->rfg
;
922 afi_t afi
= family2afi(rfd
->vn_addr
.addr_family
);
925 zlog_err("%s: can't get afi of nve vn addr", __func__
);
931 if (!bgp
->rfapi_cfg
) {
932 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
936 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
937 vnc_zlog_debug_verbose(
938 "%s: export-to-bgp group mode not enabled, skipping",
943 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
944 vnc_zlog_debug_verbose(
945 "%s: bgp redistribution of VNC direct routes is off",
951 * Loop over the list of NVE-Groups configured for
952 * exporting to direct-bgp and see if this new NVE's
953 * group is among them.
955 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
959 * Yes, this NVE's group is configured for export to direct-bgp
961 if (rfgn
->rfg
== rfg
) {
963 struct route_table
*rt
= NULL
;
964 struct route_node
*rn
;
965 struct attr attr
= {0};
966 struct rfapi_import_table
*import_table
;
969 import_table
= rfg
->rfapi_import_table
;
971 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
972 /* TBD set some configured med, see add_vnc_route() */
974 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
975 rt
= import_table
->imported_vpn
[afi
];
977 zlog_err("%s: bad afi %d", __func__
, afi
);
982 * Walk the NVE-Group's VNC Import table
984 for (rn
= route_top(rt
); rn
; rn
= route_next(rn
)) {
989 struct rfapi_descriptor
*irfd
= rfd
;
992 struct bgp_info info
;
994 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
,
999 * per-nve-group prefix list check
1001 if (rfgn
->rfg
->plist_export_bgp
[afi
]) {
1002 if (prefix_list_apply(
1003 rfgn
->rfg
->plist_export_bgp
1013 * Construct new attribute set with
1015 * nexthop and without Tunnel Encap attr
1017 if (encap_attr_export(&hattr
, &attr
,
1021 if (rfgn
->rfg
->routemap_export_bgp
) {
1022 route_map_result_t ret
;
1023 info
.peer
= irfd
->peer
;
1025 ret
= route_map_apply(
1027 ->routemap_export_bgp
,
1030 if (ret
== RMAP_DENYMATCH
) {
1031 bgp_attr_flush(&hattr
);
1036 iattr
= bgp_attr_intern(&hattr
);
1037 bgp_attr_flush(&hattr
);
1039 irfd
->peer
, &rn
->p
, /* prefix */
1041 iattr
, /* bgp_update copies
1044 ZEBRA_ROUTE_VNC_DIRECT
,
1045 BGP_ROUTE_REDISTRIBUTE
, NULL
,
1046 /* RD not used for unicast */
1048 /* tag not used for unicast */
1049 0, 0, NULL
); /* EVPN not used */
1051 bgp_attr_unintern(&iattr
);
1055 aspath_unintern(&attr
.aspath
);
1061 void vnc_direct_bgp_del_nve(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
)
1063 struct listnode
*node
, *nnode
;
1064 struct rfapi_rfg_name
*rfgn
;
1065 struct rfapi_nve_group_cfg
*rfg
= rfd
->rfg
;
1066 afi_t afi
= family2afi(rfd
->vn_addr
.addr_family
);
1069 zlog_err("%s: can't get afi of nve vn addr", __func__
);
1075 if (!bgp
->rfapi_cfg
) {
1076 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1080 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
1081 vnc_zlog_debug_verbose(
1082 "%s: export-to-bgp group mode not enabled, skipping",
1087 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
1088 vnc_zlog_debug_verbose(
1089 "%s: bgp redistribution of VNC direct routes is off",
1095 * Loop over the list of NVE-Groups configured for
1096 * exporting to direct-bgp and see if this new NVE's
1097 * group is among them.
1099 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
1103 * Yes, this NVE's group is configured for export to direct-bgp
1105 if (rfg
&& rfgn
->rfg
== rfg
) {
1107 struct route_table
*rt
= NULL
;
1108 struct route_node
*rn
;
1109 struct rfapi_import_table
*import_table
;
1111 import_table
= rfg
->rfapi_import_table
;
1113 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
1114 rt
= import_table
->imported_vpn
[afi
];
1116 zlog_err("%s: bad afi %d", __func__
, afi
);
1121 * Walk the NVE-Group's VNC Import table
1123 for (rn
= route_top(rt
); rn
; rn
= route_next(rn
)) {
1128 struct rfapi_descriptor
*irfd
= rfd
;
1130 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
,
1134 bgp_withdraw(irfd
->peer
,
1135 &rn
->p
, /* prefix */
1137 NULL
, /* attr, ignored */
1139 ZEBRA_ROUTE_VNC_DIRECT
,
1140 BGP_ROUTE_REDISTRIBUTE
,
1141 NULL
, /* RD not used for
1143 NULL
, 0, NULL
); /* tag not
1152 static void vnc_direct_add_rn_group_rd(struct bgp
*bgp
,
1153 struct rfapi_nve_group_cfg
*rfg
,
1154 struct route_node
*rn
, struct attr
*attr
,
1155 afi_t afi
, struct rfapi_descriptor
*irfd
)
1158 struct bgp_info info
;
1162 if (irfd
== NULL
&& rfg
->type
!= RFAPI_GROUP_CFG_VRF
) {
1163 /* need new rfapi_handle, for peer strcture
1164 * -- based on vnc_add_vrf_prefi */
1165 assert(rfg
->rfd
== NULL
);
1167 if (!rfg
->rt_export_list
|| !rfg
->rfapi_import_table
) {
1168 vnc_zlog_debug_verbose(
1169 "%s: VRF \"%s\" is missing RT import/export configuration.\n",
1170 __func__
, rfg
->name
);
1173 if (!rfg
->rd
.prefixlen
) {
1174 vnc_zlog_debug_verbose(
1175 "%s: VRF \"%s\" is missing RD configuration.\n",
1176 __func__
, rfg
->name
);
1179 if (rfg
->label
> MPLS_LABEL_MAX
) {
1180 vnc_zlog_debug_verbose(
1181 "%s: VRF \"%s\" is missing defaul label configuration.\n",
1182 __func__
, rfg
->name
);
1186 irfd
= XCALLOC(MTYPE_RFAPI_DESC
,
1187 sizeof(struct rfapi_descriptor
));
1191 * leave most fields empty as will get from (dynamic) config
1194 irfd
->default_tunneltype_option
.type
= BGP_ENCAP_TYPE_MPLS
;
1196 if (rfg
->vn_prefix
.family
1197 && !CHECK_FLAG(rfg
->flags
, RFAPI_RFG_VPN_NH_SELF
)) {
1198 rfapiQprefix2Raddr(&rfg
->vn_prefix
, &irfd
->vn_addr
);
1200 memset(&irfd
->vn_addr
, 0, sizeof(struct rfapi_ip_addr
));
1201 irfd
->vn_addr
.addr_family
= AF_INET
;
1202 irfd
->vn_addr
.addr
.v4
= bgp
->router_id
;
1204 irfd
->un_addr
= irfd
->vn_addr
; /* sigh, need something in UN for
1206 vnc_zlog_debug_verbose("%s: Opening RFD for VRF %s", __func__
,
1208 rfapi_init_and_open(bgp
, irfd
, rfg
);
1211 if (irfd
== NULL
|| rfapiRaddr2Qprefix(&irfd
->vn_addr
, &nhp
))
1215 * Construct new attribute set with NVE's VN
1217 * nexthop and without Tunnel Encap attr
1219 if (encap_attr_export(&hattr
, attr
, &nhp
, rn
))
1222 if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD
)) {
1223 vnc_zlog_debug_any("%s: attr follows", __func__
);
1224 rfapiPrintAttrPtrs(NULL
, attr
);
1225 vnc_zlog_debug_any("%s: hattr follows", __func__
);
1226 rfapiPrintAttrPtrs(NULL
, &hattr
);
1229 if (rfg
->routemap_export_bgp
) {
1230 route_map_result_t ret
;
1232 info
.peer
= irfd
->peer
;
1234 ret
= route_map_apply(rfg
->routemap_export_bgp
, &rn
->p
,
1236 if (ret
== RMAP_DENYMATCH
) {
1237 bgp_attr_flush(&hattr
);
1238 vnc_zlog_debug_verbose(
1239 "%s: route map says DENY, so not calling bgp_update",
1245 if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD
)) {
1246 vnc_zlog_debug_any("%s: hattr after route_map_apply:",
1248 rfapiPrintAttrPtrs(NULL
, &hattr
);
1250 iattr
= bgp_attr_intern(&hattr
);
1251 bgp_attr_flush(&hattr
);
1253 bgp_update(irfd
->peer
, &rn
->p
, /* prefix */
1255 iattr
, /* bgp_update copies it */
1256 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
1257 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
1258 NULL
, /* tag not used for unicast */
1259 0, 0, NULL
); /* EVPN not used */
1261 bgp_attr_unintern(&iattr
);
1267 * Caller is responsible for ensuring that the specified nve-group
1268 * is actually part of the list of exported nve groups.
1270 static void vnc_direct_bgp_add_group_afi(struct bgp
*bgp
,
1271 struct rfapi_nve_group_cfg
*rfg
,
1274 struct route_table
*rt
= NULL
;
1275 struct route_node
*rn
;
1276 struct attr attr
= {0};
1277 struct rfapi_import_table
*import_table
;
1279 vnc_zlog_debug_verbose("%s: entry", __func__
);
1281 import_table
= rfg
->rfapi_import_table
;
1282 if (!import_table
) {
1283 vnc_zlog_debug_verbose(
1284 "%s: import table not defined, returning", __func__
);
1288 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
1289 rt
= import_table
->imported_vpn
[afi
];
1291 zlog_err("%s: bad afi %d", __func__
, afi
);
1295 if (!rfg
->nves
&& rfg
->type
!= RFAPI_GROUP_CFG_VRF
) {
1296 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__
);
1300 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
1301 /* TBD set some configured med, see add_vnc_route() */
1304 * Walk the NVE-Group's VNC Import table
1306 for (rn
= route_top(rt
); rn
; rn
= route_next(rn
)) {
1310 struct listnode
*ln
;
1313 * per-nve-group prefix list check
1315 if (rfg
->plist_export_bgp
[afi
]) {
1316 if (prefix_list_apply(
1317 rfg
->plist_export_bgp
[afi
], &rn
->p
)
1322 if (rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
1323 vnc_direct_add_rn_group_rd(bgp
, rfg
, rn
, &attr
,
1327 * - but consistent with rest of function
1332 * For each NVE that is assigned to the export nve
1334 * a route with that NVE as its next hop
1336 for (ln
= listhead(rfg
->nves
); ln
;
1337 ln
= listnextnode(ln
)) {
1338 vnc_direct_add_rn_group_rd(bgp
, rfg
, rn
, &attr
,
1345 aspath_unintern(&attr
.aspath
);
1350 * Caller is responsible for ensuring that the specified nve-group
1351 * is actually part of the list of exported nve groups.
1353 void vnc_direct_bgp_add_group(struct bgp
*bgp
, struct rfapi_nve_group_cfg
*rfg
)
1355 vnc_direct_bgp_add_group_afi(bgp
, rfg
, AFI_IP
);
1356 vnc_direct_bgp_add_group_afi(bgp
, rfg
, AFI_IP6
);
1359 static void vnc_direct_del_rn_group_rd(struct bgp
*bgp
,
1360 struct rfapi_nve_group_cfg
*rfg
,
1361 struct route_node
*rn
, afi_t afi
,
1362 struct rfapi_descriptor
*irfd
)
1366 bgp_withdraw(irfd
->peer
, &rn
->p
, /* prefix */
1368 NULL
, /* attr, ignored */
1369 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
1370 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
1371 NULL
, 0, NULL
); /* tag not used for unicast */
1376 * Caller is responsible for ensuring that the specified nve-group
1377 * was actually part of the list of exported nve groups.
1379 static void vnc_direct_bgp_del_group_afi(struct bgp
*bgp
,
1380 struct rfapi_nve_group_cfg
*rfg
,
1383 struct route_table
*rt
= NULL
;
1384 struct route_node
*rn
;
1385 struct rfapi_import_table
*import_table
;
1387 vnc_zlog_debug_verbose("%s: entry", __func__
);
1389 import_table
= rfg
->rfapi_import_table
;
1390 if (!import_table
) {
1391 vnc_zlog_debug_verbose(
1392 "%s: import table not defined, returning", __func__
);
1396 assert(afi
== AFI_IP
|| afi
== AFI_IP6
);
1397 rt
= import_table
->imported_vpn
[afi
];
1399 if (!rfg
->nves
&& rfg
->type
!= RFAPI_GROUP_CFG_VRF
) {
1400 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__
);
1405 * Walk the NVE-Group's VNC Import table
1407 for (rn
= route_top(rt
); rn
; rn
= route_next(rn
))
1409 if (rfg
->type
== RFAPI_GROUP_CFG_VRF
)
1410 vnc_direct_del_rn_group_rd(bgp
, rfg
, rn
, afi
,
1413 struct listnode
*ln
;
1416 * For each NVE that is assigned to the export
1419 * a route with that NVE as its next hop
1421 for (ln
= listhead(rfg
->nves
); ln
;
1422 ln
= listnextnode(ln
))
1423 vnc_direct_del_rn_group_rd(
1431 * Caller is responsible for ensuring that the specified nve-group
1432 * was actually part of the list of exported nve groups.
1434 void vnc_direct_bgp_del_group(struct bgp
*bgp
, struct rfapi_nve_group_cfg
*rfg
)
1436 vnc_direct_bgp_del_group_afi(bgp
, rfg
, AFI_IP
);
1437 vnc_direct_bgp_del_group_afi(bgp
, rfg
, AFI_IP6
);
1440 void vnc_direct_bgp_reexport_group_afi(struct bgp
*bgp
,
1441 struct rfapi_nve_group_cfg
*rfg
,
1444 struct listnode
*node
;
1445 struct rfapi_rfg_name
*rfgn
;
1447 if (VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
1449 * look in the list of currently-exported groups
1451 for (ALL_LIST_ELEMENTS_RO(
1452 bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
1455 if (rfgn
->rfg
== rfg
) {
1457 * If it matches, reexport it
1459 vnc_direct_bgp_del_group_afi(bgp
, rfg
, afi
);
1460 vnc_direct_bgp_add_group_afi(bgp
, rfg
, afi
);
1468 static void vnc_direct_bgp_unexport_table(afi_t afi
, struct route_table
*rt
,
1469 struct list
*nve_list
)
1473 struct route_node
*rn
;
1475 for (rn
= route_top(rt
); rn
; rn
= route_next(rn
)) {
1479 struct listnode
*hln
;
1480 struct rfapi_descriptor
*irfd
;
1482 for (ALL_LIST_ELEMENTS_RO(nve_list
, hln
,
1485 bgp_withdraw(irfd
->peer
,
1486 &rn
->p
, /* prefix */
1488 NULL
, /* attr, ignored */
1490 ZEBRA_ROUTE_VNC_DIRECT
,
1491 BGP_ROUTE_REDISTRIBUTE
,
1492 NULL
, /* RD not used for
1494 NULL
, 0, NULL
); /* tag not
1505 static void import_table_to_nve_list_direct_bgp(struct bgp
*bgp
,
1506 struct rfapi_import_table
*it
,
1510 struct listnode
*node
;
1511 struct rfapi_rfg_name
*rfgn
;
1514 * Loop over the list of NVE-Groups configured for
1515 * exporting to direct-bgp.
1517 * Build a list of NVEs that use this import table
1520 for (ALL_LIST_ELEMENTS_RO(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
1524 * If this NVE-Group's import table matches the current one
1526 if (rfgn
->rfg
&& rfgn
->rfg
->rfapi_import_table
== it
) {
1527 if (rfgn
->rfg
->nves
)
1528 nve_group_to_nve_list(rfgn
->rfg
, nves
, family
);
1529 else if (rfgn
->rfg
->rfd
1530 && rfgn
->rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
1533 listnode_add(*nves
, rfgn
->rfg
->rfd
);
1539 void vnc_direct_bgp_vpn_enable(struct bgp
*bgp
, afi_t afi
)
1541 struct listnode
*rfgn
;
1542 struct rfapi_nve_group_cfg
*rfg
;
1547 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
1548 vnc_zlog_debug_verbose(
1549 "%s: export-to-bgp group mode not enabled, skipping",
1554 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1555 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1560 * Policy is applied per-nve-group, so we need to iterate
1561 * over the groups to add everything.
1563 for (ALL_LIST_ELEMENTS_RO(bgp
->rfapi_cfg
->nve_groups_sequential
, rfgn
,
1567 * contains policy management
1569 vnc_direct_bgp_add_group_afi(bgp
, rfg
, afi
);
1574 void vnc_direct_bgp_vpn_disable(struct bgp
*bgp
, afi_t afi
)
1576 struct rfapi_import_table
*it
;
1577 uint8_t family
= afi2family(afi
);
1579 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
1585 vnc_zlog_debug_verbose("%s: rfapi not initialized", __func__
);
1589 if (!family
|| (afi
!= AFI_IP
&& afi
!= AFI_IP6
)) {
1590 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1594 for (it
= bgp
->rfapi
->imports
; it
; it
= it
->next
) {
1596 struct list
*nve_list
= NULL
;
1598 import_table_to_nve_list_direct_bgp(bgp
, it
, &nve_list
, family
);
1601 vnc_direct_bgp_unexport_table(
1602 afi
, it
->imported_vpn
[afi
], nve_list
);
1603 list_delete_and_null(&nve_list
);
1609 /***********************************************************************
1610 * Export methods that proxy nexthop END
1611 ***********************************************************************/
1614 /***********************************************************************
1615 * Export methods that preserve original nexthop BEGIN
1616 * rh = "registering nve"
1617 ***********************************************************************/
1621 * "Adding a Route" export process
1622 * TBD do we need to check bi->type and bi->sub_type here, or does
1625 void vnc_direct_bgp_rh_add_route(struct bgp
*bgp
, afi_t afi
,
1626 struct prefix
*prefix
, struct peer
*peer
,
1629 struct vnc_export_info
*eti
;
1631 struct rfapi_cfg
*hc
;
1635 zlog_err("%s: can't get afi of route node", __func__
);
1639 /* check bgp redist flag for vnc direct ("vpn") routes */
1640 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
1641 vnc_zlog_debug_verbose(
1642 "%s: bgp redistribution of VNC direct routes is off",
1647 if (!(hc
= bgp
->rfapi_cfg
)) {
1648 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1653 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
1654 vnc_zlog_debug_verbose(
1655 "%s: export-to-bgp RH mode not enabled, skipping",
1663 if (hc
->plist_export_bgp
[afi
]) {
1664 if (prefix_list_apply(hc
->plist_export_bgp
[afi
], prefix
)
1670 * Construct new attribute set with NVE's VN addr as
1671 * nexthop and without Tunnel Encap attr
1673 if (encap_attr_export(&hattr
, attr
, NULL
, NULL
))
1675 if (hc
->routemap_export_bgp
) {
1676 struct bgp_info info
;
1677 route_map_result_t ret
;
1679 memset(&info
, 0, sizeof(info
));
1682 ret
= route_map_apply(hc
->routemap_export_bgp
, prefix
, RMAP_BGP
,
1684 if (ret
== RMAP_DENYMATCH
) {
1685 bgp_attr_flush(&hattr
);
1690 iattr
= bgp_attr_intern(&hattr
);
1691 bgp_attr_flush(&hattr
);
1694 * record route information that we will need to expire
1697 eti
= vnc_eti_get(bgp
, EXPORT_TYPE_BGP
, prefix
, peer
,
1698 ZEBRA_ROUTE_VNC_DIRECT_RH
, BGP_ROUTE_REDISTRIBUTE
);
1699 rfapiGetVncLifetime(attr
, &eti
->lifetime
);
1700 eti
->lifetime
= rfapiGetHolddownFromLifetime(eti
->lifetime
);
1704 * export expiration timer is already running on
1705 * this route: cancel it
1707 thread_cancel(eti
->timer
);
1711 bgp_update(peer
, prefix
, /* prefix */
1713 iattr
, /* bgp_update copies this attr */
1714 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT_RH
,
1715 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
1716 NULL
, /* tag not used for unicast, EVPN neither */
1717 0, 0, NULL
); /* EVPN not used */
1718 bgp_attr_unintern(&iattr
);
1721 static int vncExportWithdrawTimer(struct thread
*t
)
1723 struct vnc_export_info
*eti
= t
->arg
;
1726 * withdraw the route
1728 bgp_withdraw(eti
->peer
, &eti
->node
->p
, 0, /* addpath_id */
1729 NULL
, /* attr, ignored */
1730 family2afi(eti
->node
->p
.family
), SAFI_UNICAST
, eti
->type
,
1731 eti
->subtype
, NULL
, /* RD not used for unicast */
1733 NULL
); /* tag not used for unicast, EVPN neither */
1738 vnc_eti_delete(eti
);
1744 * "Withdrawing a Route" export process
1745 * TBD do we need to check bi->type and bi->sub_type here, or does
1748 void vnc_direct_bgp_rh_del_route(struct bgp
*bgp
, afi_t afi
,
1749 struct prefix
*prefix
, struct peer
*peer
)
1751 struct vnc_export_info
*eti
;
1754 zlog_err("%s: can't get afi route node", __func__
);
1758 /* check bgp redist flag for vnc direct ("vpn") routes */
1759 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
1760 vnc_zlog_debug_verbose(
1761 "%s: bgp redistribution of VNC direct routes is off",
1766 if (!bgp
->rfapi_cfg
) {
1767 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1771 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
1772 vnc_zlog_debug_verbose(
1773 "%s: export-to-bgp group mode not enabled, skipping",
1778 eti
= vnc_eti_get(bgp
, EXPORT_TYPE_BGP
, prefix
, peer
,
1779 ZEBRA_ROUTE_VNC_DIRECT_RH
, BGP_ROUTE_REDISTRIBUTE
);
1781 if (!eti
->timer
&& eti
->lifetime
<= INT32_MAX
) {
1783 thread_add_timer(bm
->master
, vncExportWithdrawTimer
, eti
,
1784 eti
->lifetime
, &eti
->timer
);
1785 vnc_zlog_debug_verbose(
1786 "%s: set expiration timer for %u seconds", __func__
,
1792 void vnc_direct_bgp_rh_vpn_enable(struct bgp
*bgp
, afi_t afi
)
1794 struct prefix_rd prd
;
1795 struct bgp_node
*prn
;
1796 struct rfapi_cfg
*hc
;
1798 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
1803 if (!(hc
= bgp
->rfapi_cfg
))
1806 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
1807 vnc_zlog_debug_verbose(
1808 "%s: export of RH routes not enabled, skipping",
1813 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1814 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1819 * Go through the entire BGP VPN table and export to BGP unicast.
1822 vnc_zlog_debug_verbose("%s: starting RD loop", __func__
);
1824 /* Loop over all the RDs */
1825 for (prn
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); prn
;
1826 prn
= bgp_route_next(prn
)) {
1828 struct bgp_table
*table
;
1829 struct bgp_node
*rn
;
1830 struct bgp_info
*ri
;
1832 memset(&prd
, 0, sizeof(prd
));
1833 prd
.family
= AF_UNSPEC
;
1835 memcpy(prd
.val
, prn
->p
.u
.val
, 8);
1837 /* This is the per-RD table of prefixes */
1843 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
1846 * skip prefix list check if no routes here
1852 char prefixstr
[PREFIX_STRLEN
];
1854 prefix2str(&rn
->p
, prefixstr
,
1856 vnc_zlog_debug_verbose("%s: checking prefix %s",
1857 __func__
, prefixstr
);
1863 if (hc
->plist_export_bgp
[afi
]) {
1864 if (prefix_list_apply(hc
->plist_export_bgp
[afi
],
1868 vnc_zlog_debug_verbose(
1869 "%s: prefix list says DENY",
1875 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1877 vnc_zlog_debug_verbose("%s: ri->sub_type: %d",
1878 __func__
, ri
->sub_type
);
1880 if (ri
->sub_type
== BGP_ROUTE_NORMAL
1881 || ri
->sub_type
== BGP_ROUTE_RFP
) {
1883 struct vnc_export_info
*eti
;
1888 * Construct new attribute set with
1890 * nexthop and without Tunnel Encap attr
1892 if (encap_attr_export(&hattr
, ri
->attr
,
1894 vnc_zlog_debug_verbose(
1895 "%s: encap_attr_export failed",
1900 if (hc
->routemap_export_bgp
) {
1901 struct bgp_info info
;
1902 route_map_result_t ret
;
1904 memset(&info
, 0, sizeof(info
));
1905 info
.peer
= ri
->peer
;
1907 ret
= route_map_apply(
1908 hc
->routemap_export_bgp
,
1911 if (ret
== RMAP_DENYMATCH
) {
1912 bgp_attr_flush(&hattr
);
1913 vnc_zlog_debug_verbose(
1914 "%s: route map says DENY",
1920 iattr
= bgp_attr_intern(&hattr
);
1921 bgp_attr_flush(&hattr
);
1924 * record route information that we will
1929 bgp
, EXPORT_TYPE_BGP
, &rn
->p
,
1931 ZEBRA_ROUTE_VNC_DIRECT_RH
,
1932 BGP_ROUTE_REDISTRIBUTE
);
1933 rfapiGetVncLifetime(ri
->attr
,
1938 * export expiration timer is
1939 * already running on
1940 * this route: cancel it
1942 thread_cancel(eti
->timer
);
1946 vnc_zlog_debug_verbose(
1947 "%s: calling bgp_update",
1951 ri
->peer
, &rn
->p
, /* prefix */
1953 iattr
, /* bgp_update copies
1955 AFI_IP
, SAFI_UNICAST
,
1956 ZEBRA_ROUTE_VNC_DIRECT_RH
,
1957 BGP_ROUTE_REDISTRIBUTE
, NULL
,
1958 /* RD not used for unicast */
1960 /* tag not used for unicast,
1962 0, 0, NULL
); /* EVPN not used */
1964 bgp_attr_unintern(&iattr
);
1971 void vnc_direct_bgp_rh_vpn_disable(struct bgp
*bgp
, afi_t afi
)
1973 struct bgp_node
*rn
;
1975 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
1980 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1981 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1986 * Go through the entire BGP unicast table and remove routes that
1987 * originated from us
1989 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_UNICAST
]); rn
;
1990 rn
= bgp_route_next(rn
)) {
1992 struct bgp_info
*ri
;
1993 struct bgp_info
*next
;
1995 for (ri
= rn
->info
, next
= NULL
; ri
; ri
= next
) {
1999 if (ri
->type
== ZEBRA_ROUTE_VNC_DIRECT_RH
2000 && ri
->sub_type
== BGP_ROUTE_REDISTRIBUTE
) {
2002 struct vnc_export_info
*eti
;
2005 * Delete routes immediately (no timer)
2007 eti
= vnc_eti_checktimer(
2008 bgp
, EXPORT_TYPE_BGP
, &rn
->p
, ri
->peer
,
2009 ZEBRA_ROUTE_VNC_DIRECT_RH
,
2010 BGP_ROUTE_REDISTRIBUTE
);
2013 thread_cancel(eti
->timer
);
2014 vnc_eti_delete(eti
);
2017 bgp_withdraw(ri
->peer
, &rn
->p
, /* prefix */
2020 AFI_IP
, SAFI_UNICAST
,
2021 ZEBRA_ROUTE_VNC_DIRECT_RH
,
2022 BGP_ROUTE_REDISTRIBUTE
,
2023 NULL
, /* RD not used for unicast */
2024 NULL
, 0, NULL
); /* tag not used for
2032 void vnc_direct_bgp_rh_reexport(struct bgp
*bgp
, afi_t afi
)
2034 if (VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
2035 vnc_direct_bgp_rh_vpn_disable(bgp
, afi
);
2036 vnc_direct_bgp_rh_vpn_enable(bgp
, afi
);
2040 /***********************************************************************
2041 * Generic Export methods
2042 ***********************************************************************/
2045 * Assumes the correct mode bits are already turned on. Thus it
2046 * is OK to call this function from, e.g., bgp_redistribute_set()
2047 * without caring if export is enabled or not
2049 void vnc_export_bgp_enable(struct bgp
*bgp
, afi_t afi
)
2051 if (!bgp
->rfapi_cfg
)
2054 switch (bgp
->rfapi_cfg
->flags
& BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS
) {
2055 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE
:
2058 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP
:
2059 vnc_direct_bgp_vpn_enable(bgp
, afi
);
2062 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH
:
2063 vnc_direct_bgp_rh_vpn_enable(bgp
, afi
);
2066 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE
:
2067 vnc_direct_bgp_vpn_enable_ce(bgp
, afi
);
2072 void vnc_export_bgp_disable(struct bgp
*bgp
, afi_t afi
)
2074 if (!bgp
->rfapi_cfg
)
2077 switch (bgp
->rfapi_cfg
->flags
& BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS
) {
2078 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE
:
2081 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP
:
2082 vnc_direct_bgp_vpn_disable(bgp
, afi
);
2085 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH
:
2086 vnc_direct_bgp_rh_vpn_disable(bgp
, afi
);
2089 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE
:
2090 vnc_direct_bgp_vpn_disable_ce(bgp
, afi
);
2095 void vnc_export_bgp_prechange(struct bgp
*bgp
)
2097 vnc_export_bgp_disable(bgp
, AFI_IP
);
2098 vnc_export_bgp_disable(bgp
, AFI_IP6
);
2101 void vnc_export_bgp_postchange(struct bgp
*bgp
)
2103 vnc_export_bgp_enable(bgp
, AFI_IP
);
2104 vnc_export_bgp_enable(bgp
, AFI_IP6
);
2107 void vnc_direct_bgp_reexport(struct bgp
*bgp
, afi_t afi
)
2109 vnc_export_bgp_disable(bgp
, afi
);
2110 vnc_export_bgp_enable(bgp
, afi
);