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