3 * Copyright 2009-2016, LabN Consulting, L.L.C.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 * File: vnc_export_bgp.c
23 * Purpose: Export routes to BGP directly (not via zebra)
26 #include "lib/zebra.h"
27 #include "lib/prefix.h"
28 #include "lib/agg_table.h"
31 #include "lib/stream.h"
32 #include "lib/memory.h"
33 #include "lib/linklist.h"
34 #include "lib/plist.h"
35 #include "lib/routemap.h"
36 #include "lib/lib_errors.h"
38 #include "bgpd/bgpd.h"
39 #include "bgpd/bgp_ecommunity.h"
40 #include "bgpd/bgp_attr.h"
41 #include "bgpd/bgp_aspath.h"
43 #include "bgpd/rfapi/vnc_export_bgp.h"
44 #include "bgpd/rfapi/vnc_export_bgp_p.h"
45 #include "bgpd/rfapi/vnc_export_table.h"
46 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
47 #include "bgpd/rfapi/rfapi.h"
48 #include "bgpd/rfapi/rfapi_import.h"
49 #include "bgpd/rfapi/rfapi_private.h"
50 #include "bgpd/rfapi/rfapi_backend.h"
51 #include "bgpd/rfapi/rfapi_vty.h"
52 #include "bgpd/rfapi/vnc_debug.h"
55 static void vnc_direct_add_rn_group_rd(struct bgp
*bgp
,
56 struct rfapi_nve_group_cfg
*rfg
,
57 struct agg_node
*rn
, struct attr
*attr
,
59 struct rfapi_descriptor
*irfd
);
61 /***********************************************************************
62 * Export methods that set nexthop to CE (from 5226 roo EC) BEGIN
63 ***********************************************************************/
66 * Memory allocation approach: make a ghost attr that
67 * has non-interned parts for the modifications. ghost attr
68 * memory is allocated by caller.
70 * - extract ce (=5226) EC and use as new nexthop
71 * - strip Tunnel Encap attr
74 static void encap_attr_export_ce(struct attr
*new, struct attr
*orig
,
75 struct prefix
*use_nexthop
)
78 * Make "new" a ghost attr copy of "orig"
80 memset(new, 0, sizeof(struct attr
));
86 switch (use_nexthop
->family
) {
88 new->nexthop
= use_nexthop
->u
.prefix4
;
89 new->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
; /* bytes */
90 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
94 new->mp_nexthop_global
= use_nexthop
->u
.prefix6
;
95 new->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
; /* bytes */
106 * Note that it will be deleted when BGP sends to any eBGP
107 * peer unless PEER_FLAG_MED_UNCHANGED is set:
109 * neighbor NEIGHBOR attribute-unchanged med
111 if (!CHECK_FLAG(new->flag
, BGP_ATTR_MULTI_EXIT_DISC
)) {
112 if (CHECK_FLAG(new->flag
, BGP_ATTR_LOCAL_PREF
)) {
113 if (new->local_pref
> 255)
116 new->med
= 255 - new->local_pref
;
118 new->med
= 255; /* shouldn't happen */
120 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
124 * "new" is now a ghost attr:
125 * - it owns an "extra" struct
126 * - it owns any non-interned parts
127 * - any references to interned parts are not counted
129 * Caller should, after using the attr, call:
130 * - bgp_attr_flush() to free non-interned parts
134 static int getce(struct bgp
*bgp
, struct attr
*attr
, struct prefix
*pfx_ce
)
138 uint16_t localadmin
= bgp
->rfapi_cfg
->resolve_nve_roo_local_admin
;
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
,
176 struct bgp_path_info
*bpi
)
178 struct attr
*attr
= bpi
->attr
;
179 struct peer
*peer
= bpi
->peer
;
180 const struct prefix
*prefix
= agg_node_get_prefix(rn
);
181 afi_t afi
= family2afi(prefix
->family
);
182 struct bgp_dest
*udest
;
183 struct bgp_path_info
*ubpi
;
186 struct prefix ce_nexthop
;
187 struct prefix post_routemap_nexthop
;
191 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of route node",
196 if ((bpi
->type
!= ZEBRA_ROUTE_BGP
)
197 || (bpi
->sub_type
!= BGP_ROUTE_NORMAL
198 && bpi
->sub_type
!= BGP_ROUTE_RFP
199 && bpi
->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 udest
= bgp_afi_node_get(bgp
->rib
[afi
][SAFI_UNICAST
], afi
, SAFI_UNICAST
,
259 for (ubpi
= bgp_dest_get_bgp_path_info(udest
); ubpi
;
261 struct prefix unicast_nexthop
;
263 if (CHECK_FLAG(ubpi
->flags
, BGP_PATH_REMOVED
))
266 rfapiUnicastNexthop2Prefix(afi
, ubpi
->attr
, &unicast_nexthop
);
268 if (ubpi
->type
== ZEBRA_ROUTE_VNC_DIRECT
269 && ubpi
->sub_type
== BGP_ROUTE_REDISTRIBUTE
270 && ubpi
->peer
== peer
271 && prefix_same(&unicast_nexthop
, &ce_nexthop
)) {
273 vnc_zlog_debug_verbose(
274 "%s: already have matching exported unicast route, skipping",
281 * Construct new attribute set with CE addr as
282 * nexthop and without Tunnel Encap attr
284 encap_attr_export_ce(&hattr
, attr
, &ce_nexthop
);
285 if (bgp
->rfapi_cfg
->routemap_export_bgp
) {
286 struct bgp_path_info info
;
287 route_map_result_t ret
;
289 memset(&info
, 0, sizeof(info
));
292 ret
= route_map_apply(bgp
->rfapi_cfg
->routemap_export_bgp
,
293 prefix
, RMAP_BGP
, &info
);
294 if (ret
== RMAP_DENYMATCH
) {
295 bgp_attr_flush(&hattr
);
300 iattr
= bgp_attr_intern(&hattr
);
301 bgp_attr_flush(&hattr
);
304 * Rule: disallow route-map alteration of next-hop, because it
305 * would make it too difficult to keep track of the correspondence
306 * between VPN routes and unicast routes.
308 rfapiUnicastNexthop2Prefix(afi
, iattr
, &post_routemap_nexthop
);
310 if (!prefix_same(&ce_nexthop
, &post_routemap_nexthop
)) {
311 vnc_zlog_debug_verbose(
312 "%s: route-map modification of nexthop not allowed, skipping",
314 bgp_attr_unintern(&iattr
);
318 bgp_update(peer
, prefix
, 0, /* addpath_id */
319 iattr
, /* bgp_update copies this attr */
320 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
321 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
322 NULL
, 0, /* tag not used for unicast */
323 0, NULL
); /* EVPN not used */
324 bgp_attr_unintern(&iattr
);
329 * "Withdrawing a Route" export process
331 void vnc_direct_bgp_del_route_ce(struct bgp
*bgp
, struct agg_node
*rn
,
332 struct bgp_path_info
*bpi
)
334 const struct prefix
*p
= agg_node_get_prefix(rn
);
335 afi_t afi
= family2afi(p
->family
);
336 struct bgp_path_info
*vbpi
;
337 struct prefix ce_nexthop
;
340 flog_err(EC_LIB_DEVELOPMENT
, "%s: bad afi", __func__
);
344 /* check bgp redist flag for vnc direct ("vpn") routes */
345 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
346 vnc_zlog_debug_verbose(
347 "%s: bgp redistribution of VNC direct routes is off",
352 if (!bgp
->rfapi_cfg
) {
353 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
357 if (!VNC_EXPORT_BGP_CE_ENABLED(bgp
->rfapi_cfg
)) {
358 vnc_zlog_debug_verbose(
359 "%s: export-to-bgp ce mode not enabled, skipping",
366 * This works only for IPv4 because IPv6 addresses are too big
367 * to fit in an extended community
369 if (getce(bgp
, bpi
->attr
, &ce_nexthop
)) {
370 vnc_zlog_debug_verbose("%s: EC has no encoded CE, skipping",
376 * Look for other VPN routes with same prefix, same 5226 CE,
377 * same peer. If at least one is present, don't remove the
378 * route from the unicast RIB
381 for (vbpi
= rn
->info
; vbpi
; vbpi
= vbpi
->next
) {
385 if (bpi
->peer
!= vbpi
->peer
)
387 if (getce(bgp
, vbpi
->attr
, &ce
))
389 if (prefix_same(&ce
, &ce_nexthop
)) {
390 vnc_zlog_debug_verbose(
391 "%s: still have a route via CE, not deleting unicast",
400 bgp_withdraw(bpi
->peer
, p
, 0, /* addpath_id */
401 NULL
, /* attr, ignored */
402 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
403 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
404 NULL
, 0, NULL
); /* tag not used for unicast */
407 static void vnc_direct_bgp_vpn_enable_ce(struct bgp
*bgp
, afi_t afi
)
410 struct bgp_path_info
*ri
;
412 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
417 if (!(bgp
->rfapi_cfg
))
420 if (!VNC_EXPORT_BGP_CE_ENABLED(bgp
->rfapi_cfg
)) {
421 vnc_zlog_debug_verbose(
422 "%s: export of CE routes not enabled, skipping",
427 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
428 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
433 * Go through entire ce import table and export to BGP unicast.
435 for (rn
= agg_route_top(bgp
->rfapi
->it_ce
->imported_vpn
[afi
]); rn
;
436 rn
= agg_route_next(rn
)) {
440 vnc_zlog_debug_verbose("%s: checking prefix %pRN", __func__
,
443 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
445 vnc_zlog_debug_verbose("%s: ri->sub_type: %d", __func__
,
448 if (ri
->sub_type
== BGP_ROUTE_NORMAL
449 || ri
->sub_type
== BGP_ROUTE_RFP
450 || ri
->sub_type
== BGP_ROUTE_STATIC
) {
452 vnc_direct_bgp_add_route_ce(bgp
, rn
, ri
);
458 static void vnc_direct_bgp_vpn_disable_ce(struct bgp
*bgp
, afi_t afi
)
460 struct bgp_dest
*dest
;
462 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
467 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
468 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
473 * Go through the entire BGP unicast table and remove routes that
476 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_UNICAST
]); dest
;
477 dest
= bgp_route_next(dest
)) {
479 struct bgp_path_info
*ri
;
480 struct bgp_path_info
*next
;
482 for (ri
= bgp_dest_get_bgp_path_info(dest
), next
= NULL
; ri
;
487 if (ri
->type
== ZEBRA_ROUTE_VNC_DIRECT
488 && ri
->sub_type
== BGP_ROUTE_REDISTRIBUTE
) {
491 ri
->peer
, bgp_dest_get_prefix(dest
),
494 AFI_IP
, SAFI_UNICAST
,
495 ZEBRA_ROUTE_VNC_DIRECT
,
496 BGP_ROUTE_REDISTRIBUTE
,
497 NULL
, /* RD not used for unicast */
499 NULL
); /* tag not used for unicast */
505 /***********************************************************************
506 * Export methods that set nexthop to CE (from 5226 roo EC) END
507 ***********************************************************************/
509 /***********************************************************************
510 * Export methods that proxy nexthop BEGIN
511 ***********************************************************************/
513 static struct ecommunity
*vnc_route_origin_ecom(struct agg_node
*rn
)
515 struct ecommunity
*new;
516 struct bgp_path_info
*bpi
;
521 new = ecommunity_new();
523 for (bpi
= rn
->info
; bpi
; bpi
= bpi
->next
) {
525 struct ecommunity_val roec
;
527 switch (BGP_MP_NEXTHOP_FAMILY(bpi
->attr
->mp_nexthop_len
)) {
529 memset(&roec
, 0, sizeof(roec
));
533 &bpi
->attr
->mp_nexthop_global_in
.s_addr
, 4);
536 ecommunity_add_val(new, &roec
, false, false);
539 /* No support for IPv6 addresses in extended communities
546 ecommunity_free(&new);
553 static struct ecommunity
*vnc_route_origin_ecom_single(struct in_addr
*origin
)
555 struct ecommunity
*new;
556 struct ecommunity_val roec
;
558 memset(&roec
, 0, sizeof(roec
));
561 memcpy(roec
.val
+ 2, &origin
->s_addr
, 4);
565 new = ecommunity_new();
567 ecommunity_add_val(new, &roec
, false, false);
570 ecommunity_free(&new);
579 * New memory allocation approach: make a ghost attr that
580 * has non-interned parts for the modifications. ghost attr
581 * memory is allocated by caller.
584 encap_attr_export(struct attr
*new, struct attr
*orig
,
585 struct prefix
*new_nexthop
,
586 struct agg_node
*rn
) /* for VN addrs for ecom list */
587 /* if rn is 0, use route's nexthop */
589 struct prefix orig_nexthop
;
590 struct prefix
*use_nexthop
;
591 static struct ecommunity
*ecom_ro
;
594 use_nexthop
= new_nexthop
;
596 use_nexthop
= &orig_nexthop
;
597 orig_nexthop
.family
=
598 BGP_MP_NEXTHOP_FAMILY(orig
->mp_nexthop_len
);
599 if (orig_nexthop
.family
== AF_INET
) {
600 orig_nexthop
.prefixlen
= 32;
601 orig_nexthop
.u
.prefix4
= orig
->mp_nexthop_global_in
;
602 } else if (orig_nexthop
.family
== AF_INET6
) {
603 orig_nexthop
.prefixlen
= 128;
604 orig_nexthop
.u
.prefix6
= orig
->mp_nexthop_global
;
606 return -1; /* FAIL - can't compute nexthop */
612 * Make "new" a ghost attr copy of "orig"
614 memset(new, 0, sizeof(struct attr
));
620 switch (use_nexthop
->family
) {
622 new->nexthop
= use_nexthop
->u
.prefix4
;
623 new->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV4
; /* bytes */
624 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP
);
628 new->mp_nexthop_global
= use_nexthop
->u
.prefix6
;
629 new->mp_nexthop_len
= BGP_ATTR_NHLEN_IPV6_GLOBAL
; /* bytes */
638 ecom_ro
= vnc_route_origin_ecom(rn
);
640 /* TBD use lcom for IPv6 */
641 ecom_ro
= vnc_route_origin_ecom_single(&use_nexthop
->u
.prefix4
);
643 if (new->ecommunity
) {
646 ecommunity_merge(ecom_ro
, new->ecommunity
);
648 new->ecommunity
= ecom_ro
;
651 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES
);
657 * Note that it will be deleted when BGP sends to any eBGP
658 * peer unless PEER_FLAG_MED_UNCHANGED is set:
660 * neighbor NEIGHBOR attribute-unchanged med
662 if (!CHECK_FLAG(new->flag
, BGP_ATTR_MULTI_EXIT_DISC
)) {
663 if (CHECK_FLAG(new->flag
, BGP_ATTR_LOCAL_PREF
)) {
664 if (new->local_pref
> 255)
667 new->med
= 255 - new->local_pref
;
669 new->med
= 255; /* shouldn't happen */
671 new->flag
|= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC
);
675 * "new" is now a ghost attr:
676 * - it owns an "extra" struct
677 * - it owns any non-interned parts
678 * - any references to interned parts are not counted
680 * Caller should, after using the attr, call:
681 * - bgp_attr_flush() to free non-interned parts
688 * "Adding a Route" export process
690 void vnc_direct_bgp_add_prefix(struct bgp
*bgp
,
691 struct rfapi_import_table
*import_table
,
694 struct attr attr
= {0};
695 struct listnode
*node
, *nnode
;
696 struct rfapi_rfg_name
*rfgn
;
697 const struct prefix
*p
= agg_node_get_prefix(rn
);
698 afi_t afi
= family2afi(p
->family
);
701 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of route node",
706 /* check bgp redist flag for vnc direct ("vpn") routes */
707 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
708 vnc_zlog_debug_verbose(
709 "%s: bgp redistribution of VNC direct routes is off",
714 if (!bgp
->rfapi_cfg
) {
715 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
720 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
721 vnc_zlog_debug_verbose(
722 "%s: export-to-bgp group mode not enabled, skipping",
727 if (!listcount(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
)) {
728 vnc_zlog_debug_verbose(
729 "%s: no bgp-direct export nve group, skipping",
734 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
735 /* TBD set some configured med, see add_vnc_route() */
737 vnc_zlog_debug_verbose(
738 "%s: looping over nve-groups in direct-bgp export list",
741 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
747 * If nve group is not defined yet, skip it
753 * If the nve group uses a different import table, skip it
755 if (import_table
!= rfgn
->rfg
->rfapi_import_table
)
759 * if no NVEs currently associated with this group, skip it
761 if (rfgn
->rfg
->type
!= RFAPI_GROUP_CFG_VRF
&& !rfgn
->rfg
->nves
)
765 * per-nve-group prefix list check
767 if (rfgn
->rfg
->plist_export_bgp
[afi
]) {
768 if (prefix_list_apply(rfgn
->rfg
->plist_export_bgp
[afi
],
775 if (rfgn
->rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
776 vnc_direct_add_rn_group_rd(bgp
, rfgn
->rfg
, rn
, &attr
,
777 afi
, rfgn
->rfg
->rfd
);
780 * - but consistent with rest of function
785 * For each NVE that is assigned to the export nve group,
787 * a route with that NVE as its next hop
789 for (ln
= listhead(rfgn
->rfg
->nves
); ln
;
790 ln
= listnextnode(ln
)) {
791 vnc_direct_add_rn_group_rd(bgp
, rfgn
->rfg
, rn
, &attr
,
792 afi
, listgetdata(ln
));
796 aspath_unintern(&attr
.aspath
);
800 * "Withdrawing a Route" export process
802 void vnc_direct_bgp_del_prefix(struct bgp
*bgp
,
803 struct rfapi_import_table
*import_table
,
806 struct listnode
*node
, *nnode
;
807 struct rfapi_rfg_name
*rfgn
;
808 const struct prefix
*p
= agg_node_get_prefix(rn
);
809 afi_t afi
= family2afi(p
->family
);
812 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi route node",
817 /* check bgp redist flag for vnc direct ("vpn") routes */
818 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
819 vnc_zlog_debug_verbose(
820 "%s: bgp redistribution of VNC direct routes is off",
825 if (!bgp
->rfapi_cfg
) {
826 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
831 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
832 vnc_zlog_debug_verbose(
833 "%s: export-to-bgp group mode not enabled, skipping",
838 if (!listcount(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
)) {
839 vnc_zlog_debug_verbose(
840 "%s: no bgp-direct export nve group, skipping",
845 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
851 * If nve group is not defined yet, skip it
857 * if no NVEs currently associated with this group, skip it
859 if (rfgn
->rfg
->type
!= RFAPI_GROUP_CFG_VRF
&& !rfgn
->rfg
->nves
)
863 * If the nve group uses a different import table,
866 if (import_table
!= rfgn
->rfg
->rfapi_import_table
)
869 if (rfgn
->rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
871 struct rfapi_descriptor
*irfd
;
873 irfd
= rfgn
->rfg
->rfd
;
875 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
, &nhp
))
878 bgp_withdraw(irfd
->peer
, p
, /* prefix */
880 NULL
, /* attr, ignored */
881 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
882 BGP_ROUTE_REDISTRIBUTE
,
883 NULL
, /* RD not used for unicast */
885 NULL
); /* tag not used for unicast */
888 * - but consistent with rest of function
893 * For each NVE that is assigned to the export nve group,
895 * a route with that NVE as its next hop
897 for (ln
= listhead(rfgn
->rfg
->nves
); ln
;
898 ln
= listnextnode(ln
)) {
901 struct rfapi_descriptor
*irfd
;
903 irfd
= listgetdata(ln
);
905 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
, &nhp
))
908 bgp_withdraw(irfd
->peer
, p
, /* prefix */
910 NULL
, /* attr, ignored */
911 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
912 BGP_ROUTE_REDISTRIBUTE
,
913 NULL
, /* RD not used for unicast */
915 NULL
); /* tag not used for unicast */
920 void vnc_direct_bgp_add_nve(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
)
922 struct listnode
*node
, *nnode
;
923 struct rfapi_rfg_name
*rfgn
;
924 struct rfapi_nve_group_cfg
*rfg
= rfd
->rfg
;
925 afi_t afi
= family2afi(rfd
->vn_addr
.addr_family
);
928 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of nve vn addr",
935 if (!bgp
->rfapi_cfg
) {
936 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
940 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
941 vnc_zlog_debug_verbose(
942 "%s: export-to-bgp group mode not enabled, skipping",
947 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
948 vnc_zlog_debug_verbose(
949 "%s: bgp redistribution of VNC direct routes is off",
955 * Loop over the list of NVE-Groups configured for
956 * exporting to direct-bgp and see if this new NVE's
957 * group is among them.
959 for (ALL_LIST_ELEMENTS(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
963 * Yes, this NVE's group is configured for export to direct-bgp
965 if (rfgn
->rfg
== rfg
) {
967 struct agg_table
*rt
= NULL
;
969 struct attr attr
= {0};
970 struct rfapi_import_table
*import_table
;
973 import_table
= rfg
->rfapi_import_table
;
975 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
976 /* TBD set some configured med, see add_vnc_route() */
978 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
979 rt
= import_table
->imported_vpn
[afi
];
981 flog_err(EC_LIB_DEVELOPMENT
, "%s: bad afi %d",
987 * Walk the NVE-Group's VNC Import table
989 for (rn
= agg_route_top(rt
); rn
;
990 rn
= agg_route_next(rn
)) {
995 struct rfapi_descriptor
*irfd
= rfd
;
998 struct bgp_path_info info
;
999 const struct prefix
*p
=
1000 agg_node_get_prefix(rn
);
1002 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
,
1007 * per-nve-group prefix list check
1009 if (rfgn
->rfg
->plist_export_bgp
[afi
]) {
1010 if (prefix_list_apply(
1011 rfgn
->rfg
->plist_export_bgp
1021 * Construct new attribute set with
1023 * nexthop and without Tunnel Encap attr
1025 if (encap_attr_export(&hattr
, &attr
,
1029 if (rfgn
->rfg
->routemap_export_bgp
) {
1030 route_map_result_t ret
;
1031 info
.peer
= irfd
->peer
;
1033 ret
= route_map_apply(
1035 ->routemap_export_bgp
,
1036 p
, RMAP_BGP
, &info
);
1037 if (ret
== RMAP_DENYMATCH
) {
1038 bgp_attr_flush(&hattr
);
1043 iattr
= bgp_attr_intern(&hattr
);
1044 bgp_attr_flush(&hattr
);
1046 irfd
->peer
, 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
, "%s: can't get afi of nve vn addr",
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
)) {
1136 const struct prefix
*p
=
1137 agg_node_get_prefix(rn
);
1139 struct rfapi_descriptor
*irfd
= rfd
;
1141 if (rfapiRaddr2Qprefix(&irfd
->vn_addr
,
1145 bgp_withdraw(irfd
->peer
, 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_path_info info
;
1171 const struct prefix
*p
= agg_node_get_prefix(rn
);
1173 if (irfd
== NULL
&& rfg
->type
!= RFAPI_GROUP_CFG_VRF
) {
1174 /* need new rfapi_handle, for peer strcture
1175 * -- based on vnc_add_vrf_prefi */
1176 assert(rfg
->rfd
== NULL
);
1178 if (!rfg
->rt_export_list
|| !rfg
->rfapi_import_table
) {
1179 vnc_zlog_debug_verbose(
1180 "%s: VRF \"%s\" is missing RT import/export configuration.\n",
1181 __func__
, rfg
->name
);
1184 if (!rfg
->rd
.prefixlen
) {
1185 vnc_zlog_debug_verbose(
1186 "%s: VRF \"%s\" is missing RD configuration.\n",
1187 __func__
, rfg
->name
);
1190 if (rfg
->label
> MPLS_LABEL_MAX
) {
1191 vnc_zlog_debug_verbose(
1192 "%s: VRF \"%s\" is missing default label configuration.\n",
1193 __func__
, rfg
->name
);
1197 irfd
= XCALLOC(MTYPE_RFAPI_DESC
,
1198 sizeof(struct rfapi_descriptor
));
1202 * leave most fields empty as will get from (dynamic) config
1205 irfd
->default_tunneltype_option
.type
= BGP_ENCAP_TYPE_MPLS
;
1207 if (rfg
->vn_prefix
.family
1208 && !CHECK_FLAG(rfg
->flags
, RFAPI_RFG_VPN_NH_SELF
)) {
1209 rfapiQprefix2Raddr(&rfg
->vn_prefix
, &irfd
->vn_addr
);
1211 memset(&irfd
->vn_addr
, 0, sizeof(struct rfapi_ip_addr
));
1212 irfd
->vn_addr
.addr_family
= AF_INET
;
1213 irfd
->vn_addr
.addr
.v4
= bgp
->router_id
;
1215 irfd
->un_addr
= irfd
->vn_addr
; /* sigh, need something in UN for
1217 vnc_zlog_debug_verbose("%s: Opening RFD for VRF %s", __func__
,
1219 rfapi_init_and_open(bgp
, irfd
, rfg
);
1222 if (irfd
== NULL
|| rfapiRaddr2Qprefix(&irfd
->vn_addr
, &nhp
))
1226 * Construct new attribute set with NVE's VN
1228 * nexthop and without Tunnel Encap attr
1230 if (encap_attr_export(&hattr
, attr
, &nhp
, rn
))
1233 if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD
)) {
1234 vnc_zlog_debug_any("%s: attr follows", __func__
);
1235 rfapiPrintAttrPtrs(NULL
, attr
);
1236 vnc_zlog_debug_any("%s: hattr follows", __func__
);
1237 rfapiPrintAttrPtrs(NULL
, &hattr
);
1240 if (rfg
->routemap_export_bgp
) {
1241 route_map_result_t ret
;
1243 info
.peer
= irfd
->peer
;
1245 ret
= route_map_apply(rfg
->routemap_export_bgp
, p
, RMAP_BGP
,
1247 if (ret
== RMAP_DENYMATCH
) {
1248 bgp_attr_flush(&hattr
);
1249 vnc_zlog_debug_verbose(
1250 "%s: route map says DENY, so not calling bgp_update",
1256 if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD
)) {
1257 vnc_zlog_debug_any("%s: hattr after route_map_apply:",
1259 rfapiPrintAttrPtrs(NULL
, &hattr
);
1261 iattr
= bgp_attr_intern(&hattr
);
1262 bgp_attr_flush(&hattr
);
1264 bgp_update(irfd
->peer
, p
, /* prefix */
1266 iattr
, /* bgp_update copies it */
1267 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
1268 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
1269 NULL
, /* tag not used for unicast */
1270 0, 0, NULL
); /* EVPN not used */
1272 bgp_attr_unintern(&iattr
);
1278 * Caller is responsible for ensuring that the specified nve-group
1279 * is actually part of the list of exported nve groups.
1281 static void vnc_direct_bgp_add_group_afi(struct bgp
*bgp
,
1282 struct rfapi_nve_group_cfg
*rfg
,
1285 struct agg_table
*rt
= NULL
;
1286 struct agg_node
*rn
;
1287 struct attr attr
= {0};
1288 struct rfapi_import_table
*import_table
;
1290 vnc_zlog_debug_verbose("%s: entry", __func__
);
1292 import_table
= rfg
->rfapi_import_table
;
1293 if (!import_table
) {
1294 vnc_zlog_debug_verbose(
1295 "%s: import table not defined, returning", __func__
);
1299 if (afi
== AFI_IP
|| afi
== AFI_IP6
) {
1300 rt
= import_table
->imported_vpn
[afi
];
1302 flog_err(EC_LIB_DEVELOPMENT
, "%s: bad afi %d", __func__
, afi
);
1306 if (!rfg
->nves
&& rfg
->type
!= RFAPI_GROUP_CFG_VRF
) {
1307 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__
);
1311 bgp_attr_default_set(&attr
, BGP_ORIGIN_INCOMPLETE
);
1312 /* TBD set some configured med, see add_vnc_route() */
1315 * Walk the NVE-Group's VNC Import table
1317 for (rn
= agg_route_top(rt
); rn
; rn
= agg_route_next(rn
)) {
1320 const struct prefix
*p
= agg_node_get_prefix(rn
);
1321 struct listnode
*ln
;
1324 * per-nve-group prefix list check
1326 if (rfg
->plist_export_bgp
[afi
]) {
1327 if (prefix_list_apply(
1328 rfg
->plist_export_bgp
[afi
], p
)
1333 if (rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
1334 vnc_direct_add_rn_group_rd(bgp
, rfg
, rn
, &attr
,
1338 * - but consistent with rest of function
1343 * For each NVE that is assigned to the export nve
1345 * a route with that NVE as its next hop
1347 for (ln
= listhead(rfg
->nves
); ln
;
1348 ln
= listnextnode(ln
)) {
1349 vnc_direct_add_rn_group_rd(bgp
, rfg
, rn
, &attr
,
1356 aspath_unintern(&attr
.aspath
);
1361 * Caller is responsible for ensuring that the specified nve-group
1362 * is actually part of the list of exported nve groups.
1364 void vnc_direct_bgp_add_group(struct bgp
*bgp
, struct rfapi_nve_group_cfg
*rfg
)
1366 vnc_direct_bgp_add_group_afi(bgp
, rfg
, AFI_IP
);
1367 vnc_direct_bgp_add_group_afi(bgp
, rfg
, AFI_IP6
);
1370 static void vnc_direct_del_rn_group_rd(struct bgp
*bgp
,
1371 struct rfapi_nve_group_cfg
*rfg
,
1372 struct agg_node
*rn
, afi_t afi
,
1373 struct rfapi_descriptor
*irfd
)
1378 bgp_withdraw(irfd
->peer
, agg_node_get_prefix(rn
), /* prefix */
1380 NULL
, /* attr, ignored */
1381 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT
,
1382 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
1383 NULL
, 0, NULL
); /* tag not used for unicast */
1388 * Caller is responsible for ensuring that the specified nve-group
1389 * was actually part of the list of exported nve groups.
1391 static void vnc_direct_bgp_del_group_afi(struct bgp
*bgp
,
1392 struct rfapi_nve_group_cfg
*rfg
,
1395 struct agg_table
*rt
= NULL
;
1396 struct agg_node
*rn
;
1397 struct rfapi_import_table
*import_table
;
1399 vnc_zlog_debug_verbose("%s: entry", __func__
);
1401 import_table
= rfg
->rfapi_import_table
;
1402 if (!import_table
) {
1403 vnc_zlog_debug_verbose(
1404 "%s: import table not defined, returning", __func__
);
1408 rt
= import_table
->imported_vpn
[afi
];
1410 if (!rfg
->nves
&& rfg
->type
!= RFAPI_GROUP_CFG_VRF
) {
1411 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__
);
1416 * Walk the NVE-Group's VNC Import table
1418 for (rn
= agg_route_top(rt
); rn
; rn
= agg_route_next(rn
))
1420 if (rfg
->type
== RFAPI_GROUP_CFG_VRF
)
1421 vnc_direct_del_rn_group_rd(bgp
, rfg
, rn
, afi
,
1424 struct listnode
*ln
;
1427 * For each NVE that is assigned to the export
1430 * a route with that NVE as its next hop
1432 for (ln
= listhead(rfg
->nves
); ln
;
1433 ln
= listnextnode(ln
))
1434 vnc_direct_del_rn_group_rd(
1442 * Caller is responsible for ensuring that the specified nve-group
1443 * was actually part of the list of exported nve groups.
1445 void vnc_direct_bgp_del_group(struct bgp
*bgp
, struct rfapi_nve_group_cfg
*rfg
)
1447 vnc_direct_bgp_del_group_afi(bgp
, rfg
, AFI_IP
);
1448 vnc_direct_bgp_del_group_afi(bgp
, rfg
, AFI_IP6
);
1451 void vnc_direct_bgp_reexport_group_afi(struct bgp
*bgp
,
1452 struct rfapi_nve_group_cfg
*rfg
,
1455 struct listnode
*node
;
1456 struct rfapi_rfg_name
*rfgn
;
1458 if (VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
1460 * look in the list of currently-exported groups
1462 for (ALL_LIST_ELEMENTS_RO(
1463 bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
1466 if (rfgn
->rfg
== rfg
) {
1468 * If it matches, reexport it
1470 vnc_direct_bgp_del_group_afi(bgp
, rfg
, afi
);
1471 vnc_direct_bgp_add_group_afi(bgp
, rfg
, afi
);
1479 static void vnc_direct_bgp_unexport_table(afi_t afi
, struct agg_table
*rt
,
1480 struct list
*nve_list
)
1484 struct agg_node
*rn
;
1486 for (rn
= agg_route_top(rt
); rn
; rn
= agg_route_next(rn
)) {
1490 struct listnode
*hln
;
1491 struct rfapi_descriptor
*irfd
;
1493 for (ALL_LIST_ELEMENTS_RO(nve_list
, hln
,
1496 bgp_withdraw(irfd
->peer
,
1497 agg_node_get_prefix(rn
),
1499 NULL
, /* attr, ignored */
1501 ZEBRA_ROUTE_VNC_DIRECT
,
1502 BGP_ROUTE_REDISTRIBUTE
,
1503 NULL
, /* RD not used for
1505 NULL
, 0, NULL
); /* tag not
1516 static void import_table_to_nve_list_direct_bgp(struct bgp
*bgp
,
1517 struct rfapi_import_table
*it
,
1521 struct listnode
*node
;
1522 struct rfapi_rfg_name
*rfgn
;
1525 * Loop over the list of NVE-Groups configured for
1526 * exporting to direct-bgp.
1528 * Build a list of NVEs that use this import table
1531 for (ALL_LIST_ELEMENTS_RO(bgp
->rfapi_cfg
->rfg_export_direct_bgp_l
, node
,
1535 * If this NVE-Group's import table matches the current one
1537 if (rfgn
->rfg
&& rfgn
->rfg
->rfapi_import_table
== it
) {
1538 if (rfgn
->rfg
->nves
)
1539 nve_group_to_nve_list(rfgn
->rfg
, nves
, family
);
1540 else if (rfgn
->rfg
->rfd
1541 && rfgn
->rfg
->type
== RFAPI_GROUP_CFG_VRF
) {
1544 listnode_add(*nves
, rfgn
->rfg
->rfd
);
1550 void vnc_direct_bgp_vpn_enable(struct bgp
*bgp
, afi_t afi
)
1552 struct listnode
*rfgn
;
1553 struct rfapi_nve_group_cfg
*rfg
;
1558 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp
->rfapi_cfg
)) {
1559 vnc_zlog_debug_verbose(
1560 "%s: export-to-bgp group mode not enabled, skipping",
1565 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1566 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1571 * Policy is applied per-nve-group, so we need to iterate
1572 * over the groups to add everything.
1574 for (ALL_LIST_ELEMENTS_RO(bgp
->rfapi_cfg
->nve_groups_sequential
, rfgn
,
1578 * contains policy management
1580 vnc_direct_bgp_add_group_afi(bgp
, rfg
, afi
);
1585 void vnc_direct_bgp_vpn_disable(struct bgp
*bgp
, afi_t afi
)
1587 struct rfapi_import_table
*it
;
1588 uint8_t family
= afi2family(afi
);
1590 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
1596 vnc_zlog_debug_verbose("%s: rfapi not initialized", __func__
);
1600 if (!family
|| (afi
!= AFI_IP
&& afi
!= AFI_IP6
)) {
1601 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1605 for (it
= bgp
->rfapi
->imports
; it
; it
= it
->next
) {
1607 struct list
*nve_list
= NULL
;
1609 import_table_to_nve_list_direct_bgp(bgp
, it
, &nve_list
, family
);
1612 vnc_direct_bgp_unexport_table(
1613 afi
, it
->imported_vpn
[afi
], nve_list
);
1614 list_delete(&nve_list
);
1620 /***********************************************************************
1621 * Export methods that proxy nexthop END
1622 ***********************************************************************/
1625 /***********************************************************************
1626 * Export methods that preserve original nexthop BEGIN
1627 * rh = "registering nve"
1628 ***********************************************************************/
1632 * "Adding a Route" export process
1633 * TBD do we need to check bpi->type and bpi->sub_type here, or does
1636 void vnc_direct_bgp_rh_add_route(struct bgp
*bgp
, afi_t afi
,
1637 const struct prefix
*prefix
, struct peer
*peer
,
1640 struct vnc_export_info
*eti
;
1642 struct rfapi_cfg
*hc
;
1646 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi of route node",
1651 /* check bgp redist flag for vnc direct ("vpn") routes */
1652 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
1653 vnc_zlog_debug_verbose(
1654 "%s: bgp redistribution of VNC direct routes is off",
1659 if (!(hc
= bgp
->rfapi_cfg
)) {
1660 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1665 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
1666 vnc_zlog_debug_verbose(
1667 "%s: export-to-bgp RH mode not enabled, skipping",
1675 if (hc
->plist_export_bgp
[afi
]) {
1676 if (prefix_list_apply(hc
->plist_export_bgp
[afi
], prefix
)
1682 * Construct new attribute set with NVE's VN addr as
1683 * nexthop and without Tunnel Encap attr
1685 if (encap_attr_export(&hattr
, attr
, NULL
, NULL
))
1687 if (hc
->routemap_export_bgp
) {
1688 struct bgp_path_info info
;
1689 route_map_result_t ret
;
1691 memset(&info
, 0, sizeof(info
));
1694 ret
= route_map_apply(hc
->routemap_export_bgp
, prefix
, RMAP_BGP
,
1696 if (ret
== RMAP_DENYMATCH
) {
1697 bgp_attr_flush(&hattr
);
1702 iattr
= bgp_attr_intern(&hattr
);
1703 bgp_attr_flush(&hattr
);
1706 * record route information that we will need to expire
1709 eti
= vnc_eti_get(bgp
, EXPORT_TYPE_BGP
, prefix
, peer
,
1710 ZEBRA_ROUTE_VNC_DIRECT_RH
, BGP_ROUTE_REDISTRIBUTE
);
1711 rfapiGetVncLifetime(attr
, &eti
->lifetime
);
1712 eti
->lifetime
= rfapiGetHolddownFromLifetime(eti
->lifetime
);
1716 * export expiration timer is already running on
1717 * this route: cancel it
1719 thread_cancel(eti
->timer
);
1723 bgp_update(peer
, prefix
, /* prefix */
1725 iattr
, /* bgp_update copies this attr */
1726 afi
, SAFI_UNICAST
, ZEBRA_ROUTE_VNC_DIRECT_RH
,
1727 BGP_ROUTE_REDISTRIBUTE
, NULL
, /* RD not used for unicast */
1728 NULL
, /* tag not used for unicast, EVPN neither */
1729 0, 0, NULL
); /* EVPN not used */
1730 bgp_attr_unintern(&iattr
);
1733 static int vncExportWithdrawTimer(struct thread
*t
)
1735 struct vnc_export_info
*eti
= t
->arg
;
1736 const struct prefix
*p
= agg_node_get_prefix(eti
->node
);
1739 * withdraw the route
1741 bgp_withdraw(eti
->peer
, p
, 0, /* addpath_id */
1742 NULL
, /* attr, ignored */
1743 family2afi(p
->family
), SAFI_UNICAST
, eti
->type
,
1744 eti
->subtype
, NULL
, /* RD not used for unicast */
1746 NULL
); /* tag not used for unicast, EVPN neither */
1751 vnc_eti_delete(eti
);
1757 * "Withdrawing a Route" export process
1758 * TBD do we need to check bpi->type and bpi->sub_type here, or does
1761 void vnc_direct_bgp_rh_del_route(struct bgp
*bgp
, afi_t afi
,
1762 const struct prefix
*prefix
, struct peer
*peer
)
1764 struct vnc_export_info
*eti
;
1767 flog_err(EC_LIB_DEVELOPMENT
, "%s: can't get afi route node",
1772 /* check bgp redist flag for vnc direct ("vpn") routes */
1773 if (!bgp
->redist
[afi
][ZEBRA_ROUTE_VNC_DIRECT
]) {
1774 vnc_zlog_debug_verbose(
1775 "%s: bgp redistribution of VNC direct routes is off",
1780 if (!bgp
->rfapi_cfg
) {
1781 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1785 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
1786 vnc_zlog_debug_verbose(
1787 "%s: export-to-bgp group mode not enabled, skipping",
1792 eti
= vnc_eti_get(bgp
, EXPORT_TYPE_BGP
, prefix
, peer
,
1793 ZEBRA_ROUTE_VNC_DIRECT_RH
, BGP_ROUTE_REDISTRIBUTE
);
1795 if (!eti
->timer
&& eti
->lifetime
<= INT32_MAX
) {
1797 thread_add_timer(bm
->master
, vncExportWithdrawTimer
, eti
,
1798 eti
->lifetime
, &eti
->timer
);
1799 vnc_zlog_debug_verbose(
1800 "%s: set expiration timer for %u seconds", __func__
,
1806 void vnc_direct_bgp_rh_vpn_enable(struct bgp
*bgp
, afi_t afi
)
1808 struct prefix_rd prd
;
1809 struct bgp_dest
*pdest
;
1810 struct rfapi_cfg
*hc
;
1812 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
1817 if (!(hc
= bgp
->rfapi_cfg
))
1820 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
1821 vnc_zlog_debug_verbose(
1822 "%s: export of RH routes not enabled, skipping",
1827 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1828 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
1833 * Go through the entire BGP VPN table and export to BGP unicast.
1836 vnc_zlog_debug_verbose("%s: starting RD loop", __func__
);
1838 /* Loop over all the RDs */
1839 for (pdest
= bgp_table_top(bgp
->rib
[afi
][SAFI_MPLS_VPN
]); pdest
;
1840 pdest
= bgp_route_next(pdest
)) {
1842 struct bgp_table
*table
;
1843 struct bgp_dest
*dest
;
1844 struct bgp_path_info
*ri
;
1845 const struct prefix
*pdest_p
= bgp_dest_get_prefix(pdest
);
1847 memset(&prd
, 0, sizeof(prd
));
1848 prd
.family
= AF_UNSPEC
;
1850 memcpy(prd
.val
, pdest_p
->u
.val
, 8);
1852 /* This is the per-RD table of prefixes */
1853 table
= bgp_dest_get_bgp_table_info(pdest
);
1858 for (dest
= bgp_table_top(table
); dest
;
1859 dest
= bgp_route_next(dest
)) {
1860 const struct prefix
*dest_p
;
1863 * skip prefix list check if no routes here
1865 if (!bgp_dest_has_bgp_path_info_data(dest
))
1868 vnc_zlog_debug_verbose("%s: checking prefix %pBD",
1871 dest_p
= bgp_dest_get_prefix(dest
);
1876 if (hc
->plist_export_bgp
[afi
]) {
1877 if (prefix_list_apply(hc
->plist_export_bgp
[afi
],
1881 vnc_zlog_debug_verbose(
1882 "%s: prefix list says DENY",
1888 for (ri
= bgp_dest_get_bgp_path_info(dest
); ri
;
1891 vnc_zlog_debug_verbose("%s: ri->sub_type: %d",
1892 __func__
, ri
->sub_type
);
1894 if (ri
->sub_type
== BGP_ROUTE_NORMAL
1895 || ri
->sub_type
== BGP_ROUTE_RFP
) {
1897 struct vnc_export_info
*eti
;
1902 * Construct new attribute set with
1904 * nexthop and without Tunnel Encap attr
1906 if (encap_attr_export(&hattr
, ri
->attr
,
1908 vnc_zlog_debug_verbose(
1909 "%s: encap_attr_export failed",
1914 if (hc
->routemap_export_bgp
) {
1915 struct bgp_path_info info
;
1916 route_map_result_t ret
;
1918 memset(&info
, 0, sizeof(info
));
1919 info
.peer
= ri
->peer
;
1921 ret
= route_map_apply(
1922 hc
->routemap_export_bgp
,
1925 if (ret
== RMAP_DENYMATCH
) {
1926 bgp_attr_flush(&hattr
);
1927 vnc_zlog_debug_verbose(
1928 "%s: route map says DENY",
1934 iattr
= bgp_attr_intern(&hattr
);
1935 bgp_attr_flush(&hattr
);
1938 * record route information that we will
1943 bgp
, EXPORT_TYPE_BGP
, dest_p
,
1945 ZEBRA_ROUTE_VNC_DIRECT_RH
,
1946 BGP_ROUTE_REDISTRIBUTE
);
1947 rfapiGetVncLifetime(ri
->attr
,
1952 * export expiration timer is
1953 * already running on
1954 * this route: cancel it
1956 thread_cancel(eti
->timer
);
1960 vnc_zlog_debug_verbose(
1961 "%s: calling bgp_update",
1965 ri
->peer
, dest_p
, /* prefix */
1967 iattr
, /* bgp_update copies
1969 AFI_IP
, SAFI_UNICAST
,
1970 ZEBRA_ROUTE_VNC_DIRECT_RH
,
1971 BGP_ROUTE_REDISTRIBUTE
, NULL
,
1972 /* RD not used for unicast */
1974 /* tag not used for unicast,
1976 0, 0, NULL
); /* EVPN not used */
1978 bgp_attr_unintern(&iattr
);
1985 void vnc_direct_bgp_rh_vpn_disable(struct bgp
*bgp
, afi_t afi
)
1987 struct bgp_dest
*dest
;
1989 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__
, afi
);
1994 if (afi
!= AFI_IP
&& afi
!= AFI_IP6
) {
1995 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__
, afi
);
2000 * Go through the entire BGP unicast table and remove routes that
2001 * originated from us
2003 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_UNICAST
]); dest
;
2004 dest
= bgp_route_next(dest
)) {
2005 const struct prefix
*dest_p
= bgp_dest_get_prefix(dest
);
2006 struct bgp_path_info
*ri
;
2007 struct bgp_path_info
*next
;
2009 for (ri
= bgp_dest_get_bgp_path_info(dest
), next
= NULL
; ri
;
2014 if (ri
->type
== ZEBRA_ROUTE_VNC_DIRECT_RH
2015 && ri
->sub_type
== BGP_ROUTE_REDISTRIBUTE
) {
2017 struct vnc_export_info
*eti
;
2020 * Delete routes immediately (no timer)
2022 eti
= vnc_eti_checktimer(
2023 bgp
, EXPORT_TYPE_BGP
, dest_p
, ri
->peer
,
2024 ZEBRA_ROUTE_VNC_DIRECT_RH
,
2025 BGP_ROUTE_REDISTRIBUTE
);
2028 thread_cancel(eti
->timer
);
2029 vnc_eti_delete(eti
);
2032 bgp_withdraw(ri
->peer
, dest_p
, /* prefix */
2035 AFI_IP
, SAFI_UNICAST
,
2036 ZEBRA_ROUTE_VNC_DIRECT_RH
,
2037 BGP_ROUTE_REDISTRIBUTE
,
2038 NULL
, /* RD not used for unicast */
2039 NULL
, 0, NULL
); /* tag not used for
2047 void vnc_direct_bgp_rh_reexport(struct bgp
*bgp
, afi_t afi
)
2049 if (VNC_EXPORT_BGP_RH_ENABLED(bgp
->rfapi_cfg
)) {
2050 vnc_direct_bgp_rh_vpn_disable(bgp
, afi
);
2051 vnc_direct_bgp_rh_vpn_enable(bgp
, afi
);
2055 /***********************************************************************
2056 * Generic Export methods
2057 ***********************************************************************/
2060 * Assumes the correct mode bits are already turned on. Thus it
2061 * is OK to call this function from, e.g., bgp_redistribute_set()
2062 * without caring if export is enabled or not
2064 void vnc_export_bgp_enable(struct bgp
*bgp
, afi_t afi
)
2066 if (!bgp
->rfapi_cfg
)
2069 switch (bgp
->rfapi_cfg
->flags
& BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS
) {
2070 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE
:
2073 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP
:
2074 vnc_direct_bgp_vpn_enable(bgp
, afi
);
2077 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH
:
2078 vnc_direct_bgp_rh_vpn_enable(bgp
, afi
);
2081 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE
:
2082 vnc_direct_bgp_vpn_enable_ce(bgp
, afi
);
2087 void vnc_export_bgp_disable(struct bgp
*bgp
, afi_t afi
)
2089 if (!bgp
->rfapi_cfg
)
2092 switch (bgp
->rfapi_cfg
->flags
& BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS
) {
2093 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE
:
2096 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP
:
2097 vnc_direct_bgp_vpn_disable(bgp
, afi
);
2100 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH
:
2101 vnc_direct_bgp_rh_vpn_disable(bgp
, afi
);
2104 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE
:
2105 vnc_direct_bgp_vpn_disable_ce(bgp
, afi
);
2110 void vnc_export_bgp_prechange(struct bgp
*bgp
)
2112 vnc_export_bgp_disable(bgp
, AFI_IP
);
2113 vnc_export_bgp_disable(bgp
, AFI_IP6
);
2116 void vnc_export_bgp_postchange(struct bgp
*bgp
)
2118 vnc_export_bgp_enable(bgp
, AFI_IP
);
2119 vnc_export_bgp_enable(bgp
, AFI_IP6
);
2122 void vnc_direct_bgp_reexport(struct bgp
*bgp
, afi_t afi
)
2124 vnc_export_bgp_disable(bgp
, afi
);
2125 vnc_export_bgp_enable(bgp
, afi
);