]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/rfapi/vnc_export_bgp.c
Merge pull request #3087 from opensourcerouting/bfd-memleak
[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"
fe08ba7e 28#include "lib/agg_table.h"
f8b6f499
LB
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,
fe08ba7e 57 struct agg_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
fe08ba7e 175void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct agg_node *rn,
d62a17ae 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) {
1c50c1c0
QY
191 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of route node",
192 __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 */
fe08ba7e 330void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct agg_node *rn,
d62a17ae 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) {
450971aa 338 flog_err(EC_LIB_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{
fe08ba7e 407 struct agg_node *rn;
d62a17ae 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 */
fe08ba7e
DS
433 for (rn = agg_route_top(bgp->rfapi->it_ce->imported_vpn[afi]); rn;
434 rn = agg_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
fe08ba7e 516static struct ecommunity *vnc_route_origin_ecom(struct agg_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,
fe08ba7e
DS
589 struct agg_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,
fe08ba7e 695 struct agg_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) {
1c50c1c0
QY
703 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of route node",
704 __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,
fe08ba7e 806 struct agg_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) {
450971aa 813 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi route node",
1c50c1c0 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) {
1c50c1c0
QY
929 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of nve vn addr",
930 __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
fe08ba7e
DS
968 struct agg_table *rt = NULL;
969 struct agg_node *rn;
d62a17ae 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 {
450971aa 982 flog_err(EC_LIB_DEVELOPMENT, "%s: bad afi %d",
1c50c1c0 983 __func__, afi);
d62a17ae 984 return;
985 }
986
987 /*
988 * Walk the NVE-Group's VNC Import table
989 */
fe08ba7e
DS
990 for (rn = agg_route_top(rt); rn;
991 rn = agg_route_next(rn)) {
d62a17ae 992
993 if (rn->info) {
994
995 struct prefix nhp;
996 struct rfapi_descriptor *irfd = rfd;
997 struct attr hattr;
998 struct attr *iattr;
999 struct bgp_info info;
1000
1001 if (rfapiRaddr2Qprefix(&irfd->vn_addr,
1002 &nhp))
1003 continue;
1004
1005 /*
1006 * per-nve-group prefix list check
1007 */
1008 if (rfgn->rfg->plist_export_bgp[afi]) {
1009 if (prefix_list_apply(
1010 rfgn->rfg->plist_export_bgp
1011 [afi],
1012 &rn->p)
1013 == PREFIX_DENY)
1014
1015 continue;
1016 }
1017
1018
1019 /*
1020 * Construct new attribute set with
1021 * NVE's VN addr as
1022 * nexthop and without Tunnel Encap attr
1023 */
1024 if (encap_attr_export(&hattr, &attr,
1025 &nhp, rn))
1026 continue;
1027
1028 if (rfgn->rfg->routemap_export_bgp) {
1029 route_map_result_t ret;
1030 info.peer = irfd->peer;
1031 info.attr = &hattr;
1032 ret = route_map_apply(
1033 rfgn->rfg
1034 ->routemap_export_bgp,
1035 &rn->p, RMAP_BGP,
1036 &info);
1037 if (ret == RMAP_DENYMATCH) {
1038 bgp_attr_flush(&hattr);
1039 continue;
1040 }
1041 }
1042
1043 iattr = bgp_attr_intern(&hattr);
1044 bgp_attr_flush(&hattr);
3380418f
LB
1045 bgp_update(
1046 irfd->peer, &rn->p, /* prefix */
1047 0, /* addpath_id */
1048 iattr, /* bgp_update copies
1049 it */
1050 afi, SAFI_UNICAST,
1051 ZEBRA_ROUTE_VNC_DIRECT,
1052 BGP_ROUTE_REDISTRIBUTE, NULL,
1053 /* RD not used for unicast */
1054 NULL,
1055 /* tag not used for unicast */
1056 0, 0, NULL); /* EVPN not used */
d62a17ae 1057
1058 bgp_attr_unintern(&iattr);
1059 }
1060 }
1061
1062 aspath_unintern(&attr.aspath);
1063 }
1064 }
65efcfce
LB
1065}
1066
1067
d62a17ae 1068void vnc_direct_bgp_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
65efcfce 1069{
d62a17ae 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);
1074
1075 if (!afi) {
1c50c1c0
QY
1076 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of nve vn addr",
1077 __func__);
d62a17ae 1078 return;
1079 }
1080
1081 if (!bgp)
1082 return;
1083 if (!bgp->rfapi_cfg) {
1084 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1085 __func__);
1086 return;
1087 }
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",
1091 __func__);
1092 return;
1093 }
1094
1095 if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
1096 vnc_zlog_debug_verbose(
1097 "%s: bgp redistribution of VNC direct routes is off",
1098 __func__);
1099 return;
1100 }
65efcfce 1101
d62a17ae 1102 /*
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.
1106 */
1107 for (ALL_LIST_ELEMENTS(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node,
1108 nnode, rfgn)) {
1109
1110 /*
1111 * Yes, this NVE's group is configured for export to direct-bgp
1112 */
1113 if (rfg && rfgn->rfg == rfg) {
1114
fe08ba7e
DS
1115 struct agg_table *rt = NULL;
1116 struct agg_node *rn;
d62a17ae 1117 struct rfapi_import_table *import_table;
1118
1119 import_table = rfg->rfapi_import_table;
1120
1121 if (afi == AFI_IP || afi == AFI_IP6) {
1122 rt = import_table->imported_vpn[afi];
1123 } else {
450971aa 1124 flog_err(EC_LIB_DEVELOPMENT, "%s: bad afi %d",
1c50c1c0 1125 __func__, afi);
d62a17ae 1126 return;
1127 }
1128
1129 /*
1130 * Walk the NVE-Group's VNC Import table
1131 */
fe08ba7e
DS
1132 for (rn = agg_route_top(rt); rn;
1133 rn = agg_route_next(rn)) {
d62a17ae 1134
1135 if (rn->info) {
1136
1137 struct prefix nhp;
1138 struct rfapi_descriptor *irfd = rfd;
1139
1140 if (rfapiRaddr2Qprefix(&irfd->vn_addr,
1141 &nhp))
1142 continue;
1143
1144 bgp_withdraw(irfd->peer,
1145 &rn->p, /* prefix */
1146 0, /* addpath_id */
1147 NULL, /* attr, ignored */
1148 afi, SAFI_UNICAST,
1149 ZEBRA_ROUTE_VNC_DIRECT,
1150 BGP_ROUTE_REDISTRIBUTE,
1151 NULL, /* RD not used for
1152 unicast */
317f1fe0 1153 NULL, 0, NULL); /* tag not
d62a17ae 1154 used for
1155 unicast */
1156 }
1157 }
1158 }
1159 }
1160}
65efcfce 1161
d477c01d
LB
1162static void vnc_direct_add_rn_group_rd(struct bgp *bgp,
1163 struct rfapi_nve_group_cfg *rfg,
fe08ba7e 1164 struct agg_node *rn, struct attr *attr,
996c9314 1165 afi_t afi, struct rfapi_descriptor *irfd)
d477c01d
LB
1166{
1167 struct prefix nhp;
1168 struct bgp_info info;
1169 struct attr hattr;
1170 struct attr *iattr;
1171
1172 if (irfd == NULL && rfg->type != RFAPI_GROUP_CFG_VRF) {
1173 /* need new rfapi_handle, for peer strcture
1174 * -- based on vnc_add_vrf_prefi */
e1541bf6 1175 assert(rfg->rfd == NULL);
d477c01d
LB
1176
1177 if (!rfg->rt_export_list || !rfg->rfapi_import_table) {
996c9314
LB
1178 vnc_zlog_debug_verbose(
1179 "%s: VRF \"%s\" is missing RT import/export configuration.\n",
1180 __func__, rfg->name);
d477c01d
LB
1181 return;
1182 }
1183 if (!rfg->rd.prefixlen) {
996c9314
LB
1184 vnc_zlog_debug_verbose(
1185 "%s: VRF \"%s\" is missing RD configuration.\n",
1186 __func__, rfg->name);
d477c01d
LB
1187 return;
1188 }
1189 if (rfg->label > MPLS_LABEL_MAX) {
996c9314
LB
1190 vnc_zlog_debug_verbose(
1191 "%s: VRF \"%s\" is missing defaul label configuration.\n",
1192 __func__, rfg->name);
d477c01d
LB
1193 return;
1194 }
1195
1196 irfd = XCALLOC(MTYPE_RFAPI_DESC,
996c9314 1197 sizeof(struct rfapi_descriptor));
d477c01d
LB
1198 irfd->bgp = bgp;
1199 rfg->rfd = irfd;
e1541bf6
LB
1200 /*
1201 * leave most fields empty as will get from (dynamic) config
1202 * when needed
1203 */
d477c01d
LB
1204 irfd->default_tunneltype_option.type = BGP_ENCAP_TYPE_MPLS;
1205 irfd->cookie = rfg;
1206 if (rfg->vn_prefix.family
1207 && !CHECK_FLAG(rfg->flags, RFAPI_RFG_VPN_NH_SELF)) {
1208 rfapiQprefix2Raddr(&rfg->vn_prefix, &irfd->vn_addr);
1209 } else {
1210 memset(&irfd->vn_addr, 0, sizeof(struct rfapi_ip_addr));
1211 irfd->vn_addr.addr_family = AF_INET;
1212 irfd->vn_addr.addr.v4 = bgp->router_id;
1213 }
1214 irfd->un_addr = irfd->vn_addr; /* sigh, need something in UN for
1215 lookups */
1216 vnc_zlog_debug_verbose("%s: Opening RFD for VRF %s", __func__,
1217 rfg->name);
1218 rfapi_init_and_open(bgp, irfd, rfg);
1219 }
1220
1221 if (irfd == NULL || rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp))
1222 return;
1223
1224 /*
1225 * Construct new attribute set with NVE's VN
1226 * addr as
1227 * nexthop and without Tunnel Encap attr
1228 */
1229 if (encap_attr_export(&hattr, attr, &nhp, rn))
1230 return;
1231
1232 if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD)) {
996c9314 1233 vnc_zlog_debug_any("%s: attr follows", __func__);
d477c01d 1234 rfapiPrintAttrPtrs(NULL, attr);
996c9314 1235 vnc_zlog_debug_any("%s: hattr follows", __func__);
d477c01d
LB
1236 rfapiPrintAttrPtrs(NULL, &hattr);
1237 }
1238
1239 if (rfg->routemap_export_bgp) {
1240 route_map_result_t ret;
e1541bf6 1241
d477c01d
LB
1242 info.peer = irfd->peer;
1243 info.attr = &hattr;
996c9314
LB
1244 ret = route_map_apply(rfg->routemap_export_bgp, &rn->p,
1245 RMAP_BGP, &info);
d477c01d
LB
1246 if (ret == RMAP_DENYMATCH) {
1247 bgp_attr_flush(&hattr);
996c9314
LB
1248 vnc_zlog_debug_verbose(
1249 "%s: route map says DENY, so not calling bgp_update",
1250 __func__);
d477c01d
LB
1251 return;
1252 }
1253 }
1254
1255 if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD)) {
e1541bf6 1256 vnc_zlog_debug_any("%s: hattr after route_map_apply:",
d477c01d
LB
1257 __func__);
1258 rfapiPrintAttrPtrs(NULL, &hattr);
1259 }
1260 iattr = bgp_attr_intern(&hattr);
1261 bgp_attr_flush(&hattr);
1262
1263 bgp_update(irfd->peer, &rn->p, /* prefix */
1264 0, /* addpath_id */
996c9314
LB
1265 iattr, /* bgp_update copies it */
1266 afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
1267 BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
1268 NULL, /* tag not used for unicast */
1269 0, 0, NULL); /* EVPN not used */
d477c01d
LB
1270
1271 bgp_attr_unintern(&iattr);
1272
1273 return;
1274}
65efcfce
LB
1275
1276/*
1277 * Caller is responsible for ensuring that the specified nve-group
1278 * is actually part of the list of exported nve groups.
1279 */
d62a17ae 1280static void vnc_direct_bgp_add_group_afi(struct bgp *bgp,
1281 struct rfapi_nve_group_cfg *rfg,
1282 afi_t afi)
65efcfce 1283{
fe08ba7e
DS
1284 struct agg_table *rt = NULL;
1285 struct agg_node *rn;
d62a17ae 1286 struct attr attr = {0};
1287 struct rfapi_import_table *import_table;
1288
1289 vnc_zlog_debug_verbose("%s: entry", __func__);
1290
1291 import_table = rfg->rfapi_import_table;
1292 if (!import_table) {
1293 vnc_zlog_debug_verbose(
1294 "%s: import table not defined, returning", __func__);
1295 return;
1296 }
1297
1298 if (afi == AFI_IP || afi == AFI_IP6) {
1299 rt = import_table->imported_vpn[afi];
1300 } else {
450971aa 1301 flog_err(EC_LIB_DEVELOPMENT, "%s: bad afi %d", __func__, afi);
d62a17ae 1302 return;
1303 }
1304
d477c01d 1305 if (!rfg->nves && rfg->type != RFAPI_GROUP_CFG_VRF) {
d62a17ae 1306 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__);
1307 return;
1308 }
1309
1310 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
1311 /* TBD set some configured med, see add_vnc_route() */
1312
1313 /*
1314 * Walk the NVE-Group's VNC Import table
1315 */
fe08ba7e 1316 for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) {
d62a17ae 1317
1318 if (rn->info) {
1319
1320 struct listnode *ln;
1321
1322 /*
1323 * per-nve-group prefix list check
1324 */
1325 if (rfg->plist_export_bgp[afi]) {
1326 if (prefix_list_apply(
1327 rfg->plist_export_bgp[afi], &rn->p)
1328 == PREFIX_DENY)
1329
1330 continue;
1331 }
d477c01d
LB
1332 if (rfg->type == RFAPI_GROUP_CFG_VRF) {
1333 vnc_direct_add_rn_group_rd(bgp, rfg, rn, &attr,
1334 afi, rfg->rfd);
e1541bf6
LB
1335 /*
1336 * yuck!
1337 * - but consistent with rest of function
1338 */
1339 continue;
d477c01d 1340 }
d62a17ae 1341 /*
1342 * For each NVE that is assigned to the export nve
1343 * group, generate
1344 * a route with that NVE as its next hop
1345 */
1346 for (ln = listhead(rfg->nves); ln;
1347 ln = listnextnode(ln)) {
d477c01d 1348 vnc_direct_add_rn_group_rd(bgp, rfg, rn, &attr,
996c9314
LB
1349 afi,
1350 listgetdata(ln));
d62a17ae 1351 }
1352 }
1353 }
1354
1355 aspath_unintern(&attr.aspath);
65efcfce
LB
1356}
1357
1358
1359/*
1360 * Caller is responsible for ensuring that the specified nve-group
1361 * is actually part of the list of exported nve groups.
1362 */
d62a17ae 1363void vnc_direct_bgp_add_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
65efcfce 1364{
d62a17ae 1365 vnc_direct_bgp_add_group_afi(bgp, rfg, AFI_IP);
1366 vnc_direct_bgp_add_group_afi(bgp, rfg, AFI_IP6);
65efcfce
LB
1367}
1368
d477c01d
LB
1369static void vnc_direct_del_rn_group_rd(struct bgp *bgp,
1370 struct rfapi_nve_group_cfg *rfg,
fe08ba7e 1371 struct agg_node *rn, afi_t afi,
d477c01d
LB
1372 struct rfapi_descriptor *irfd)
1373{
1374 if (irfd == NULL)
1375 return;
1376 bgp_withdraw(irfd->peer, &rn->p, /* prefix */
996c9314
LB
1377 0, /* addpath_id */
1378 NULL, /* attr, ignored */
1379 afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
1380 BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
1381 NULL, 0, NULL); /* tag not used for unicast */
d477c01d
LB
1382 return;
1383}
65efcfce 1384
65efcfce
LB
1385/*
1386 * Caller is responsible for ensuring that the specified nve-group
1387 * was actually part of the list of exported nve groups.
1388 */
d62a17ae 1389static void vnc_direct_bgp_del_group_afi(struct bgp *bgp,
1390 struct rfapi_nve_group_cfg *rfg,
1391 afi_t afi)
65efcfce 1392{
fe08ba7e
DS
1393 struct agg_table *rt = NULL;
1394 struct agg_node *rn;
d62a17ae 1395 struct rfapi_import_table *import_table;
1396
1397 vnc_zlog_debug_verbose("%s: entry", __func__);
1398
1399 import_table = rfg->rfapi_import_table;
1400 if (!import_table) {
1401 vnc_zlog_debug_verbose(
1402 "%s: import table not defined, returning", __func__);
1403 return;
1404 }
1405
1406 assert(afi == AFI_IP || afi == AFI_IP6);
1407 rt = import_table->imported_vpn[afi];
1408
d477c01d 1409 if (!rfg->nves && rfg->type != RFAPI_GROUP_CFG_VRF) {
d62a17ae 1410 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__);
1411 return;
1412 }
1413
1414 /*
1415 * Walk the NVE-Group's VNC Import table
1416 */
fe08ba7e 1417 for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn))
d62a17ae 1418 if (rn->info) {
d477c01d 1419 if (rfg->type == RFAPI_GROUP_CFG_VRF)
996c9314
LB
1420 vnc_direct_del_rn_group_rd(bgp, rfg, rn, afi,
1421 rfg->rfd);
d477c01d
LB
1422 else {
1423 struct listnode *ln;
d62a17ae 1424
d477c01d 1425 /*
996c9314
LB
1426 * For each NVE that is assigned to the export
1427 * nve
d477c01d
LB
1428 * group, generate
1429 * a route with that NVE as its next hop
1430 */
1431 for (ln = listhead(rfg->nves); ln;
1432 ln = listnextnode(ln))
996c9314
LB
1433 vnc_direct_del_rn_group_rd(
1434 bgp, rfg, rn, afi,
1435 listgetdata(ln));
d62a17ae 1436 }
1437 }
65efcfce
LB
1438}
1439
65efcfce
LB
1440/*
1441 * Caller is responsible for ensuring that the specified nve-group
1442 * was actually part of the list of exported nve groups.
1443 */
d62a17ae 1444void vnc_direct_bgp_del_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
65efcfce 1445{
d62a17ae 1446 vnc_direct_bgp_del_group_afi(bgp, rfg, AFI_IP);
1447 vnc_direct_bgp_del_group_afi(bgp, rfg, AFI_IP6);
65efcfce
LB
1448}
1449
d62a17ae 1450void vnc_direct_bgp_reexport_group_afi(struct bgp *bgp,
1451 struct rfapi_nve_group_cfg *rfg,
1452 afi_t afi)
65efcfce 1453{
d62a17ae 1454 struct listnode *node;
1455 struct rfapi_rfg_name *rfgn;
1456
1457 if (VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) {
1458 /*
1459 * look in the list of currently-exported groups
1460 */
1461 for (ALL_LIST_ELEMENTS_RO(
1462 bgp->rfapi_cfg->rfg_export_direct_bgp_l, node,
1463 rfgn)) {
1464
1465 if (rfgn->rfg == rfg) {
1466 /*
1467 * If it matches, reexport it
1468 */
1469 vnc_direct_bgp_del_group_afi(bgp, rfg, afi);
1470 vnc_direct_bgp_add_group_afi(bgp, rfg, afi);
1471 break;
1472 }
1473 }
1474 }
65efcfce
LB
1475}
1476
1477
fe08ba7e 1478static void vnc_direct_bgp_unexport_table(afi_t afi, struct agg_table *rt,
d62a17ae 1479 struct list *nve_list)
65efcfce 1480{
d62a17ae 1481 if (nve_list) {
1482
fe08ba7e 1483 struct agg_node *rn;
d62a17ae 1484
fe08ba7e 1485 for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) {
d62a17ae 1486
1487 if (rn->info) {
1488
1489 struct listnode *hln;
1490 struct rfapi_descriptor *irfd;
1491
1492 for (ALL_LIST_ELEMENTS_RO(nve_list, hln,
1493 irfd)) {
1494
1495 bgp_withdraw(irfd->peer,
1496 &rn->p, /* prefix */
1497 0, /* addpath_id */
1498 NULL, /* attr, ignored */
1499 afi, SAFI_UNICAST,
1500 ZEBRA_ROUTE_VNC_DIRECT,
1501 BGP_ROUTE_REDISTRIBUTE,
1502 NULL, /* RD not used for
1503 unicast */
317f1fe0 1504 NULL, 0, NULL); /* tag not
d62a17ae 1505 used for
1506 unicast,
1507 EVPN
1508 neither */
1509 }
1510 }
1511 }
1512 }
65efcfce
LB
1513}
1514
d62a17ae 1515static void import_table_to_nve_list_direct_bgp(struct bgp *bgp,
1516 struct rfapi_import_table *it,
1517 struct list **nves,
1518 uint8_t family)
65efcfce 1519{
d62a17ae 1520 struct listnode *node;
1521 struct rfapi_rfg_name *rfgn;
1522
1523 /*
1524 * Loop over the list of NVE-Groups configured for
1525 * exporting to direct-bgp.
1526 *
1527 * Build a list of NVEs that use this import table
1528 */
1529 *nves = NULL;
1530 for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->rfg_export_direct_bgp_l, node,
1531 rfgn)) {
1532
1533 /*
1534 * If this NVE-Group's import table matches the current one
1535 */
d477c01d
LB
1536 if (rfgn->rfg && rfgn->rfg->rfapi_import_table == it) {
1537 if (rfgn->rfg->nves)
1538 nve_group_to_nve_list(rfgn->rfg, nves, family);
996c9314
LB
1539 else if (rfgn->rfg->rfd
1540 && rfgn->rfg->type == RFAPI_GROUP_CFG_VRF) {
d477c01d
LB
1541 if (!*nves)
1542 *nves = list_new();
1543 listnode_add(*nves, rfgn->rfg->rfd);
1544 }
d62a17ae 1545 }
1546 }
65efcfce
LB
1547}
1548
d62a17ae 1549void vnc_direct_bgp_vpn_enable(struct bgp *bgp, afi_t afi)
65efcfce 1550{
d62a17ae 1551 struct listnode *rfgn;
1552 struct rfapi_nve_group_cfg *rfg;
1553
1554 if (!bgp)
1555 return;
1556
1557 if (!VNC_EXPORT_BGP_GRP_ENABLED(bgp->rfapi_cfg)) {
1558 vnc_zlog_debug_verbose(
1559 "%s: export-to-bgp group mode not enabled, skipping",
1560 __func__);
1561 return;
1562 }
1563
1564 if (afi != AFI_IP && afi != AFI_IP6) {
1565 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
1566 return;
1567 }
1568
1569 /*
1570 * Policy is applied per-nve-group, so we need to iterate
1571 * over the groups to add everything.
1572 */
1573 for (ALL_LIST_ELEMENTS_RO(bgp->rfapi_cfg->nve_groups_sequential, rfgn,
1574 rfg)) {
1575
1576 /*
1577 * contains policy management
1578 */
1579 vnc_direct_bgp_add_group_afi(bgp, rfg, afi);
1580 }
65efcfce
LB
1581}
1582
1583
d62a17ae 1584void vnc_direct_bgp_vpn_disable(struct bgp *bgp, afi_t afi)
65efcfce 1585{
d62a17ae 1586 struct rfapi_import_table *it;
1587 uint8_t family = afi2family(afi);
65efcfce 1588
d62a17ae 1589 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
65efcfce 1590
d62a17ae 1591 if (!bgp)
1592 return;
65efcfce 1593
d62a17ae 1594 if (!bgp->rfapi) {
1595 vnc_zlog_debug_verbose("%s: rfapi not initialized", __func__);
1596 return;
1597 }
65efcfce 1598
d62a17ae 1599 if (!family || (afi != AFI_IP && afi != AFI_IP6)) {
1600 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
1601 return;
1602 }
65efcfce 1603
d62a17ae 1604 for (it = bgp->rfapi->imports; it; it = it->next) {
65efcfce 1605
d62a17ae 1606 struct list *nve_list = NULL;
65efcfce 1607
d62a17ae 1608 import_table_to_nve_list_direct_bgp(bgp, it, &nve_list, family);
65efcfce 1609
d62a17ae 1610 if (nve_list) {
1611 vnc_direct_bgp_unexport_table(
1612 afi, it->imported_vpn[afi], nve_list);
6a154c88 1613 list_delete(&nve_list);
d62a17ae 1614 }
1615 }
65efcfce
LB
1616}
1617
1618
1619/***********************************************************************
1620 * Export methods that proxy nexthop END
1621 ***********************************************************************/
1622
1623
1624/***********************************************************************
1625 * Export methods that preserve original nexthop BEGIN
1626 * rh = "registering nve"
1627 ***********************************************************************/
1628
1629
1630/*
1631 * "Adding a Route" export process
1632 * TBD do we need to check bi->type and bi->sub_type here, or does
1633 * caller do it?
1634 */
d62a17ae 1635void vnc_direct_bgp_rh_add_route(struct bgp *bgp, afi_t afi,
1636 struct prefix *prefix, struct peer *peer,
1637 struct attr *attr)
65efcfce 1638{
d62a17ae 1639 struct vnc_export_info *eti;
1640 struct attr hattr;
1641 struct rfapi_cfg *hc;
1642 struct attr *iattr;
1643
1644 if (!afi) {
1c50c1c0
QY
1645 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of route node",
1646 __func__);
d62a17ae 1647 return;
1648 }
1649
1650 /* check bgp redist flag for vnc direct ("vpn") routes */
1651 if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
1652 vnc_zlog_debug_verbose(
1653 "%s: bgp redistribution of VNC direct routes is off",
1654 __func__);
1655 return;
1656 }
1657
1658 if (!(hc = bgp->rfapi_cfg)) {
1659 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1660 __func__);
1661 return;
1662 }
1663
1664 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp->rfapi_cfg)) {
1665 vnc_zlog_debug_verbose(
1666 "%s: export-to-bgp RH mode not enabled, skipping",
1667 __func__);
1668 return;
1669 }
1670
1671 /*
1672 * prefix list check
1673 */
1674 if (hc->plist_export_bgp[afi]) {
1675 if (prefix_list_apply(hc->plist_export_bgp[afi], prefix)
1676 == PREFIX_DENY)
1677 return;
1678 }
1679
1680 /*
1681 * Construct new attribute set with NVE's VN addr as
1682 * nexthop and without Tunnel Encap attr
1683 */
1684 if (encap_attr_export(&hattr, attr, NULL, NULL))
1685 return;
1686 if (hc->routemap_export_bgp) {
1687 struct bgp_info info;
1688 route_map_result_t ret;
1689
1690 memset(&info, 0, sizeof(info));
1691 info.peer = peer;
1692 info.attr = &hattr;
1693 ret = route_map_apply(hc->routemap_export_bgp, prefix, RMAP_BGP,
1694 &info);
1695 if (ret == RMAP_DENYMATCH) {
1696 bgp_attr_flush(&hattr);
1697 return;
1698 }
1699 }
1700
1701 iattr = bgp_attr_intern(&hattr);
1702 bgp_attr_flush(&hattr);
1703
1704 /*
1705 * record route information that we will need to expire
1706 * this route
1707 */
1708 eti = vnc_eti_get(bgp, EXPORT_TYPE_BGP, prefix, peer,
1709 ZEBRA_ROUTE_VNC_DIRECT_RH, BGP_ROUTE_REDISTRIBUTE);
1710 rfapiGetVncLifetime(attr, &eti->lifetime);
1711 eti->lifetime = rfapiGetHolddownFromLifetime(eti->lifetime);
1712
1713 if (eti->timer) {
1714 /*
1715 * export expiration timer is already running on
1716 * this route: cancel it
1717 */
1718 thread_cancel(eti->timer);
1719 eti->timer = NULL;
1720 }
65efcfce 1721
d62a17ae 1722 bgp_update(peer, prefix, /* prefix */
1723 0, /* addpath_id */
1724 iattr, /* bgp_update copies this attr */
1725 afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT_RH,
1726 BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
996c9314 1727 NULL, /* tag not used for unicast, EVPN neither */
317f1fe0 1728 0, 0, NULL); /* EVPN not used */
d62a17ae 1729 bgp_attr_unintern(&iattr);
65efcfce
LB
1730}
1731
d62a17ae 1732static int vncExportWithdrawTimer(struct thread *t)
65efcfce 1733{
d62a17ae 1734 struct vnc_export_info *eti = t->arg;
1735
1736 /*
1737 * withdraw the route
1738 */
1739 bgp_withdraw(eti->peer, &eti->node->p, 0, /* addpath_id */
1740 NULL, /* attr, ignored */
1741 family2afi(eti->node->p.family), SAFI_UNICAST, eti->type,
1742 eti->subtype, NULL, /* RD not used for unicast */
996c9314
LB
1743 NULL, 0,
1744 NULL); /* tag not used for unicast, EVPN neither */
d62a17ae 1745
1746 /*
1747 * Free the eti
1748 */
1749 vnc_eti_delete(eti);
1750
1751 return 0;
65efcfce
LB
1752}
1753
1754/*
1755 * "Withdrawing a Route" export process
1756 * TBD do we need to check bi->type and bi->sub_type here, or does
1757 * caller do it?
1758 */
d62a17ae 1759void vnc_direct_bgp_rh_del_route(struct bgp *bgp, afi_t afi,
1760 struct prefix *prefix, struct peer *peer)
65efcfce 1761{
d62a17ae 1762 struct vnc_export_info *eti;
1763
1764 if (!afi) {
450971aa 1765 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi route node",
1c50c1c0 1766 __func__);
d62a17ae 1767 return;
1768 }
1769
1770 /* check bgp redist flag for vnc direct ("vpn") routes */
1771 if (!bgp->redist[afi][ZEBRA_ROUTE_VNC_DIRECT]) {
1772 vnc_zlog_debug_verbose(
1773 "%s: bgp redistribution of VNC direct routes is off",
1774 __func__);
1775 return;
1776 }
1777
1778 if (!bgp->rfapi_cfg) {
1779 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1780 __func__);
1781 return;
1782 }
1783 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp->rfapi_cfg)) {
1784 vnc_zlog_debug_verbose(
1785 "%s: export-to-bgp group mode not enabled, skipping",
1786 __func__);
1787 return;
1788 }
1789
1790 eti = vnc_eti_get(bgp, EXPORT_TYPE_BGP, prefix, peer,
1791 ZEBRA_ROUTE_VNC_DIRECT_RH, BGP_ROUTE_REDISTRIBUTE);
1792
1793 if (!eti->timer && eti->lifetime <= INT32_MAX) {
1794 eti->timer = NULL;
1795 thread_add_timer(bm->master, vncExportWithdrawTimer, eti,
1796 eti->lifetime, &eti->timer);
1797 vnc_zlog_debug_verbose(
1798 "%s: set expiration timer for %u seconds", __func__,
1799 eti->lifetime);
1800 }
65efcfce
LB
1801}
1802
1803
d62a17ae 1804void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi)
65efcfce 1805{
d62a17ae 1806 struct prefix_rd prd;
1807 struct bgp_node *prn;
1808 struct rfapi_cfg *hc;
1809
1810 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
1811
1812 if (!bgp)
1813 return;
1814
1815 if (!(hc = bgp->rfapi_cfg))
1816 return;
1817
1818 if (!VNC_EXPORT_BGP_RH_ENABLED(bgp->rfapi_cfg)) {
1819 vnc_zlog_debug_verbose(
1820 "%s: export of RH routes not enabled, skipping",
1821 __func__);
1822 return;
1823 }
1824
1825 if (afi != AFI_IP && afi != AFI_IP6) {
1826 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
1827 return;
1828 }
1829
1830 /*
1831 * Go through the entire BGP VPN table and export to BGP unicast.
1832 */
1833
1834 vnc_zlog_debug_verbose("%s: starting RD loop", __func__);
1835
1836 /* Loop over all the RDs */
1837 for (prn = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); prn;
1838 prn = bgp_route_next(prn)) {
1839
1840 struct bgp_table *table;
1841 struct bgp_node *rn;
1842 struct bgp_info *ri;
1843
1844 memset(&prd, 0, sizeof(prd));
1845 prd.family = AF_UNSPEC;
1846 prd.prefixlen = 64;
1847 memcpy(prd.val, prn->p.u.val, 8);
1848
1849 /* This is the per-RD table of prefixes */
1850 table = prn->info;
1851
d477c01d
LB
1852 if (!table)
1853 continue;
1854
d62a17ae 1855 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
1856
1857 /*
1858 * skip prefix list check if no routes here
1859 */
1860 if (!rn->info)
1861 continue;
1862
1863 {
872ed4c7 1864 char prefixstr[PREFIX_STRLEN];
d62a17ae 1865
872ed4c7
DS
1866 prefix2str(&rn->p, prefixstr,
1867 sizeof(prefixstr));
996c9314
LB
1868 vnc_zlog_debug_verbose("%s: checking prefix %s",
1869 __func__, prefixstr);
d62a17ae 1870 }
1871
1872 /*
1873 * prefix list check
1874 */
1875 if (hc->plist_export_bgp[afi]) {
1876 if (prefix_list_apply(hc->plist_export_bgp[afi],
1877 &rn->p)
1878 == PREFIX_DENY) {
1879
1880 vnc_zlog_debug_verbose(
1881 "%s: prefix list says DENY",
1882 __func__);
1883 continue;
1884 }
1885 }
1886
1887 for (ri = rn->info; ri; ri = ri->next) {
1888
1889 vnc_zlog_debug_verbose("%s: ri->sub_type: %d",
1890 __func__, ri->sub_type);
1891
1892 if (ri->sub_type == BGP_ROUTE_NORMAL
1893 || ri->sub_type == BGP_ROUTE_RFP) {
1894
1895 struct vnc_export_info *eti;
1896 struct attr hattr;
1897 struct attr *iattr;
1898
1899 /*
1900 * Construct new attribute set with
1901 * NVE's VN addr as
1902 * nexthop and without Tunnel Encap attr
1903 */
1904 if (encap_attr_export(&hattr, ri->attr,
1905 NULL, NULL)) {
1906 vnc_zlog_debug_verbose(
1907 "%s: encap_attr_export failed",
1908 __func__);
1909 continue;
1910 }
1911
1912 if (hc->routemap_export_bgp) {
1913 struct bgp_info info;
1914 route_map_result_t ret;
1915
1916 memset(&info, 0, sizeof(info));
1917 info.peer = ri->peer;
1918 info.attr = &hattr;
1919 ret = route_map_apply(
1920 hc->routemap_export_bgp,
1921 &rn->p, RMAP_BGP,
1922 &info);
1923 if (ret == RMAP_DENYMATCH) {
1924 bgp_attr_flush(&hattr);
1925 vnc_zlog_debug_verbose(
1926 "%s: route map says DENY",
1927 __func__);
1928 continue;
1929 }
1930 }
1931
1932 iattr = bgp_attr_intern(&hattr);
1933 bgp_attr_flush(&hattr);
1934
1935 /*
1936 * record route information that we will
1937 * need to expire
1938 * this route
1939 */
1940 eti = vnc_eti_get(
1941 bgp, EXPORT_TYPE_BGP, &rn->p,
1942 ri->peer,
1943 ZEBRA_ROUTE_VNC_DIRECT_RH,
1944 BGP_ROUTE_REDISTRIBUTE);
1945 rfapiGetVncLifetime(ri->attr,
1946 &eti->lifetime);
1947
1948 if (eti->timer) {
1949 /*
1950 * export expiration timer is
1951 * already running on
1952 * this route: cancel it
1953 */
1954 thread_cancel(eti->timer);
1955 eti->timer = NULL;
1956 }
1957
1958 vnc_zlog_debug_verbose(
1959 "%s: calling bgp_update",
1960 __func__);
1961
3380418f
LB
1962 bgp_update(
1963 ri->peer, &rn->p, /* prefix */
1964 0, /* addpath_id */
1965 iattr, /* bgp_update copies
1966 it */
1967 AFI_IP, SAFI_UNICAST,
1968 ZEBRA_ROUTE_VNC_DIRECT_RH,
1969 BGP_ROUTE_REDISTRIBUTE, NULL,
1970 /* RD not used for unicast */
1971 NULL,
1972 /* tag not used for unicast,
1973 or EVPN */
1974 0, 0, NULL); /* EVPN not used */
1975
d62a17ae 1976 bgp_attr_unintern(&iattr);
1977 }
1978 }
1979 }
1980 }
65efcfce
LB
1981}
1982
d62a17ae 1983void vnc_direct_bgp_rh_vpn_disable(struct bgp *bgp, afi_t afi)
65efcfce 1984{
d62a17ae 1985 struct bgp_node *rn;
1986
1987 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
1988
1989 if (!bgp)
1990 return;
1991
1992 if (afi != AFI_IP && afi != AFI_IP6) {
1993 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
1994 return;
1995 }
1996
1997 /*
1998 * Go through the entire BGP unicast table and remove routes that
1999 * originated from us
2000 */
2001 for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn;
2002 rn = bgp_route_next(rn)) {
2003
2004 struct bgp_info *ri;
2005 struct bgp_info *next;
2006
2007 for (ri = rn->info, next = NULL; ri; ri = next) {
2008
2009 next = ri->next;
2010
2011 if (ri->type == ZEBRA_ROUTE_VNC_DIRECT_RH
2012 && ri->sub_type == BGP_ROUTE_REDISTRIBUTE) {
2013
2014 struct vnc_export_info *eti;
2015
2016 /*
2017 * Delete routes immediately (no timer)
2018 */
2019 eti = vnc_eti_checktimer(
2020 bgp, EXPORT_TYPE_BGP, &rn->p, ri->peer,
2021 ZEBRA_ROUTE_VNC_DIRECT_RH,
2022 BGP_ROUTE_REDISTRIBUTE);
2023 if (eti) {
2024 if (eti->timer)
2025 thread_cancel(eti->timer);
2026 vnc_eti_delete(eti);
2027 }
2028
2029 bgp_withdraw(ri->peer, &rn->p, /* prefix */
2030 0, /* addpath_id */
2031 NULL, /* ignored */
2032 AFI_IP, SAFI_UNICAST,
2033 ZEBRA_ROUTE_VNC_DIRECT_RH,
2034 BGP_ROUTE_REDISTRIBUTE,
2035 NULL, /* RD not used for unicast */
317f1fe0 2036 NULL, 0, NULL); /* tag not used for
d62a17ae 2037 unicast, EVPN
2038 neither */
2039 }
2040 }
2041 }
65efcfce
LB
2042}
2043
d62a17ae 2044void vnc_direct_bgp_rh_reexport(struct bgp *bgp, afi_t afi)
65efcfce 2045{
d62a17ae 2046 if (VNC_EXPORT_BGP_RH_ENABLED(bgp->rfapi_cfg)) {
2047 vnc_direct_bgp_rh_vpn_disable(bgp, afi);
2048 vnc_direct_bgp_rh_vpn_enable(bgp, afi);
2049 }
65efcfce
LB
2050}
2051
2052/***********************************************************************
2053 * Generic Export methods
2054 ***********************************************************************/
2055
2056/*
2057 * Assumes the correct mode bits are already turned on. Thus it
2058 * is OK to call this function from, e.g., bgp_redistribute_set()
2059 * without caring if export is enabled or not
2060 */
d62a17ae 2061void vnc_export_bgp_enable(struct bgp *bgp, afi_t afi)
65efcfce 2062{
b8e031e5
PZ
2063 if (!bgp->rfapi_cfg)
2064 return;
2065
d62a17ae 2066 switch (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) {
2067 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE:
2068 break;
2069
2070 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP:
2071 vnc_direct_bgp_vpn_enable(bgp, afi);
2072 break;
2073
2074 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH:
2075 vnc_direct_bgp_rh_vpn_enable(bgp, afi);
2076 break;
2077
2078 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE:
2079 vnc_direct_bgp_vpn_enable_ce(bgp, afi);
2080 break;
2081 }
65efcfce
LB
2082}
2083
d62a17ae 2084void vnc_export_bgp_disable(struct bgp *bgp, afi_t afi)
65efcfce 2085{
b8e031e5
PZ
2086 if (!bgp->rfapi_cfg)
2087 return;
2088
d62a17ae 2089 switch (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_EXPORT_BGP_MODE_BITS) {
2090 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_NONE:
2091 break;
2092
2093 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_GRP:
2094 vnc_direct_bgp_vpn_disable(bgp, afi);
2095 break;
2096
2097 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_RH:
2098 vnc_direct_bgp_rh_vpn_disable(bgp, afi);
2099 break;
2100
2101 case BGP_VNC_CONFIG_EXPORT_BGP_MODE_CE:
2102 vnc_direct_bgp_vpn_disable_ce(bgp, afi);
2103 break;
2104 }
65efcfce
LB
2105}
2106
d62a17ae 2107void vnc_export_bgp_prechange(struct bgp *bgp)
65efcfce 2108{
d62a17ae 2109 vnc_export_bgp_disable(bgp, AFI_IP);
2110 vnc_export_bgp_disable(bgp, AFI_IP6);
65efcfce
LB
2111}
2112
d62a17ae 2113void vnc_export_bgp_postchange(struct bgp *bgp)
65efcfce 2114{
d62a17ae 2115 vnc_export_bgp_enable(bgp, AFI_IP);
2116 vnc_export_bgp_enable(bgp, AFI_IP6);
65efcfce
LB
2117}
2118
d62a17ae 2119void vnc_direct_bgp_reexport(struct bgp *bgp, afi_t afi)
65efcfce 2120{
d62a17ae 2121 vnc_export_bgp_disable(bgp, afi);
2122 vnc_export_bgp_enable(bgp, afi);
65efcfce 2123}