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