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