]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/rfapi/vnc_export_bgp.c
Merge pull request #2848 from donaldsharp/more_init
[mirror_frr.git] / bgpd / rfapi / vnc_export_bgp.c
CommitLineData
d62a17ae 1/*
65efcfce
LB
2 *
3 * Copyright 2009-2016, LabN Consulting, L.L.C.
4 *
5 *
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.
10 *
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.
15 *
896014f4
DL
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
65efcfce
LB
19 */
20
21/*
22 * File: vnc_export_bgp.c
23 * Purpose: Export routes to BGP directly (not via zebra)
24 */
25
f8b6f499
LB
26#include "lib/zebra.h"
27#include "lib/prefix.h"
28#include "lib/table.h"
29#include "lib/vty.h"
30#include "lib/log.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"
02705213 36#include "lib/lib_errors.h"
65efcfce 37
f8b6f499
LB
38#include "bgpd/bgpd.h"
39#include "bgpd/bgp_ecommunity.h"
40#include "bgpd/bgp_attr.h"
41#include "bgpd/bgp_aspath.h"
65efcfce 42
f8b6f499
LB
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"
65efcfce 53
d477c01d
LB
54
55static void vnc_direct_add_rn_group_rd(struct bgp *bgp,
56 struct rfapi_nve_group_cfg *rfg,
996c9314 57 struct route_node *rn, struct attr *attr,
d477c01d
LB
58 afi_t afi,
59 struct rfapi_descriptor *irfd);
60
65efcfce
LB
61/***********************************************************************
62 * Export methods that set nexthop to CE (from 5226 roo EC) BEGIN
63 ***********************************************************************/
64
65/*
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.
69 *
70 * - extract ce (=5226) EC and use as new nexthop
71 * - strip Tunnel Encap attr
72 * - copy all ECs
73 */
d62a17ae 74static void encap_attr_export_ce(struct attr *new, struct attr *orig,
75 struct prefix *use_nexthop)
65efcfce 76{
d62a17ae 77 /*
78 * Make "new" a ghost attr copy of "orig"
79 */
80 memset(new, 0, sizeof(struct attr));
81 bgp_attr_dup(new, orig);
82
83 /*
84 * Set nexthop
85 */
86 switch (use_nexthop->family) {
87 case AF_INET:
88 new->nexthop = use_nexthop->u.prefix4;
89 new->mp_nexthop_len = 4; /* bytes */
90 new->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
91 break;
92
93 case AF_INET6:
94 new->mp_nexthop_global = use_nexthop->u.prefix6;
95 new->mp_nexthop_len = 16; /* bytes */
96 break;
97
98 default:
99 assert(0);
100 break;
101 }
102
103 /*
104 * Set MED
105 *
106 * Note that it will be deleted when BGP sends to any eBGP
107 * peer unless PEER_FLAG_MED_UNCHANGED is set:
108 *
109 * neighbor NEIGHBOR attribute-unchanged med
110 */
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)
114 new->med = 0;
115 else
116 new->med = 255 - new->local_pref;
117 } else {
118 new->med = 255; /* shouldn't happen */
119 }
120 new->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
121 }
122
123 /*
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
128 *
129 * Caller should, after using the attr, call:
130 * - bgp_attr_flush() to free non-interned parts
131 */
65efcfce
LB
132}
133
d62a17ae 134static int getce(struct bgp *bgp, struct attr *attr, struct prefix *pfx_ce)
65efcfce 135{
d62a17ae 136 uint8_t *ecp;
137 int i;
138 uint16_t localadmin = bgp->rfapi_cfg->resolve_nve_roo_local_admin;
139
140 for (ecp = attr->ecommunity->val, i = 0; i < attr->ecommunity->size;
141 ++i, ecp += ECOMMUNITY_SIZE) {
142
143 if (VNC_DEBUG(EXPORT_BGP_GETCE)) {
144 vnc_zlog_debug_any(
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]);
148 }
149
150 /*
151 * is it ROO?
152 */
153 if (ecp[0] != 1 || ecp[1] != 3) {
154 continue;
155 }
156
157 /*
158 * Match local admin value?
159 */
160 if (ecp[6] != ((localadmin & 0xff00) >> 8)
161 || ecp[7] != (localadmin & 0xff))
162 continue;
163
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;
168
169 return 0;
170 }
171 return -1;
65efcfce
LB
172}
173
174
d62a17ae 175void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct route_node *rn,
176 struct bgp_info *bi)
65efcfce 177{
d62a17ae 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;
184 struct attr hattr;
185 struct attr *iattr;
186 struct prefix ce_nexthop;
187 struct prefix post_routemap_nexthop;
188
189
190 if (!afi) {
af4c2728 191 flog_err(LIB_ERR_DEVELOPMENT,
02705213 192 "%s: can't get afi of route node", __func__);
d62a17ae 193 return;
194 }
195
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)) {
200
201 vnc_zlog_debug_verbose(
202 "%s: wrong route type/sub_type for export, skipping",
203 __func__);
204 return;
205 }
206
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",
211 __func__);
212 return;
213 }
214
215 if (!bgp->rfapi_cfg) {
216 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
217 __func__);
218 return;
219 }
220
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",
224 __func__);
225 return;
226 }
227
228 /*
229 * prefix list check
230 */
231 if (bgp->rfapi_cfg->plist_export_bgp[afi]) {
232 if (prefix_list_apply(bgp->rfapi_cfg->plist_export_bgp[afi],
233 prefix)
234 == PREFIX_DENY) {
235 vnc_zlog_debug_verbose(
236 "%s: prefix list denied, skipping", __func__);
237 return;
238 }
239 }
240
241
242 /*
243 * Extract CE
244 * This works only for IPv4 because IPv6 addresses are too big
245 * to fit in an extended community
246 */
247 if (getce(bgp, attr, &ce_nexthop)) {
248 vnc_zlog_debug_verbose("%s: EC has no encoded CE, skipping",
249 __func__);
250 return;
251 }
252
253 /*
254 * Is this route already represented in the unicast RIB?
255 * (look up prefix; compare route type, sub_type, peer, nexthop)
256 */
257 urn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST,
258 prefix, NULL);
259 for (ubi = urn->info; ubi; ubi = ubi->next) {
260 struct prefix unicast_nexthop;
261
262 if (CHECK_FLAG(ubi->flags, BGP_INFO_REMOVED))
263 continue;
264
265 rfapiUnicastNexthop2Prefix(afi, ubi->attr, &unicast_nexthop);
266
267 if (ubi->type == ZEBRA_ROUTE_VNC_DIRECT
268 && ubi->sub_type == BGP_ROUTE_REDISTRIBUTE
269 && ubi->peer == peer
270 && prefix_same(&unicast_nexthop, &ce_nexthop)) {
271
272 vnc_zlog_debug_verbose(
273 "%s: already have matching exported unicast route, skipping",
274 __func__);
275 return;
276 }
277 }
278
279 /*
280 * Construct new attribute set with CE addr as
281 * nexthop and without Tunnel Encap attr
282 */
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;
287
288 memset(&info, 0, sizeof(info));
289 info.peer = peer;
290 info.attr = &hattr;
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);
295 return;
296 }
297 }
298
299 iattr = bgp_attr_intern(&hattr);
300 bgp_attr_flush(&hattr);
301
302 /*
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.
306 */
307 rfapiUnicastNexthop2Prefix(afi, iattr, &post_routemap_nexthop);
308
309 if (!prefix_same(&ce_nexthop, &post_routemap_nexthop)) {
310 vnc_zlog_debug_verbose(
311 "%s: route-map modification of nexthop not allowed, skipping",
312 __func__);
313 bgp_attr_unintern(&iattr);
314 return;
315 }
316
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 */
b57ba6d2 321 NULL, 0, /* tag not used for unicast */
d62a17ae 322 0, NULL); /* EVPN not used */
323 bgp_attr_unintern(&iattr);
65efcfce
LB
324}
325
326
327/*
328 * "Withdrawing a Route" export process
329 */
d62a17ae 330void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct route_node *rn,
331 struct bgp_info *bi)
65efcfce 332{
d62a17ae 333 afi_t afi = family2afi(rn->p.family);
334 struct bgp_info *vbi;
335 struct prefix ce_nexthop;
336
337 if (!afi) {
af4c2728 338 flog_err(LIB_ERR_DEVELOPMENT, "%s: bad afi", __func__);
d62a17ae 339 return;
340 }
341
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",
346 __func__);
347 return;
348 }
349
350 if (!bgp->rfapi_cfg) {
351 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
352 __func__);
353 return;
354 }
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",
358 __func__);
359 return;
360 }
361
362 /*
363 * Extract CE
364 * This works only for IPv4 because IPv6 addresses are too big
365 * to fit in an extended community
366 */
367 if (getce(bgp, bi->attr, &ce_nexthop)) {
368 vnc_zlog_debug_verbose("%s: EC has no encoded CE, skipping",
369 __func__);
370 return;
371 }
372
373 /*
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
377 */
378
379 for (vbi = rn->info; vbi; vbi = vbi->next) {
380 struct prefix ce;
381 if (bi == vbi)
382 continue;
383 if (bi->peer != vbi->peer)
384 continue;
385 if (getce(bgp, vbi->attr, &ce))
386 continue;
387 if (prefix_same(&ce, &ce_nexthop)) {
388 vnc_zlog_debug_verbose(
389 "%s: still have a route via CE, not deleting unicast",
390 __func__);
391 return;
392 }
393 }
65efcfce 394
d62a17ae 395 /*
396 * withdraw the route
397 */
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 */
317f1fe0 402 NULL, 0, NULL); /* tag not used for unicast */
65efcfce
LB
403}
404
d62a17ae 405static void vnc_direct_bgp_vpn_enable_ce(struct bgp *bgp, afi_t afi)
65efcfce 406{
d62a17ae 407 struct route_node *rn;
408 struct bgp_info *ri;
65efcfce 409
d62a17ae 410 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
65efcfce 411
d62a17ae 412 if (!bgp)
413 return;
65efcfce 414
3f54c705 415 if (!(bgp->rfapi_cfg))
d62a17ae 416 return;
65efcfce 417
d62a17ae 418 if (!VNC_EXPORT_BGP_CE_ENABLED(bgp->rfapi_cfg)) {
419 vnc_zlog_debug_verbose(
420 "%s: export of CE routes not enabled, skipping",
421 __func__);
422 return;
423 }
65efcfce 424
d62a17ae 425 if (afi != AFI_IP && afi != AFI_IP6) {
426 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
427 return;
428 }
65efcfce 429
d62a17ae 430 /*
431 * Go through entire ce import table and export to BGP unicast.
432 */
433 for (rn = route_top(bgp->rfapi->it_ce->imported_vpn[afi]); rn;
434 rn = route_next(rn)) {
65efcfce 435
d62a17ae 436 if (!rn->info)
437 continue;
65efcfce 438
d62a17ae 439 {
872ed4c7
DS
440 char prefixstr[PREFIX_STRLEN];
441
442 prefix2str(&rn->p, prefixstr, sizeof(prefixstr));
443 vnc_zlog_debug_verbose("%s: checking prefix %s",
444 __func__, prefixstr);
d62a17ae 445 }
65efcfce 446
d62a17ae 447 for (ri = rn->info; ri; ri = ri->next) {
65efcfce 448
d62a17ae 449 vnc_zlog_debug_verbose("%s: ri->sub_type: %d", __func__,
450 ri->sub_type);
65efcfce 451
d62a17ae 452 if (ri->sub_type == BGP_ROUTE_NORMAL
453 || ri->sub_type == BGP_ROUTE_RFP
454 || ri->sub_type == BGP_ROUTE_STATIC) {
65efcfce 455
d62a17ae 456 vnc_direct_bgp_add_route_ce(bgp, rn, ri);
457 }
458 }
459 }
65efcfce
LB
460}
461
d62a17ae 462static void vnc_direct_bgp_vpn_disable_ce(struct bgp *bgp, afi_t afi)
65efcfce 463{
d62a17ae 464 struct bgp_node *rn;
465
466 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
467
468 if (!bgp)
469 return;
470
471 if (afi != AFI_IP && afi != AFI_IP6) {
472 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
473 return;
474 }
475
476 /*
477 * Go through the entire BGP unicast table and remove routes that
478 * originated from us
479 */
480 for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn;
481 rn = bgp_route_next(rn)) {
482
483 struct bgp_info *ri;
484 struct bgp_info *next;
485
486 for (ri = rn->info, next = NULL; ri; ri = next) {
487
488 next = ri->next;
489
490 if (ri->type == ZEBRA_ROUTE_VNC_DIRECT
491 && ri->sub_type == BGP_ROUTE_REDISTRIBUTE) {
492
493 bgp_withdraw(
494 ri->peer, &rn->p, /* prefix */
495 0, /* addpath_id */
496 NULL, /* ignored */
497 AFI_IP, SAFI_UNICAST,
498 ZEBRA_ROUTE_VNC_DIRECT,
499 BGP_ROUTE_REDISTRIBUTE,
500 NULL, /* RD not used for unicast */
317f1fe0 501 NULL, 0,
d62a17ae 502 NULL); /* tag not used for unicast */
503 }
504 }
505 }
65efcfce
LB
506}
507
508/***********************************************************************
509 * Export methods that set nexthop to CE (from 5226 roo EC) END
510 ***********************************************************************/
511
512/***********************************************************************
513 * Export methods that proxy nexthop BEGIN
514 ***********************************************************************/
515
d62a17ae 516static struct ecommunity *vnc_route_origin_ecom(struct route_node *rn)
65efcfce 517{
d62a17ae 518 struct ecommunity *new;
519 struct bgp_info *bi;
520
521 if (!rn->info)
522 return NULL;
523
524 new = ecommunity_new();
525
526 for (bi = rn->info; bi; bi = bi->next) {
527
528 struct ecommunity_val roec;
529
530 switch (BGP_MP_NEXTHOP_FAMILY(bi->attr->mp_nexthop_len)) {
531 case AF_INET:
532 memset(&roec, 0, sizeof(roec));
533 roec.val[0] = 0x01;
534 roec.val[1] = 0x03;
535 memcpy(roec.val + 2,
536 &bi->attr->mp_nexthop_global_in.s_addr, 4);
537 roec.val[6] = 0;
538 roec.val[7] = 0;
539 ecommunity_add_val(new, &roec);
540 break;
541 case AF_INET6:
542 /* No support for IPv6 addresses in extended communities
543 */
544 break;
545 }
546 }
547
548 if (!new->size) {
549 ecommunity_free(&new);
550 new = NULL;
551 }
552
553 return new;
65efcfce
LB
554}
555
d62a17ae 556static struct ecommunity *vnc_route_origin_ecom_single(struct in_addr *origin)
65efcfce 557{
d62a17ae 558 struct ecommunity *new;
559 struct ecommunity_val roec;
560
561 memset(&roec, 0, sizeof(roec));
562 roec.val[0] = 0x01;
563 roec.val[1] = 0x03;
564 memcpy(roec.val + 2, &origin->s_addr, 4);
565 roec.val[6] = 0;
566 roec.val[7] = 0;
567
568 new = ecommunity_new();
569 assert(new);
570 ecommunity_add_val(new, &roec);
571
572 if (!new->size) {
573 ecommunity_free(&new);
574 new = NULL;
575 }
576
577 return new;
65efcfce
LB
578}
579
580
581/*
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.
585 */
586static int
d62a17ae 587encap_attr_export(struct attr *new, struct attr *orig,
588 struct prefix *new_nexthop,
589 struct route_node *rn) /* for VN addrs for ecom list */
590 /* if rn is 0, use route's nexthop */
65efcfce 591{
d62a17ae 592 struct prefix orig_nexthop;
593 struct prefix *use_nexthop;
594 static struct ecommunity *ecom_ro;
595
596 if (new_nexthop) {
597 use_nexthop = new_nexthop;
598 } else {
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;
608 } else {
609 return -1; /* FAIL - can't compute nexthop */
610 }
611 }
612
613
614 /*
615 * Make "new" a ghost attr copy of "orig"
616 */
617 memset(new, 0, sizeof(struct attr));
618 bgp_attr_dup(new, orig);
619
620 /*
621 * Set nexthop
622 */
623 switch (use_nexthop->family) {
624 case AF_INET:
625 new->nexthop = use_nexthop->u.prefix4;
626 new->mp_nexthop_len = 4; /* bytes */
627 new->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
628 break;
629
630 case AF_INET6:
631 new->mp_nexthop_global = use_nexthop->u.prefix6;
632 new->mp_nexthop_len = 16; /* bytes */
633 break;
634
635 default:
636 assert(0);
637 break;
638 }
639
640 if (rn) {
641 ecom_ro = vnc_route_origin_ecom(rn);
642 } else {
7f88f54a 643 /* TBD use lcom for IPv6 */
d62a17ae 644 ecom_ro = vnc_route_origin_ecom_single(&use_nexthop->u.prefix4);
645 }
646 if (new->ecommunity) {
647 if (ecom_ro)
648 new->ecommunity =
649 ecommunity_merge(ecom_ro, new->ecommunity);
650 } else {
651 new->ecommunity = ecom_ro;
652 }
653 if (ecom_ro) {
654 new->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
655 }
656
657 /*
658 * Set MED
659 *
660 * Note that it will be deleted when BGP sends to any eBGP
661 * peer unless PEER_FLAG_MED_UNCHANGED is set:
662 *
663 * neighbor NEIGHBOR attribute-unchanged med
664 */
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)
668 new->med = 0;
669 else
670 new->med = 255 - new->local_pref;
671 } else {
672 new->med = 255; /* shouldn't happen */
673 }
674 new->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
675 }
676
677 /*
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
682 *
683 * Caller should, after using the attr, call:
684 * - bgp_attr_flush() to free non-interned parts
685 */
686
687 return 0;
65efcfce
LB
688}
689
690/*
691 * "Adding a Route" export process
692 */
d62a17ae 693void vnc_direct_bgp_add_prefix(struct bgp *bgp,
694 struct rfapi_import_table *import_table,
695 struct route_node *rn)
65efcfce 696{
d62a17ae 697 struct attr attr = {0};
698 struct listnode *node, *nnode;
699 struct rfapi_rfg_name *rfgn;
700 afi_t afi = family2afi(rn->p.family);
701
702 if (!afi) {
af4c2728 703 flog_err(LIB_ERR_DEVELOPMENT,
02705213 704 "%s: can't get afi of route node", __func__);
d62a17ae 705 return;
706 }
707
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",
712 __func__);
713 return;
714 }
715
716 if (!bgp->rfapi_cfg) {
717 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
718 __func__);
719 return;
720 }
721
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",
725 __func__);
726 return;
727 }
728
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",
732 __func__);
733 return;
734 }
735
736 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
737 /* TBD set some configured med, see add_vnc_route() */
738
739 vnc_zlog_debug_verbose(
740 "%s: looping over nve-groups in direct-bgp export list",
741 __func__);
742
743 for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node,
744 nnode, rfgn)) {
745
746 struct listnode *ln;
747
748 /*
749 * If nve group is not defined yet, skip it
750 */
751 if (!rfgn->rfg)
752 continue;
753
754 /*
755 * If the nve group uses a different import table, skip it
756 */
757 if (import_table != rfgn->rfg->rfapi_import_table)
758 continue;
759
760 /*
761 * if no NVEs currently associated with this group, skip it
762 */
d477c01d 763 if (rfgn->rfg->type != RFAPI_GROUP_CFG_VRF && !rfgn->rfg->nves)
d62a17ae 764 continue;
765
766 /*
767 * per-nve-group prefix list check
768 */
769 if (rfgn->rfg->plist_export_bgp[afi]) {
770 if (prefix_list_apply(rfgn->rfg->plist_export_bgp[afi],
771 &rn->p)
772 == PREFIX_DENY)
773
774 continue;
775 }
776
d477c01d
LB
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);
e1541bf6
LB
780 /*
781 * yuck!
782 * - but consistent with rest of function
783 */
784 continue;
d477c01d 785 }
d62a17ae 786 /*
787 * For each NVE that is assigned to the export nve group,
788 * generate
789 * a route with that NVE as its next hop
790 */
791 for (ln = listhead(rfgn->rfg->nves); ln;
792 ln = listnextnode(ln)) {
d477c01d
LB
793 vnc_direct_add_rn_group_rd(bgp, rfgn->rfg, rn, &attr,
794 afi, listgetdata(ln));
d62a17ae 795 }
796 }
797
798 aspath_unintern(&attr.aspath);
65efcfce
LB
799}
800
801/*
802 * "Withdrawing a Route" export process
803 */
d62a17ae 804void vnc_direct_bgp_del_prefix(struct bgp *bgp,
805 struct rfapi_import_table *import_table,
806 struct route_node *rn)
65efcfce 807{
d62a17ae 808 struct listnode *node, *nnode;
809 struct rfapi_rfg_name *rfgn;
810 afi_t afi = family2afi(rn->p.family);
811
812 if (!afi) {
af4c2728 813 flog_err(LIB_ERR_DEVELOPMENT, "%s: can't get afi route node",
02705213 814 __func__);
d62a17ae 815 return;
816 }
817
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",
822 __func__);
823 return;
824 }
825
826 if (!bgp->rfapi_cfg) {
827 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
828 __func__);
829 return;
830 }
831
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",
835 __func__);
836 return;
837 }
838
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",
842 __func__);
843 return;
844 }
845
846 for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node,
847 nnode, rfgn)) {
848
849 struct listnode *ln;
850
851 /*
852 * If nve group is not defined yet, skip it
853 */
854 if (!rfgn->rfg)
855 continue;
856
857 /*
858 * if no NVEs currently associated with this group, skip it
859 */
d477c01d 860 if (rfgn->rfg->type != RFAPI_GROUP_CFG_VRF && !rfgn->rfg->nves)
d62a17ae 861 continue;
862
863 /*
864 * If the nve group uses a different import table,
865 * skip it
866 */
867 if (import_table != rfgn->rfg->rfapi_import_table)
868 continue;
869
d477c01d
LB
870 if (rfgn->rfg->type == RFAPI_GROUP_CFG_VRF) {
871 struct prefix nhp;
872 struct rfapi_descriptor *irfd;
873
874 irfd = rfgn->rfg->rfd;
875
876 if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
877 continue;
878
879 bgp_withdraw(irfd->peer, &rn->p, /* prefix */
880 0, /* addpath_id */
881 NULL, /* attr, ignored */
882 afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
883 BGP_ROUTE_REDISTRIBUTE,
996c9314
LB
884 NULL, /* RD not used for unicast */
885 NULL, 0,
886 NULL); /* tag not used for unicast */
e1541bf6
LB
887 /*
888 * yuck!
889 * - but consistent with rest of function
890 */
891 continue;
d477c01d 892 }
d62a17ae 893 /*
894 * For each NVE that is assigned to the export nve group,
895 * generate
896 * a route with that NVE as its next hop
897 */
898 for (ln = listhead(rfgn->rfg->nves); ln;
899 ln = listnextnode(ln)) {
900
901 struct prefix nhp;
902 struct rfapi_descriptor *irfd;
903
904 irfd = listgetdata(ln);
905
906 if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
907 continue;
908
909 bgp_withdraw(irfd->peer, &rn->p, /* prefix */
910 0, /* addpath_id */
911 NULL, /* attr, ignored */
912 afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
913 BGP_ROUTE_REDISTRIBUTE,
996c9314
LB
914 NULL, /* RD not used for unicast */
915 NULL, 0,
916 NULL); /* tag not used for unicast */
d62a17ae 917 }
918 }
65efcfce
LB
919}
920
d62a17ae 921void vnc_direct_bgp_add_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
65efcfce 922{
d62a17ae 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);
927
928 if (!afi) {
af4c2728 929 flog_err(LIB_ERR_DEVELOPMENT,
02705213 930 "%s: can't get afi of nve vn addr", __func__);
d62a17ae 931 return;
932 }
933
934 if (!bgp)
935 return;
936 if (!bgp->rfapi_cfg) {
937 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
938 __func__);
939 return;
940 }
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",
944 __func__);
945 return;
946 }
947
948 if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
949 vnc_zlog_debug_verbose(
950 "%s: bgp redistribution of VNC direct routes is off",
951 __func__);
952 return;
953 }
954
955 /*
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.
959 */
960 for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node,
961 nnode, rfgn)) {
962
963 /*
964 * Yes, this NVE's group is configured for export to direct-bgp
965 */
966 if (rfgn->rfg == rfg) {
967
968 struct route_table *rt = NULL;
969 struct route_node *rn;
970 struct attr attr = {0};
971 struct rfapi_import_table *import_table;
972
973
974 import_table = rfg->rfapi_import_table;
975
976 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
977 /* TBD set some configured med, see add_vnc_route() */
978
979 if (afi == AFI_IP || afi == AFI_IP6) {
980 rt = import_table->imported_vpn[afi];
981 } else {
af4c2728 982 flog_err(LIB_ERR_DEVELOPMENT, "%s: bad afi %d",
02705213 983 __func__, afi);
d62a17ae 984 return;
985 }
986
987 /*
988 * Walk the NVE-Group's VNC Import table
989 */
990 for (rn = route_top(rt); rn; rn = route_next(rn)) {
991
992 if (rn->info) {
993
994 struct prefix nhp;
995 struct rfapi_descriptor *irfd = rfd;
996 struct attr hattr;
997 struct attr *iattr;
998 struct bgp_info info;
999
1000 if (rfapiRaddr2Qprefix(&irfd->vn_addr,
1001 &nhp))
1002 continue;
1003
1004 /*
1005 * per-nve-group prefix list check
1006 */
1007 if (rfgn->rfg->plist_export_bgp[afi]) {
1008 if (prefix_list_apply(
1009 rfgn->rfg->plist_export_bgp
1010 [afi],
1011 &rn->p)
1012 == PREFIX_DENY)
1013
1014 continue;
1015 }
1016
1017
1018 /*
1019 * Construct new attribute set with
1020 * NVE's VN addr as
1021 * nexthop and without Tunnel Encap attr
1022 */
1023 if (encap_attr_export(&hattr, &attr,
1024 &nhp, rn))
1025 continue;
1026
1027 if (rfgn->rfg->routemap_export_bgp) {
1028 route_map_result_t ret;
1029 info.peer = irfd->peer;
1030 info.attr = &hattr;
1031 ret = route_map_apply(
1032 rfgn->rfg
1033 ->routemap_export_bgp,
1034 &rn->p, RMAP_BGP,
1035 &info);
1036 if (ret == RMAP_DENYMATCH) {
1037 bgp_attr_flush(&hattr);
1038 continue;
1039 }
1040 }
1041
1042 iattr = bgp_attr_intern(&hattr);
1043 bgp_attr_flush(&hattr);
3380418f
LB
1044 bgp_update(
1045 irfd->peer, &rn->p, /* prefix */
1046 0, /* addpath_id */
1047 iattr, /* bgp_update copies
1048 it */
1049 afi, SAFI_UNICAST,
1050 ZEBRA_ROUTE_VNC_DIRECT,
1051 BGP_ROUTE_REDISTRIBUTE, NULL,
1052 /* RD not used for unicast */
1053 NULL,
1054 /* tag not used for unicast */
1055 0, 0, NULL); /* EVPN not used */
d62a17ae 1056
1057 bgp_attr_unintern(&iattr);
1058 }
1059 }
1060
1061 aspath_unintern(&attr.aspath);
1062 }
1063 }
65efcfce
LB
1064}
1065
1066
d62a17ae 1067void vnc_direct_bgp_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
65efcfce 1068{
d62a17ae 1069 struct listnode *node, *nnode;
1070 struct rfapi_rfg_name *rfgn;
1071 struct rfapi_nve_group_cfg *rfg = rfd->rfg;
1072 afi_t afi = family2afi(rfd->vn_addr.addr_family);
1073
1074 if (!afi) {
af4c2728 1075 flog_err(LIB_ERR_DEVELOPMENT,
02705213 1076 "%s: can't get afi of nve vn addr", __func__);
d62a17ae 1077 return;
1078 }
1079
1080 if (!bgp)
1081 return;
1082 if (!bgp->rfapi_cfg) {
1083 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1084 __func__);
1085 return;
1086 }
1087 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) {
1088 vnc_zlog_debug_verbose(
1089 "%s: export-to-bgp group mode not enabled, skipping",
1090 __func__);
1091 return;
1092 }
1093
1094 if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
1095 vnc_zlog_debug_verbose(
1096 "%s: bgp redistribution of VNC direct routes is off",
1097 __func__);
1098 return;
1099 }
65efcfce 1100
d62a17ae 1101 /*
1102 * Loop over the list of NVE-Groups configured for
1103 * exporting to direct-bgp and see if this new NVE's
1104 * group is among them.
1105 */
1106 for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node,
1107 nnode, rfgn)) {
1108
1109 /*
1110 * Yes, this NVE's group is configured for export to direct-bgp
1111 */
1112 if (rfg && rfgn->rfg == rfg) {
1113
1114 struct route_table *rt = NULL;
1115 struct route_node *rn;
1116 struct rfapi_import_table *import_table;
1117
1118 import_table = rfg->rfapi_import_table;
1119
1120 if (afi == AFI_IP || afi == AFI_IP6) {
1121 rt = import_table->imported_vpn[afi];
1122 } else {
af4c2728 1123 flog_err(LIB_ERR_DEVELOPMENT, "%s: bad afi %d",
02705213 1124 __func__, afi);
d62a17ae 1125 return;
1126 }
1127
1128 /*
1129 * Walk the NVE-Group's VNC Import table
1130 */
1131 for (rn = route_top(rt); rn; rn = route_next(rn)) {
1132
1133 if (rn->info) {
1134
1135 struct prefix nhp;
1136 struct rfapi_descriptor *irfd = rfd;
1137
1138 if (rfapiRaddr2Qprefix(&irfd->vn_addr,
1139 &nhp))
1140 continue;
1141
1142 bgp_withdraw(irfd->peer,
1143 &rn->p, /* prefix */
1144 0, /* addpath_id */
1145 NULL, /* attr, ignored */
1146 afi, SAFI_UNICAST,
1147 ZEBRA_ROUTE_VNC_DIRECT,
1148 BGP_ROUTE_REDISTRIBUTE,
1149 NULL, /* RD not used for
1150 unicast */
317f1fe0 1151 NULL, 0, NULL); /* tag not
d62a17ae 1152 used for
1153 unicast */
1154 }
1155 }
1156 }
1157 }
1158}
65efcfce 1159
d477c01d
LB
1160static void vnc_direct_add_rn_group_rd(struct bgp *bgp,
1161 struct rfapi_nve_group_cfg *rfg,
996c9314
LB
1162 struct route_node *rn, struct attr *attr,
1163 afi_t afi, struct rfapi_descriptor *irfd)
d477c01d
LB
1164{
1165 struct prefix nhp;
1166 struct bgp_info info;
1167 struct attr hattr;
1168 struct attr *iattr;
1169
1170 if (irfd == NULL && rfg->type != RFAPI_GROUP_CFG_VRF) {
1171 /* need new rfapi_handle, for peer strcture
1172 * -- based on vnc_add_vrf_prefi */
e1541bf6 1173 assert(rfg->rfd == NULL);
d477c01d
LB
1174
1175 if (!rfg->rt_export_list || !rfg->rfapi_import_table) {
996c9314
LB
1176 vnc_zlog_debug_verbose(
1177 "%s: VRF \"%s\" is missing RT import/export configuration.\n",
1178 __func__, rfg->name);
d477c01d
LB
1179 return;
1180 }
1181 if (!rfg->rd.prefixlen) {
996c9314
LB
1182 vnc_zlog_debug_verbose(
1183 "%s: VRF \"%s\" is missing RD configuration.\n",
1184 __func__, rfg->name);
d477c01d
LB
1185 return;
1186 }
1187 if (rfg->label > MPLS_LABEL_MAX) {
996c9314
LB
1188 vnc_zlog_debug_verbose(
1189 "%s: VRF \"%s\" is missing defaul label configuration.\n",
1190 __func__, rfg->name);
d477c01d
LB
1191 return;
1192 }
1193
1194 irfd = XCALLOC(MTYPE_RFAPI_DESC,
996c9314 1195 sizeof(struct rfapi_descriptor));
d477c01d
LB
1196 irfd->bgp = bgp;
1197 rfg->rfd = irfd;
e1541bf6
LB
1198 /*
1199 * leave most fields empty as will get from (dynamic) config
1200 * when needed
1201 */
d477c01d
LB
1202 irfd->default_tunneltype_option.type = BGP_ENCAP_TYPE_MPLS;
1203 irfd->cookie = rfg;
1204 if (rfg->vn_prefix.family
1205 && !CHECK_FLAG(rfg->flags, RFAPI_RFG_VPN_NH_SELF)) {
1206 rfapiQprefix2Raddr(&rfg->vn_prefix, &irfd->vn_addr);
1207 } else {
1208 memset(&irfd->vn_addr, 0, sizeof(struct rfapi_ip_addr));
1209 irfd->vn_addr.addr_family = AF_INET;
1210 irfd->vn_addr.addr.v4 = bgp->router_id;
1211 }
1212 irfd->un_addr = irfd->vn_addr; /* sigh, need something in UN for
1213 lookups */
1214 vnc_zlog_debug_verbose("%s: Opening RFD for VRF %s", __func__,
1215 rfg->name);
1216 rfapi_init_and_open(bgp, irfd, rfg);
1217 }
1218
1219 if (irfd == NULL || rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
1220 return;
1221
1222 /*
1223 * Construct new attribute set with NVE's VN
1224 * addr as
1225 * nexthop and without Tunnel Encap attr
1226 */
1227 if (encap_attr_export(&hattr, attr, &nhp, rn))
1228 return;
1229
1230 if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD)) {
996c9314 1231 vnc_zlog_debug_any("%s: attr follows", __func__);
d477c01d 1232 rfapiPrintAttrPtrs(NULL, attr);
996c9314 1233 vnc_zlog_debug_any("%s: hattr follows", __func__);
d477c01d
LB
1234 rfapiPrintAttrPtrs(NULL, &hattr);
1235 }
1236
1237 if (rfg->routemap_export_bgp) {
1238 route_map_result_t ret;
e1541bf6 1239
d477c01d
LB
1240 info.peer = irfd->peer;
1241 info.attr = &hattr;
996c9314
LB
1242 ret = route_map_apply(rfg->routemap_export_bgp, &rn->p,
1243 RMAP_BGP, &info);
d477c01d
LB
1244 if (ret == RMAP_DENYMATCH) {
1245 bgp_attr_flush(&hattr);
996c9314
LB
1246 vnc_zlog_debug_verbose(
1247 "%s: route map says DENY, so not calling bgp_update",
1248 __func__);
d477c01d
LB
1249 return;
1250 }
1251 }
1252
1253 if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD)) {
e1541bf6 1254 vnc_zlog_debug_any("%s: hattr after route_map_apply:",
d477c01d
LB
1255 __func__);
1256 rfapiPrintAttrPtrs(NULL, &hattr);
1257 }
1258 iattr = bgp_attr_intern(&hattr);
1259 bgp_attr_flush(&hattr);
1260
1261 bgp_update(irfd->peer, &rn->p, /* prefix */
1262 0, /* addpath_id */
996c9314
LB
1263 iattr, /* bgp_update copies it */
1264 afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
1265 BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
1266 NULL, /* tag not used for unicast */
1267 0, 0, NULL); /* EVPN not used */
d477c01d
LB
1268
1269 bgp_attr_unintern(&iattr);
1270
1271 return;
1272}
65efcfce
LB
1273
1274/*
1275 * Caller is responsible for ensuring that the specified nve-group
1276 * is actually part of the list of exported nve groups.
1277 */
d62a17ae 1278static void vnc_direct_bgp_add_group_afi(struct bgp *bgp,
1279 struct rfapi_nve_group_cfg *rfg,
1280 afi_t afi)
65efcfce 1281{
d62a17ae 1282 struct route_table *rt = NULL;
1283 struct route_node *rn;
1284 struct attr attr = {0};
1285 struct rfapi_import_table *import_table;
1286
1287 vnc_zlog_debug_verbose("%s: entry", __func__);
1288
1289 import_table = rfg->rfapi_import_table;
1290 if (!import_table) {
1291 vnc_zlog_debug_verbose(
1292 "%s: import table not defined, returning", __func__);
1293 return;
1294 }
1295
1296 if (afi == AFI_IP || afi == AFI_IP6) {
1297 rt = import_table->imported_vpn[afi];
1298 } else {
af4c2728 1299 flog_err(LIB_ERR_DEVELOPMENT, "%s: bad afi %d", __func__, afi);
d62a17ae 1300 return;
1301 }
1302
d477c01d 1303 if (!rfg->nves && rfg->type != RFAPI_GROUP_CFG_VRF) {
d62a17ae 1304 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__);
1305 return;
1306 }
1307
1308 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
1309 /* TBD set some configured med, see add_vnc_route() */
1310
1311 /*
1312 * Walk the NVE-Group's VNC Import table
1313 */
1314 for (rn = route_top(rt); rn; rn = route_next(rn)) {
1315
1316 if (rn->info) {
1317
1318 struct listnode *ln;
1319
1320 /*
1321 * per-nve-group prefix list check
1322 */
1323 if (rfg->plist_export_bgp[afi]) {
1324 if (prefix_list_apply(
1325 rfg->plist_export_bgp[afi], &rn->p)
1326 == PREFIX_DENY)
1327
1328 continue;
1329 }
d477c01d
LB
1330 if (rfg->type == RFAPI_GROUP_CFG_VRF) {
1331 vnc_direct_add_rn_group_rd(bgp, rfg, rn, &attr,
1332 afi, rfg->rfd);
e1541bf6
LB
1333 /*
1334 * yuck!
1335 * - but consistent with rest of function
1336 */
1337 continue;
d477c01d 1338 }
d62a17ae 1339 /*
1340 * For each NVE that is assigned to the export nve
1341 * group, generate
1342 * a route with that NVE as its next hop
1343 */
1344 for (ln = listhead(rfg->nves); ln;
1345 ln = listnextnode(ln)) {
d477c01d 1346 vnc_direct_add_rn_group_rd(bgp, rfg, rn, &attr,
996c9314
LB
1347 afi,
1348 listgetdata(ln));
d62a17ae 1349 }
1350 }
1351 }
1352
1353 aspath_unintern(&attr.aspath);
65efcfce
LB
1354}
1355
1356
1357/*
1358 * Caller is responsible for ensuring that the specified nve-group
1359 * is actually part of the list of exported nve groups.
1360 */
d62a17ae 1361void vnc_direct_bgp_add_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
65efcfce 1362{
d62a17ae 1363 vnc_direct_bgp_add_group_afi(bgp, rfg, AFI_IP);
1364 vnc_direct_bgp_add_group_afi(bgp, rfg, AFI_IP6);
65efcfce
LB
1365}
1366
d477c01d
LB
1367static void vnc_direct_del_rn_group_rd(struct bgp *bgp,
1368 struct rfapi_nve_group_cfg *rfg,
996c9314 1369 struct route_node *rn, afi_t afi,
d477c01d
LB
1370 struct rfapi_descriptor *irfd)
1371{
1372 if (irfd == NULL)
1373 return;
1374 bgp_withdraw(irfd->peer, &rn->p, /* prefix */
996c9314
LB
1375 0, /* addpath_id */
1376 NULL, /* attr, ignored */
1377 afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
1378 BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
1379 NULL, 0, NULL); /* tag not used for unicast */
d477c01d
LB
1380 return;
1381}
65efcfce 1382
65efcfce
LB
1383/*
1384 * Caller is responsible for ensuring that the specified nve-group
1385 * was actually part of the list of exported nve groups.
1386 */
d62a17ae 1387static void vnc_direct_bgp_del_group_afi(struct bgp *bgp,
1388 struct rfapi_nve_group_cfg *rfg,
1389 afi_t afi)
65efcfce 1390{
d62a17ae 1391 struct route_table *rt = NULL;
1392 struct route_node *rn;
1393 struct rfapi_import_table *import_table;
1394
1395 vnc_zlog_debug_verbose("%s: entry", __func__);
1396
1397 import_table = rfg->rfapi_import_table;
1398 if (!import_table) {
1399 vnc_zlog_debug_verbose(
1400 "%s: import table not defined, returning", __func__);
1401 return;
1402 }
1403
1404 assert(afi == AFI_IP || afi == AFI_IP6);
1405 rt = import_table->imported_vpn[afi];
1406
d477c01d 1407 if (!rfg->nves && rfg->type != RFAPI_GROUP_CFG_VRF) {
d62a17ae 1408 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__);
1409 return;
1410 }
1411
1412 /*
1413 * Walk the NVE-Group's VNC Import table
1414 */
d477c01d 1415 for (rn = route_top(rt); rn; rn = route_next(rn))
d62a17ae 1416 if (rn->info) {
d477c01d 1417 if (rfg->type == RFAPI_GROUP_CFG_VRF)
996c9314
LB
1418 vnc_direct_del_rn_group_rd(bgp, rfg, rn, afi,
1419 rfg->rfd);
d477c01d
LB
1420 else {
1421 struct listnode *ln;
d62a17ae 1422
d477c01d 1423 /*
996c9314
LB
1424 * For each NVE that is assigned to the export
1425 * nve
d477c01d
LB
1426 * group, generate
1427 * a route with that NVE as its next hop
1428 */
1429 for (ln = listhead(rfg->nves); ln;
1430 ln = listnextnode(ln))
996c9314
LB
1431 vnc_direct_del_rn_group_rd(
1432 bgp, rfg, rn, afi,
1433 listgetdata(ln));
d62a17ae 1434 }
1435 }
65efcfce
LB
1436}
1437
65efcfce
LB
1438/*
1439 * Caller is responsible for ensuring that the specified nve-group
1440 * was actually part of the list of exported nve groups.
1441 */
d62a17ae 1442void vnc_direct_bgp_del_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
65efcfce 1443{
d62a17ae 1444 vnc_direct_bgp_del_group_afi(bgp, rfg, AFI_IP);
1445 vnc_direct_bgp_del_group_afi(bgp, rfg, AFI_IP6);
65efcfce
LB
1446}
1447
d62a17ae 1448void vnc_direct_bgp_reexport_group_afi(struct bgp *bgp,
1449 struct rfapi_nve_group_cfg *rfg,
1450 afi_t afi)
65efcfce 1451{
d62a17ae 1452 struct listnode *node;
1453 struct rfapi_rfg_name *rfgn;
1454
1455 if (VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) {
1456 /*
1457 * look in the list of currently-exported groups
1458 */
1459 for (ALL_LIST_ELEMENTS_RO(
1460 bgp->rfapi_cfg->rfg_export_direct_bgp_l, node,
1461 rfgn)) {
1462
1463 if (rfgn->rfg == rfg) {
1464 /*
1465 * If it matches, reexport it
1466 */
1467 vnc_direct_bgp_del_group_afi(bgp, rfg, afi);
1468 vnc_direct_bgp_add_group_afi(bgp, rfg, afi);
1469 break;
1470 }
1471 }
1472 }
65efcfce
LB
1473}
1474
1475
d62a17ae 1476static void vnc_direct_bgp_unexport_table(afi_t afi, struct route_table *rt,
1477 struct list *nve_list)
65efcfce 1478{
d62a17ae 1479 if (nve_list) {
1480
1481 struct route_node *rn;
1482
1483 for (rn = route_top(rt); rn; rn = route_next(rn)) {
1484
1485 if (rn->info) {
1486
1487 struct listnode *hln;
1488 struct rfapi_descriptor *irfd;
1489
1490 for (ALL_LIST_ELEMENTS_RO(nve_list, hln,
1491 irfd)) {
1492
1493 bgp_withdraw(irfd->peer,
1494 &rn->p, /* prefix */
1495 0, /* addpath_id */
1496 NULL, /* attr, ignored */
1497 afi, SAFI_UNICAST,
1498 ZEBRA_ROUTE_VNC_DIRECT,
1499 BGP_ROUTE_REDISTRIBUTE,
1500 NULL, /* RD not used for
1501 unicast */
317f1fe0 1502 NULL, 0, NULL); /* tag not
d62a17ae 1503 used for
1504 unicast,
1505 EVPN
1506 neither */
1507 }
1508 }
1509 }
1510 }
65efcfce
LB
1511}
1512
d62a17ae 1513static void import_table_to_nve_list_direct_bgp(struct bgp *bgp,
1514 struct rfapi_import_table *it,
1515 struct list **nves,
1516 uint8_t family)
65efcfce 1517{
d62a17ae 1518 struct listnode *node;
1519 struct rfapi_rfg_name *rfgn;
1520
1521 /*
1522 * Loop over the list of NVE-Groups configured for
1523 * exporting to direct-bgp.
1524 *
1525 * Build a list of NVEs that use this import table
1526 */
1527 *nves = NULL;
1528 for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node,
1529 rfgn)) {
1530
1531 /*
1532 * If this NVE-Group's import table matches the current one
1533 */
d477c01d
LB
1534 if (rfgn->rfg && rfgn->rfg->rfapi_import_table == it) {
1535 if (rfgn->rfg->nves)
1536 nve_group_to_nve_list(rfgn->rfg, nves, family);
996c9314
LB
1537 else if (rfgn->rfg->rfd
1538 && rfgn->rfg->type == RFAPI_GROUP_CFG_VRF) {
d477c01d
LB
1539 if (!*nves)
1540 *nves = list_new();
1541 listnode_add(*nves, rfgn->rfg->rfd);
1542 }
d62a17ae 1543 }
1544 }
65efcfce
LB
1545}
1546
d62a17ae 1547void vnc_direct_bgp_vpn_enable(struct bgp *bgp, afi_t afi)
65efcfce 1548{
d62a17ae 1549 struct listnode *rfgn;
1550 struct rfapi_nve_group_cfg *rfg;
1551
1552 if (!bgp)
1553 return;
1554
1555 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) {
1556 vnc_zlog_debug_verbose(
1557 "%s: export-to-bgp group mode not enabled, skipping",
1558 __func__);
1559 return;
1560 }
1561
1562 if (afi != AFI_IP && afi != AFI_IP6) {
1563 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
1564 return;
1565 }
1566
1567 /*
1568 * Policy is applied per-nve-group, so we need to iterate
1569 * over the groups to add everything.
1570 */
1571 for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->nve_groups_sequential, rfgn,
1572 rfg)) {
1573
1574 /*
1575 * contains policy management
1576 */
1577 vnc_direct_bgp_add_group_afi(bgp, rfg, afi);
1578 }
65efcfce
LB
1579}
1580
1581
d62a17ae 1582void vnc_direct_bgp_vpn_disable(struct bgp *bgp, afi_t afi)
65efcfce 1583{
d62a17ae 1584 struct rfapi_import_table *it;
1585 uint8_t family = afi2family(afi);
65efcfce 1586
d62a17ae 1587 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
65efcfce 1588
d62a17ae 1589 if (!bgp)
1590 return;
65efcfce 1591
d62a17ae 1592 if (!bgp->rfapi) {
1593 vnc_zlog_debug_verbose("%s: rfapi not initialized", __func__);
1594 return;
1595 }
65efcfce 1596
d62a17ae 1597 if (!family || (afi != AFI_IP && afi != AFI_IP6)) {
1598 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
1599 return;
1600 }
65efcfce 1601
d62a17ae 1602 for (it = bgp->rfapi->imports; it; it = it->next) {
65efcfce 1603
d62a17ae 1604 struct list *nve_list = NULL;
65efcfce 1605
d62a17ae 1606 import_table_to_nve_list_direct_bgp(bgp, it, &nve_list, family);
65efcfce 1607
d62a17ae 1608 if (nve_list) {
1609 vnc_direct_bgp_unexport_table(
1610 afi, it->imported_vpn[afi], nve_list);
acdf5e25 1611 list_delete_and_null(&nve_list);
d62a17ae 1612 }
1613 }
65efcfce
LB
1614}
1615
1616
1617/***********************************************************************
1618 * Export methods that proxy nexthop END
1619 ***********************************************************************/
1620
1621
1622/***********************************************************************
1623 * Export methods that preserve original nexthop BEGIN
1624 * rh = "registering nve"
1625 ***********************************************************************/
1626
1627
1628/*
1629 * "Adding a Route" export process
1630 * TBD do we need to check bi->type and bi->sub_type here, or does
1631 * caller do it?
1632 */
d62a17ae 1633void vnc_direct_bgp_rh_add_route(struct bgp *bgp, afi_t afi,
1634 struct prefix *prefix, struct peer *peer,
1635 struct attr *attr)
65efcfce 1636{
d62a17ae 1637 struct vnc_export_info *eti;
1638 struct attr hattr;
1639 struct rfapi_cfg *hc;
1640 struct attr *iattr;
1641
1642 if (!afi) {
af4c2728 1643 flog_err(LIB_ERR_DEVELOPMENT,
02705213 1644 "%s: can't get afi of route node", __func__);
d62a17ae 1645 return;
1646 }
1647
1648 /* check bgp redist flag for vnc direct ("vpn") routes */
1649 if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
1650 vnc_zlog_debug_verbose(
1651 "%s: bgp redistribution of VNC direct routes is off",
1652 __func__);
1653 return;
1654 }
1655
1656 if (!(hc = bgp->rfapi_cfg)) {
1657 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1658 __func__);
1659 return;
1660 }
1661
1662 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp->rfapi_cfg)) {
1663 vnc_zlog_debug_verbose(
1664 "%s: export-to-bgp RH mode not enabled, skipping",
1665 __func__);
1666 return;
1667 }
1668
1669 /*
1670 * prefix list check
1671 */
1672 if (hc->plist_export_bgp[afi]) {
1673 if (prefix_list_apply(hc->plist_export_bgp[afi], prefix)
1674 == PREFIX_DENY)
1675 return;
1676 }
1677
1678 /*
1679 * Construct new attribute set with NVE's VN addr as
1680 * nexthop and without Tunnel Encap attr
1681 */
1682 if (encap_attr_export(&hattr, attr, NULL, NULL))
1683 return;
1684 if (hc->routemap_export_bgp) {
1685 struct bgp_info info;
1686 route_map_result_t ret;
1687
1688 memset(&info, 0, sizeof(info));
1689 info.peer = peer;
1690 info.attr = &hattr;
1691 ret = route_map_apply(hc->routemap_export_bgp, prefix, RMAP_BGP,
1692 &info);
1693 if (ret == RMAP_DENYMATCH) {
1694 bgp_attr_flush(&hattr);
1695 return;
1696 }
1697 }
1698
1699 iattr = bgp_attr_intern(&hattr);
1700 bgp_attr_flush(&hattr);
1701
1702 /*
1703 * record route information that we will need to expire
1704 * this route
1705 */
1706 eti = vnc_eti_get(bgp, EXPORT_TYPE_BGP, prefix, peer,
1707 ZEBRA_ROUTE_VNC_DIRECT_RH, BGP_ROUTE_REDISTRIBUTE);
1708 rfapiGetVncLifetime(attr, &eti->lifetime);
1709 eti->lifetime = rfapiGetHolddownFromLifetime(eti->lifetime);
1710
1711 if (eti->timer) {
1712 /*
1713 * export expiration timer is already running on
1714 * this route: cancel it
1715 */
1716 thread_cancel(eti->timer);
1717 eti->timer = NULL;
1718 }
65efcfce 1719
d62a17ae 1720 bgp_update(peer, prefix, /* prefix */
1721 0, /* addpath_id */
1722 iattr, /* bgp_update copies this attr */
1723 afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT_RH,
1724 BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
996c9314 1725 NULL, /* tag not used for unicast, EVPN neither */
317f1fe0 1726 0, 0, NULL); /* EVPN not used */
d62a17ae 1727 bgp_attr_unintern(&iattr);
65efcfce
LB
1728}
1729
d62a17ae 1730static int vncExportWithdrawTimer(struct thread *t)
65efcfce 1731{
d62a17ae 1732 struct vnc_export_info *eti = t->arg;
1733
1734 /*
1735 * withdraw the route
1736 */
1737 bgp_withdraw(eti->peer, &eti->node->p, 0, /* addpath_id */
1738 NULL, /* attr, ignored */
1739 family2afi(eti->node->p.family), SAFI_UNICAST, eti->type,
1740 eti->subtype, NULL, /* RD not used for unicast */
996c9314
LB
1741 NULL, 0,
1742 NULL); /* tag not used for unicast, EVPN neither */
d62a17ae 1743
1744 /*
1745 * Free the eti
1746 */
1747 vnc_eti_delete(eti);
1748
1749 return 0;
65efcfce
LB
1750}
1751
1752/*
1753 * "Withdrawing a Route" export process
1754 * TBD do we need to check bi->type and bi->sub_type here, or does
1755 * caller do it?
1756 */
d62a17ae 1757void vnc_direct_bgp_rh_del_route(struct bgp *bgp, afi_t afi,
1758 struct prefix *prefix, struct peer *peer)
65efcfce 1759{
d62a17ae 1760 struct vnc_export_info *eti;
1761
1762 if (!afi) {
af4c2728 1763 flog_err(LIB_ERR_DEVELOPMENT, "%s: can't get afi route node",
02705213 1764 __func__);
d62a17ae 1765 return;
1766 }
1767
1768 /* check bgp redist flag for vnc direct ("vpn") routes */
1769 if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
1770 vnc_zlog_debug_verbose(
1771 "%s: bgp redistribution of VNC direct routes is off",
1772 __func__);
1773 return;
1774 }
1775
1776 if (!bgp->rfapi_cfg) {
1777 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1778 __func__);
1779 return;
1780 }
1781 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp->rfapi_cfg)) {
1782 vnc_zlog_debug_verbose(
1783 "%s: export-to-bgp group mode not enabled, skipping",
1784 __func__);
1785 return;
1786 }
1787
1788 eti = vnc_eti_get(bgp, EXPORT_TYPE_BGP, prefix, peer,
1789 ZEBRA_ROUTE_VNC_DIRECT_RH, BGP_ROUTE_REDISTRIBUTE);
1790
1791 if (!eti->timer && eti->lifetime <= INT32_MAX) {
1792 eti->timer = NULL;
1793 thread_add_timer(bm->master, vncExportWithdrawTimer, eti,
1794 eti->lifetime, &eti->timer);
1795 vnc_zlog_debug_verbose(
1796 "%s: set expiration timer for %u seconds", __func__,
1797 eti->lifetime);
1798 }
65efcfce
LB
1799}
1800
1801
d62a17ae 1802void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi)
65efcfce 1803{
d62a17ae 1804 struct prefix_rd prd;
1805 struct bgp_node *prn;
1806 struct rfapi_cfg *hc;
1807
1808 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
1809
1810 if (!bgp)
1811 return;
1812
1813 if (!(hc = bgp->rfapi_cfg))
1814 return;
1815
1816 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp->rfapi_cfg)) {
1817 vnc_zlog_debug_verbose(
1818 "%s: export of RH routes not enabled, skipping",
1819 __func__);
1820 return;
1821 }
1822
1823 if (afi != AFI_IP && afi != AFI_IP6) {
1824 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
1825 return;
1826 }
1827
1828 /*
1829 * Go through the entire BGP VPN table and export to BGP unicast.
1830 */
1831
1832 vnc_zlog_debug_verbose("%s: starting RD loop", __func__);
1833
1834 /* Loop over all the RDs */
1835 for (prn = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); prn;
1836 prn = bgp_route_next(prn)) {
1837
1838 struct bgp_table *table;
1839 struct bgp_node *rn;
1840 struct bgp_info *ri;
1841
1842 memset(&prd, 0, sizeof(prd));
1843 prd.family = AF_UNSPEC;
1844 prd.prefixlen = 64;
1845 memcpy(prd.val, prn->p.u.val, 8);
1846
1847 /* This is the per-RD table of prefixes */
1848 table = prn->info;
1849
d477c01d
LB
1850 if (!table)
1851 continue;
1852
d62a17ae 1853 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
1854
1855 /*
1856 * skip prefix list check if no routes here
1857 */
1858 if (!rn->info)
1859 continue;
1860
1861 {
872ed4c7 1862 char prefixstr[PREFIX_STRLEN];
d62a17ae 1863
872ed4c7
DS
1864 prefix2str(&rn->p, prefixstr,
1865 sizeof(prefixstr));
996c9314
LB
1866 vnc_zlog_debug_verbose("%s: checking prefix %s",
1867 __func__, prefixstr);
d62a17ae 1868 }
1869
1870 /*
1871 * prefix list check
1872 */
1873 if (hc->plist_export_bgp[afi]) {
1874 if (prefix_list_apply(hc->plist_export_bgp[afi],
1875 &rn->p)
1876 == PREFIX_DENY) {
1877
1878 vnc_zlog_debug_verbose(
1879 "%s: prefix list says DENY",
1880 __func__);
1881 continue;
1882 }
1883 }
1884
1885 for (ri = rn->info; ri; ri = ri->next) {
1886
1887 vnc_zlog_debug_verbose("%s: ri->sub_type: %d",
1888 __func__, ri->sub_type);
1889
1890 if (ri->sub_type == BGP_ROUTE_NORMAL
1891 || ri->sub_type == BGP_ROUTE_RFP) {
1892
1893 struct vnc_export_info *eti;
1894 struct attr hattr;
1895 struct attr *iattr;
1896
1897 /*
1898 * Construct new attribute set with
1899 * NVE's VN addr as
1900 * nexthop and without Tunnel Encap attr
1901 */
1902 if (encap_attr_export(&hattr, ri->attr,
1903 NULL, NULL)) {
1904 vnc_zlog_debug_verbose(
1905 "%s: encap_attr_export failed",
1906 __func__);
1907 continue;
1908 }
1909
1910 if (hc->routemap_export_bgp) {
1911 struct bgp_info info;
1912 route_map_result_t ret;
1913
1914 memset(&info, 0, sizeof(info));
1915 info.peer = ri->peer;
1916 info.attr = &hattr;
1917 ret = route_map_apply(
1918 hc->routemap_export_bgp,
1919 &rn->p, RMAP_BGP,
1920 &info);
1921 if (ret == RMAP_DENYMATCH) {
1922 bgp_attr_flush(&hattr);
1923 vnc_zlog_debug_verbose(
1924 "%s: route map says DENY",
1925 __func__);
1926 continue;
1927 }
1928 }
1929
1930 iattr = bgp_attr_intern(&hattr);
1931 bgp_attr_flush(&hattr);
1932
1933 /*
1934 * record route information that we will
1935 * need to expire
1936 * this route
1937 */
1938 eti = vnc_eti_get(
1939 bgp, EXPORT_TYPE_BGP, &rn->p,
1940 ri->peer,
1941 ZEBRA_ROUTE_VNC_DIRECT_RH,
1942 BGP_ROUTE_REDISTRIBUTE);
1943 rfapiGetVncLifetime(ri->attr,
1944 &eti->lifetime);
1945
1946 if (eti->timer) {
1947 /*
1948 * export expiration timer is
1949 * already running on
1950 * this route: cancel it
1951 */
1952 thread_cancel(eti->timer);
1953 eti->timer = NULL;
1954 }
1955
1956 vnc_zlog_debug_verbose(
1957 "%s: calling bgp_update",
1958 __func__);
1959
3380418f
LB
1960 bgp_update(
1961 ri->peer, &rn->p, /* prefix */
1962 0, /* addpath_id */
1963 iattr, /* bgp_update copies
1964 it */
1965 AFI_IP, SAFI_UNICAST,
1966 ZEBRA_ROUTE_VNC_DIRECT_RH,
1967 BGP_ROUTE_REDISTRIBUTE, NULL,
1968 /* RD not used for unicast */
1969 NULL,
1970 /* tag not used for unicast,
1971 or EVPN */
1972 0, 0, NULL); /* EVPN not used */
1973
d62a17ae 1974 bgp_attr_unintern(&iattr);
1975 }
1976 }
1977 }
1978 }
65efcfce
LB
1979}
1980
d62a17ae 1981void vnc_direct_bgp_rh_vpn_disable(struct bgp *bgp, afi_t afi)
65efcfce 1982{
d62a17ae 1983 struct bgp_node *rn;
1984
1985 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
1986
1987 if (!bgp)
1988 return;
1989
1990 if (afi != AFI_IP && afi != AFI_IP6) {
1991 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
1992 return;
1993 }
1994
1995 /*
1996 * Go through the entire BGP unicast table and remove routes that
1997 * originated from us
1998 */
1999 for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn;
2000 rn = bgp_route_next(rn)) {
2001
2002 struct bgp_info *ri;
2003 struct bgp_info *next;
2004
2005 for (ri = rn->info, next = NULL; ri; ri = next) {
2006
2007 next = ri->next;
2008
2009 if (ri->type == ZEBRA_ROUTE_VNC_DIRECT_RH
2010 && ri->sub_type == BGP_ROUTE_REDISTRIBUTE) {
2011
2012 struct vnc_export_info *eti;
2013
2014 /*
2015 * Delete routes immediately (no timer)
2016 */
2017 eti = vnc_eti_checktimer(
2018 bgp, EXPORT_TYPE_BGP, &rn->p, ri->peer,
2019 ZEBRA_ROUTE_VNC_DIRECT_RH,
2020 BGP_ROUTE_REDISTRIBUTE);
2021 if (eti) {
2022 if (eti->timer)
2023 thread_cancel(eti->timer);
2024 vnc_eti_delete(eti);
2025 }
2026
2027 bgp_withdraw(ri->peer, &rn->p, /* prefix */
2028 0, /* addpath_id */
2029 NULL, /* ignored */
2030 AFI_IP, SAFI_UNICAST,
2031 ZEBRA_ROUTE_VNC_DIRECT_RH,
2032 BGP_ROUTE_REDISTRIBUTE,
2033 NULL, /* RD not used for unicast */
317f1fe0 2034 NULL, 0, NULL); /* tag not used for
d62a17ae 2035 unicast, EVPN
2036 neither */
2037 }
2038 }
2039 }
65efcfce
LB
2040}
2041
d62a17ae 2042void vnc_direct_bgp_rh_reexport(struct bgp *bgp, afi_t afi)
65efcfce 2043{
d62a17ae 2044 if (VNC_EXPORT_BGP_RH_ENABLED(bgp->rfapi_cfg)) {
2045 vnc_direct_bgp_rh_vpn_disable(bgp, afi);
2046 vnc_direct_bgp_rh_vpn_enable(bgp, afi);
2047 }
65efcfce
LB
2048}
2049
2050/***********************************************************************
2051 * Generic Export methods
2052 ***********************************************************************/
2053
2054/*
2055 * Assumes the correct mode bits are already turned on. Thus it
2056 * is OK to call this function from, e.g., bgp_redistribute_set()
2057 * without caring if export is enabled or not
2058 */
d62a17ae 2059void vnc_export_bgp_enable(struct bgp *bgp, afi_t afi)
65efcfce 2060{
b8e031e5
PZ
2061 if (!bgp->rfapi_cfg)
2062 return;
2063
d62a17ae 2064 switch (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) {
2065 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE:
2066 break;
2067
2068 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP:
2069 vnc_direct_bgp_vpn_enable(bgp, afi);
2070 break;
2071
2072 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH:
2073 vnc_direct_bgp_rh_vpn_enable(bgp, afi);
2074 break;
2075
2076 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE:
2077 vnc_direct_bgp_vpn_enable_ce(bgp, afi);
2078 break;
2079 }
65efcfce
LB
2080}
2081
d62a17ae 2082void vnc_export_bgp_disable(struct bgp *bgp, afi_t afi)
65efcfce 2083{
b8e031e5
PZ
2084 if (!bgp->rfapi_cfg)
2085 return;
2086
d62a17ae 2087 switch (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) {
2088 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE:
2089 break;
2090
2091 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP:
2092 vnc_direct_bgp_vpn_disable(bgp, afi);
2093 break;
2094
2095 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH:
2096 vnc_direct_bgp_rh_vpn_disable(bgp, afi);
2097 break;
2098
2099 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE:
2100 vnc_direct_bgp_vpn_disable_ce(bgp, afi);
2101 break;
2102 }
65efcfce
LB
2103}
2104
d62a17ae 2105void vnc_export_bgp_prechange(struct bgp *bgp)
65efcfce 2106{
d62a17ae 2107 vnc_export_bgp_disable(bgp, AFI_IP);
2108 vnc_export_bgp_disable(bgp, AFI_IP6);
65efcfce
LB
2109}
2110
d62a17ae 2111void vnc_export_bgp_postchange(struct bgp *bgp)
65efcfce 2112{
d62a17ae 2113 vnc_export_bgp_enable(bgp, AFI_IP);
2114 vnc_export_bgp_enable(bgp, AFI_IP6);
65efcfce
LB
2115}
2116
d62a17ae 2117void vnc_direct_bgp_reexport(struct bgp *bgp, afi_t afi)
65efcfce 2118{
d62a17ae 2119 vnc_export_bgp_disable(bgp, afi);
2120 vnc_export_bgp_enable(bgp, afi);
65efcfce 2121}