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