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