]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/rfapi/vnc_export_bgp.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / bgpd / rfapi / vnc_export_bgp.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 *
4 * Copyright 2009-2016, LabN Consulting, L.L.C.
5 *
6 */
7
8 /*
9 * File: vnc_export_bgp.c
10 * Purpose: Export routes to BGP directly (not via zebra)
11 */
12
13 #include "lib/zebra.h"
14 #include "lib/prefix.h"
15 #include "lib/agg_table.h"
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"
23 #include "lib/lib_errors.h"
24
25 #include "bgpd/bgpd.h"
26 #include "bgpd/bgp_ecommunity.h"
27 #include "bgpd/bgp_attr.h"
28 #include "bgpd/bgp_aspath.h"
29
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"
40
41
42 static void vnc_direct_add_rn_group_rd(struct bgp *bgp,
43 struct rfapi_nve_group_cfg *rfg,
44 struct agg_node *rn, struct attr *attr,
45 afi_t afi,
46 struct rfapi_descriptor *irfd);
47
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 */
61 static void encap_attr_export_ce(struct attr *new, struct attr *orig,
62 struct prefix *use_nexthop)
63 {
64 /*
65 * Make "new" a ghost attr copy of "orig"
66 */
67 memset(new, 0, sizeof(struct attr));
68 *new = *orig;
69
70 /*
71 * Set nexthop
72 */
73 switch (use_nexthop->family) {
74 case AF_INET:
75 new->nexthop = use_nexthop->u.prefix4;
76 new->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; /* bytes */
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;
82 new->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; /* bytes */
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 */
119 }
120
121 static int getce(struct bgp *bgp, struct attr *attr, struct prefix *pfx_ce)
122 {
123 uint8_t *ecp;
124 uint32_t i;
125 uint16_t localadmin = bgp->rfapi_cfg->resolve_nve_roo_local_admin;
126 struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
127
128 for (ecp = ecomm->val, i = 0; i < ecomm->size;
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;
155 pfx_ce->prefixlen = IPV4_MAX_BITLEN;
156
157 return 0;
158 }
159 return -1;
160 }
161
162
163 void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct agg_node *rn,
164 struct bgp_path_info *bpi)
165 {
166 struct attr *attr = bpi->attr;
167 struct peer *peer = bpi->peer;
168 const struct prefix *prefix = agg_node_get_prefix(rn);
169 afi_t afi = family2afi(prefix->family);
170 struct bgp_dest *udest;
171 struct bgp_path_info *ubpi;
172 struct attr hattr;
173 struct attr *iattr;
174 struct prefix ce_nexthop;
175 struct prefix post_routemap_nexthop;
176
177
178 if (!afi) {
179 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of route node",
180 __func__);
181 return;
182 }
183
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)) {
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 */
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) {
249 struct prefix unicast_nexthop;
250
251 if (CHECK_FLAG(ubpi->flags, BGP_PATH_REMOVED))
252 continue;
253
254 rfapiUnicastNexthop2Prefix(afi, ubpi->attr, &unicast_nexthop);
255
256 if (ubpi->type == ZEBRA_ROUTE_VNC_DIRECT
257 && ubpi->sub_type == BGP_ROUTE_REDISTRIBUTE
258 && ubpi->peer == peer
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) {
274 struct bgp_path_info info;
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,
281 prefix, &info);
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 */
310 NULL, 0, /* tag not used for unicast */
311 0, NULL); /* EVPN not used */
312 bgp_attr_unintern(&iattr);
313 }
314
315
316 /*
317 * "Withdrawing a Route" export process
318 */
319 void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct agg_node *rn,
320 struct bgp_path_info *bpi)
321 {
322 const struct prefix *p = agg_node_get_prefix(rn);
323 afi_t afi = family2afi(p->family);
324 struct bgp_path_info *vbpi;
325 struct prefix ce_nexthop;
326
327 if (!afi) {
328 flog_err(EC_LIB_DEVELOPMENT, "%s: bad afi", __func__);
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 */
357 if (getce(bgp, bpi->attr, &ce_nexthop)) {
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
369 for (vbpi = rn->info; vbpi; vbpi = vbpi->next) {
370 struct prefix ce;
371 if (bpi == vbpi)
372 continue;
373 if (bpi->peer != vbpi->peer)
374 continue;
375 if (getce(bgp, vbpi->attr, &ce))
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 }
384
385 /*
386 * withdraw the route
387 */
388 bgp_withdraw(bpi->peer, p, 0, /* addpath_id */
389 afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
390 BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */
391 NULL, 0, NULL); /* tag not used for unicast */
392 }
393
394 static void vnc_direct_bgp_vpn_enable_ce(struct bgp *bgp, afi_t afi)
395 {
396 struct agg_node *rn;
397 struct bgp_path_info *ri;
398
399 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
400
401 if (!bgp)
402 return;
403
404 if (!(bgp->rfapi_cfg))
405 return;
406
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 }
413
414 if (afi != AFI_IP && afi != AFI_IP6) {
415 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
416 return;
417 }
418
419 /*
420 * Go through entire ce import table and export to BGP unicast.
421 */
422 for (rn = agg_route_top(bgp->rfapi->it_ce->imported_vpn[afi]); rn;
423 rn = agg_route_next(rn)) {
424 if (!rn->info)
425 continue;
426
427 vnc_zlog_debug_verbose("%s: checking prefix %pRN", __func__,
428 rn);
429
430 for (ri = rn->info; ri; ri = ri->next) {
431
432 vnc_zlog_debug_verbose("%s: ri->sub_type: %d", __func__,
433 ri->sub_type);
434
435 if (ri->sub_type == BGP_ROUTE_NORMAL
436 || ri->sub_type == BGP_ROUTE_RFP
437 || ri->sub_type == BGP_ROUTE_STATIC) {
438
439 vnc_direct_bgp_add_route_ce(bgp, rn, ri);
440 }
441 }
442 }
443 }
444
445 static void vnc_direct_bgp_vpn_disable_ce(struct bgp *bgp, afi_t afi)
446 {
447 struct bgp_dest *dest;
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 */
463 for (dest = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); dest;
464 dest = bgp_route_next(dest)) {
465
466 struct bgp_path_info *ri;
467 struct bgp_path_info *next;
468
469 for (ri = bgp_dest_get_bgp_path_info(dest), next = NULL; ri;
470 ri = next) {
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(
478 ri->peer, bgp_dest_get_prefix(dest),
479 0, /* addpath_id */
480 AFI_IP, SAFI_UNICAST,
481 ZEBRA_ROUTE_VNC_DIRECT,
482 BGP_ROUTE_REDISTRIBUTE,
483 NULL, /* RD not used for unicast */
484 NULL, 0,
485 NULL); /* tag not used for unicast */
486 }
487 }
488 }
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
499 static struct ecommunity *vnc_route_origin_ecom(struct agg_node *rn)
500 {
501 struct ecommunity *new;
502 struct bgp_path_info *bpi;
503
504 if (!rn->info)
505 return NULL;
506
507 new = ecommunity_new();
508
509 for (bpi = rn->info; bpi; bpi = bpi->next) {
510
511 struct ecommunity_val roec;
512
513 switch (BGP_MP_NEXTHOP_FAMILY(bpi->attr->mp_nexthop_len)) {
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,
519 &bpi->attr->mp_nexthop_global_in.s_addr, 4);
520 roec.val[6] = 0;
521 roec.val[7] = 0;
522 ecommunity_add_val(new, &roec, false, false);
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;
537 }
538
539 static struct ecommunity *vnc_route_origin_ecom_single(struct in_addr *origin)
540 {
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();
552 ecommunity_add_val(new, &roec, false, false);
553
554 if (!new->size) {
555 ecommunity_free(&new);
556 new = NULL;
557 }
558
559 return new;
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 */
568 static int
569 encap_attr_export(struct attr *new, struct attr *orig,
570 struct prefix *new_nexthop,
571 struct agg_node *rn) /* for VN addrs for ecom list */
572 /* if rn is 0, use route's nexthop */
573 {
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) {
585 orig_nexthop.prefixlen = IPV4_MAX_BITLEN;
586 orig_nexthop.u.prefix4 = orig->mp_nexthop_global_in;
587 } else if (orig_nexthop.family == AF_INET6) {
588 orig_nexthop.prefixlen = IPV6_MAX_BITLEN;
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));
600 *new = *orig;
601
602 /*
603 * Set nexthop
604 */
605 switch (use_nexthop->family) {
606 case AF_INET:
607 new->nexthop = use_nexthop->u.prefix4;
608 new->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; /* bytes */
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;
614 new->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; /* bytes */
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 {
625 /* TBD use lcom for IPv6 */
626 ecom_ro = vnc_route_origin_ecom_single(&use_nexthop->u.prefix4);
627 }
628 if (bgp_attr_get_ecommunity(new)) {
629 if (ecom_ro)
630 bgp_attr_set_ecommunity(
631 new,
632 ecommunity_merge(ecom_ro,
633 bgp_attr_get_ecommunity(new)));
634 } else {
635 bgp_attr_set_ecommunity(new, ecom_ro);
636 }
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;
669 }
670
671 /*
672 * "Adding a Route" export process
673 */
674 void vnc_direct_bgp_add_prefix(struct bgp *bgp,
675 struct rfapi_import_table *import_table,
676 struct agg_node *rn)
677 {
678 struct attr attr = {0};
679 struct listnode *node, *nnode;
680 struct rfapi_rfg_name *rfgn;
681 const struct prefix *p = agg_node_get_prefix(rn);
682 afi_t afi = family2afi(p->family);
683
684 if (!afi) {
685 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of route node",
686 __func__);
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
718 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
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 */
745 if (rfgn->rfg->type != RFAPI_GROUP_CFG_VRF && !rfgn->rfg->nves)
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],
753 p)
754 == PREFIX_DENY)
755
756 continue;
757 }
758
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);
762 /*
763 * yuck!
764 * - but consistent with rest of function
765 */
766 continue;
767 }
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)) {
775 vnc_direct_add_rn_group_rd(bgp, rfgn->rfg, rn, &attr,
776 afi, listgetdata(ln));
777 }
778 }
779
780 aspath_unintern(&attr.aspath);
781 }
782
783 /*
784 * "Withdrawing a Route" export process
785 */
786 void vnc_direct_bgp_del_prefix(struct bgp *bgp,
787 struct rfapi_import_table *import_table,
788 struct agg_node *rn)
789 {
790 struct listnode *node, *nnode;
791 struct rfapi_rfg_name *rfgn;
792 const struct prefix *p = agg_node_get_prefix(rn);
793 afi_t afi = family2afi(p->family);
794
795 if (!afi) {
796 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi route node",
797 __func__);
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 */
843 if (rfgn->rfg->type != RFAPI_GROUP_CFG_VRF && !rfgn->rfg->nves)
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
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
862 bgp_withdraw(irfd->peer, p, /* prefix */
863 0, /* addpath_id */
864 afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
865 BGP_ROUTE_REDISTRIBUTE,
866 NULL, /* RD not used for unicast */
867 NULL, 0,
868 NULL); /* tag not used for unicast */
869 /*
870 * yuck!
871 * - but consistent with rest of function
872 */
873 continue;
874 }
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
891 bgp_withdraw(irfd->peer, p, /* prefix */
892 0, /* addpath_id */
893 afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT,
894 BGP_ROUTE_REDISTRIBUTE,
895 NULL, /* RD not used for unicast */
896 NULL, 0,
897 NULL); /* tag not used for unicast */
898 }
899 }
900 }
901
902 void vnc_direct_bgp_add_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
903 {
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) {
910 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of nve vn addr",
911 __func__);
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
949 struct agg_table *rt = NULL;
950 struct agg_node *rn;
951 struct attr attr = {0};
952 struct rfapi_import_table *import_table;
953
954
955 import_table = rfg->rfapi_import_table;
956
957 if (afi == AFI_IP || afi == AFI_IP6) {
958 rt = import_table->imported_vpn[afi];
959 } else {
960 flog_err(EC_LIB_DEVELOPMENT, "%s: bad afi %d",
961 __func__, afi);
962 return;
963 }
964
965 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
966 /* TBD set some configured med, see add_vnc_route() */
967
968 /*
969 * Walk the NVE-Group's VNC Import table
970 */
971 for (rn = agg_route_top(rt); rn;
972 rn = agg_route_next(rn)) {
973
974 if (rn->info) {
975
976 struct prefix nhp;
977 struct rfapi_descriptor *irfd = rfd;
978 struct attr hattr;
979 struct attr *iattr;
980 struct bgp_path_info info;
981 const struct prefix *p =
982 agg_node_get_prefix(rn);
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],
995 p)
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,
1018 p, &info);
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);
1027 bgp_update(
1028 irfd->peer, p, /* prefix */
1029 0, /* addpath_id */
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 */
1039
1040 bgp_attr_unintern(&iattr);
1041 }
1042 }
1043
1044 aspath_unintern(&attr.aspath);
1045 }
1046 }
1047 }
1048
1049
1050 void vnc_direct_bgp_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
1051 {
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) {
1058 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of nve vn addr",
1059 __func__);
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 }
1083
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
1097 struct agg_table *rt = NULL;
1098 struct agg_node *rn;
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 {
1106 flog_err(EC_LIB_DEVELOPMENT, "%s: bad afi %d",
1107 __func__, afi);
1108 return;
1109 }
1110
1111 /*
1112 * Walk the NVE-Group's VNC Import table
1113 */
1114 for (rn = agg_route_top(rt); rn;
1115 rn = agg_route_next(rn)) {
1116
1117 if (rn->info) {
1118 const struct prefix *p =
1119 agg_node_get_prefix(rn);
1120 struct prefix nhp;
1121 struct rfapi_descriptor *irfd = rfd;
1122
1123 if (rfapiRaddr2Qprefix(&irfd->vn_addr,
1124 &nhp))
1125 continue;
1126
1127 bgp_withdraw(irfd->peer, p, /* prefix */
1128 0, /* addpath_id */
1129 afi, SAFI_UNICAST,
1130 ZEBRA_ROUTE_VNC_DIRECT,
1131 BGP_ROUTE_REDISTRIBUTE,
1132 NULL, /* RD not used for
1133 unicast */
1134 NULL, 0, NULL); /* tag not
1135 used for
1136 unicast */
1137 }
1138 }
1139 }
1140 }
1141 }
1142
1143 static void vnc_direct_add_rn_group_rd(struct bgp *bgp,
1144 struct rfapi_nve_group_cfg *rfg,
1145 struct agg_node *rn, struct attr *attr,
1146 afi_t afi, struct rfapi_descriptor *irfd)
1147 {
1148 struct prefix nhp;
1149 struct bgp_path_info info;
1150 struct attr hattr;
1151 struct attr *iattr;
1152 const struct prefix *p = agg_node_get_prefix(rn);
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 */
1157 assert(rfg->rfd == NULL);
1158
1159 if (!rfg->rt_export_list || !rfg->rfapi_import_table) {
1160 vnc_zlog_debug_verbose(
1161 "%s: VRF \"%s\" is missing RT import/export configuration.",
1162 __func__, rfg->name);
1163 return;
1164 }
1165 if (!rfg->rd.prefixlen) {
1166 vnc_zlog_debug_verbose(
1167 "%s: VRF \"%s\" is missing RD configuration.",
1168 __func__, rfg->name);
1169 return;
1170 }
1171 if (rfg->label > MPLS_LABEL_MAX) {
1172 vnc_zlog_debug_verbose(
1173 "%s: VRF \"%s\" is missing default label configuration.",
1174 __func__, rfg->name);
1175 return;
1176 }
1177
1178 irfd = XCALLOC(MTYPE_RFAPI_DESC,
1179 sizeof(struct rfapi_descriptor));
1180 irfd->bgp = bgp;
1181 rfg->rfd = irfd;
1182 /*
1183 * leave most fields empty as will get from (dynamic) config
1184 * when needed
1185 */
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)) {
1215 vnc_zlog_debug_any("%s: attr follows", __func__);
1216 rfapiPrintAttrPtrs(NULL, attr);
1217 vnc_zlog_debug_any("%s: hattr follows", __func__);
1218 rfapiPrintAttrPtrs(NULL, &hattr);
1219 }
1220
1221 if (rfg->routemap_export_bgp) {
1222 route_map_result_t ret;
1223
1224 info.peer = irfd->peer;
1225 info.attr = &hattr;
1226 ret = route_map_apply(rfg->routemap_export_bgp, p, &info);
1227 if (ret == RMAP_DENYMATCH) {
1228 bgp_attr_flush(&hattr);
1229 vnc_zlog_debug_verbose(
1230 "%s: route map says DENY, so not calling bgp_update",
1231 __func__);
1232 return;
1233 }
1234 }
1235
1236 if (VNC_DEBUG(EXPORT_BGP_DIRECT_ADD)) {
1237 vnc_zlog_debug_any("%s: hattr after route_map_apply:",
1238 __func__);
1239 rfapiPrintAttrPtrs(NULL, &hattr);
1240 }
1241 iattr = bgp_attr_intern(&hattr);
1242 bgp_attr_flush(&hattr);
1243
1244 bgp_update(irfd->peer, p, /* prefix */
1245 0, /* addpath_id */
1246 iattr, /* bgp_update copies it */
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 */
1251
1252 bgp_attr_unintern(&iattr);
1253
1254 return;
1255 }
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 */
1261 static void vnc_direct_bgp_add_group_afi(struct bgp *bgp,
1262 struct rfapi_nve_group_cfg *rfg,
1263 afi_t afi)
1264 {
1265 struct agg_table *rt = NULL;
1266 struct agg_node *rn;
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 {
1282 flog_err(EC_LIB_DEVELOPMENT, "%s: bad afi %d", __func__, afi);
1283 return;
1284 }
1285
1286 if (!rfg->nves && rfg->type != RFAPI_GROUP_CFG_VRF) {
1287 vnc_zlog_debug_verbose("%s: no NVEs in this group", __func__);
1288 return;
1289 }
1290
1291 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
1292 /* TBD set some configured med, see add_vnc_route() */
1293
1294 /*
1295 * Walk the NVE-Group's VNC Import table
1296 */
1297 for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) {
1298
1299 if (rn->info) {
1300 const struct prefix *p = agg_node_get_prefix(rn);
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(
1308 rfg->plist_export_bgp[afi], p)
1309 == PREFIX_DENY)
1310
1311 continue;
1312 }
1313 if (rfg->type == RFAPI_GROUP_CFG_VRF) {
1314 vnc_direct_add_rn_group_rd(bgp, rfg, rn, &attr,
1315 afi, rfg->rfd);
1316 /*
1317 * yuck!
1318 * - but consistent with rest of function
1319 */
1320 continue;
1321 }
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)) {
1329 vnc_direct_add_rn_group_rd(bgp, rfg, rn, &attr,
1330 afi,
1331 listgetdata(ln));
1332 }
1333 }
1334 }
1335
1336 aspath_unintern(&attr.aspath);
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 */
1344 void vnc_direct_bgp_add_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
1345 {
1346 vnc_direct_bgp_add_group_afi(bgp, rfg, AFI_IP);
1347 vnc_direct_bgp_add_group_afi(bgp, rfg, AFI_IP6);
1348 }
1349
1350 static void vnc_direct_del_rn_group_rd(struct bgp *bgp,
1351 struct rfapi_nve_group_cfg *rfg,
1352 struct agg_node *rn, afi_t afi,
1353 struct rfapi_descriptor *irfd)
1354 {
1355 if (irfd == NULL)
1356 return;
1357
1358 bgp_withdraw(irfd->peer, agg_node_get_prefix(rn), /* prefix */
1359 0, /* addpath_id */
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 */
1363 return;
1364 }
1365
1366 /*
1367 * Caller is responsible for ensuring that the specified nve-group
1368 * was actually part of the list of exported nve groups.
1369 */
1370 static void vnc_direct_bgp_del_group_afi(struct bgp *bgp,
1371 struct rfapi_nve_group_cfg *rfg,
1372 afi_t afi)
1373 {
1374 struct agg_table *rt = NULL;
1375 struct agg_node *rn;
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
1387 rt = import_table->imported_vpn[afi];
1388
1389 if (!rfg->nves && rfg->type != RFAPI_GROUP_CFG_VRF) {
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 */
1397 for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn))
1398 if (rn->info) {
1399 if (rfg->type == RFAPI_GROUP_CFG_VRF)
1400 vnc_direct_del_rn_group_rd(bgp, rfg, rn, afi,
1401 rfg->rfd);
1402 else {
1403 struct listnode *ln;
1404
1405 /*
1406 * For each NVE that is assigned to the export
1407 * nve
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))
1413 vnc_direct_del_rn_group_rd(
1414 bgp, rfg, rn, afi,
1415 listgetdata(ln));
1416 }
1417 }
1418 }
1419
1420 /*
1421 * Caller is responsible for ensuring that the specified nve-group
1422 * was actually part of the list of exported nve groups.
1423 */
1424 void vnc_direct_bgp_del_group(struct bgp *bgp, struct rfapi_nve_group_cfg *rfg)
1425 {
1426 vnc_direct_bgp_del_group_afi(bgp, rfg, AFI_IP);
1427 vnc_direct_bgp_del_group_afi(bgp, rfg, AFI_IP6);
1428 }
1429
1430 void vnc_direct_bgp_reexport_group_afi(struct bgp *bgp,
1431 struct rfapi_nve_group_cfg *rfg,
1432 afi_t afi)
1433 {
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 }
1455 }
1456
1457
1458 static void vnc_direct_bgp_unexport_table(afi_t afi, struct agg_table *rt,
1459 struct list *nve_list)
1460 {
1461 if (nve_list) {
1462
1463 struct agg_node *rn;
1464
1465 for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) {
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,
1476 agg_node_get_prefix(rn),
1477 0, /* addpath_id */
1478 afi, SAFI_UNICAST,
1479 ZEBRA_ROUTE_VNC_DIRECT,
1480 BGP_ROUTE_REDISTRIBUTE,
1481 NULL, /* RD not used for
1482 unicast */
1483 NULL, 0, NULL); /* tag not
1484 used for
1485 unicast,
1486 EVPN
1487 neither */
1488 }
1489 }
1490 }
1491 }
1492 }
1493
1494 static 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)
1498 {
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 */
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);
1518 else if (rfgn->rfg->rfd
1519 && rfgn->rfg->type == RFAPI_GROUP_CFG_VRF) {
1520 if (!*nves)
1521 *nves = list_new();
1522 listnode_add(*nves, rfgn->rfg->rfd);
1523 }
1524 }
1525 }
1526 }
1527
1528 void vnc_direct_bgp_vpn_enable(struct bgp *bgp, afi_t afi)
1529 {
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 }
1560 }
1561
1562
1563 void vnc_direct_bgp_vpn_disable(struct bgp *bgp, afi_t afi)
1564 {
1565 struct rfapi_import_table *it;
1566 uint8_t family = afi2family(afi);
1567
1568 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
1569
1570 if (!bgp)
1571 return;
1572
1573 if (!bgp->rfapi) {
1574 vnc_zlog_debug_verbose("%s: rfapi not initialized", __func__);
1575 return;
1576 }
1577
1578 if (!family || (afi != AFI_IP && afi != AFI_IP6)) {
1579 vnc_zlog_debug_verbose("%s: bad afi: %d", __func__, afi);
1580 return;
1581 }
1582
1583 for (it = bgp->rfapi->imports; it; it = it->next) {
1584
1585 struct list *nve_list = NULL;
1586
1587 import_table_to_nve_list_direct_bgp(bgp, it, &nve_list, family);
1588
1589 if (nve_list) {
1590 vnc_direct_bgp_unexport_table(
1591 afi, it->imported_vpn[afi], nve_list);
1592 list_delete(&nve_list);
1593 }
1594 }
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
1611 * TBD do we need to check bpi->type and bpi->sub_type here, or does
1612 * caller do it?
1613 */
1614 void vnc_direct_bgp_rh_add_route(struct bgp *bgp, afi_t afi,
1615 const struct prefix *prefix, struct peer *peer,
1616 struct attr *attr)
1617 {
1618 struct vnc_export_info *eti;
1619 struct attr hattr;
1620 struct rfapi_cfg *hc;
1621 struct attr *iattr;
1622
1623 if (!afi) {
1624 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of route node",
1625 __func__);
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) {
1666 struct bgp_path_info info;
1667 route_map_result_t ret;
1668
1669 memset(&info, 0, sizeof(info));
1670 info.peer = peer;
1671 info.attr = &hattr;
1672 ret = route_map_apply(hc->routemap_export_bgp, prefix, &info);
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
1691 /*
1692 * export expiration timer is already running on
1693 * this route: cancel it
1694 */
1695 THREAD_OFF(eti->timer);
1696
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 */
1702 NULL, /* tag not used for unicast, EVPN neither */
1703 0, 0, NULL); /* EVPN not used */
1704 bgp_attr_unintern(&iattr);
1705 }
1706
1707 static void vncExportWithdrawTimer(struct thread *t)
1708 {
1709 struct vnc_export_info *eti = THREAD_ARG(t);
1710 const struct prefix *p = agg_node_get_prefix(eti->node);
1711
1712 /*
1713 * withdraw the route
1714 */
1715 bgp_withdraw(eti->peer, p, 0, /* addpath_id */
1716 family2afi(p->family), SAFI_UNICAST, eti->type,
1717 eti->subtype, NULL, /* RD not used for unicast */
1718 NULL, 0,
1719 NULL); /* tag not used for unicast, EVPN neither */
1720
1721 /*
1722 * Free the eti
1723 */
1724 vnc_eti_delete(eti);
1725 }
1726
1727 /*
1728 * "Withdrawing a Route" export process
1729 * TBD do we need to check bpi->type and bpi->sub_type here, or does
1730 * caller do it?
1731 */
1732 void vnc_direct_bgp_rh_del_route(struct bgp *bgp, afi_t afi,
1733 const struct prefix *prefix, struct peer *peer)
1734 {
1735 struct vnc_export_info *eti;
1736
1737 if (!afi) {
1738 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi route node",
1739 __func__);
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 }
1774 }
1775
1776
1777 void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi)
1778 {
1779 struct prefix_rd prd;
1780 struct bgp_dest *pdest;
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 */
1810 for (pdest = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); pdest;
1811 pdest = bgp_route_next(pdest)) {
1812
1813 struct bgp_table *table;
1814 struct bgp_dest *dest;
1815 struct bgp_path_info *ri;
1816 const struct prefix *pdest_p = bgp_dest_get_prefix(pdest);
1817
1818 memset(&prd, 0, sizeof(prd));
1819 prd.family = AF_UNSPEC;
1820 prd.prefixlen = 64;
1821 memcpy(prd.val, pdest_p->u.val, 8);
1822
1823 /* This is the per-RD table of prefixes */
1824 table = bgp_dest_get_bgp_table_info(pdest);
1825
1826 if (!table)
1827 continue;
1828
1829 for (dest = bgp_table_top(table); dest;
1830 dest = bgp_route_next(dest)) {
1831 const struct prefix *dest_p;
1832
1833 /*
1834 * skip prefix list check if no routes here
1835 */
1836 if (!bgp_dest_has_bgp_path_info_data(dest))
1837 continue;
1838
1839 vnc_zlog_debug_verbose("%s: checking prefix %pBD",
1840 __func__, dest);
1841
1842 dest_p = bgp_dest_get_prefix(dest);
1843
1844 /*
1845 * prefix list check
1846 */
1847 if (hc->plist_export_bgp[afi]) {
1848 if (prefix_list_apply(hc->plist_export_bgp[afi],
1849 dest_p)
1850 == PREFIX_DENY) {
1851
1852 vnc_zlog_debug_verbose(
1853 "%s: prefix list says DENY",
1854 __func__);
1855 continue;
1856 }
1857 }
1858
1859 for (ri = bgp_dest_get_bgp_path_info(dest); ri;
1860 ri = ri->next) {
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) {
1886 struct bgp_path_info info;
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,
1894 dest_p, &info);
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(
1913 bgp, EXPORT_TYPE_BGP, dest_p,
1914 ri->peer,
1915 ZEBRA_ROUTE_VNC_DIRECT_RH,
1916 BGP_ROUTE_REDISTRIBUTE);
1917 rfapiGetVncLifetime(ri->attr,
1918 &eti->lifetime);
1919
1920 /*
1921 * export expiration timer is
1922 * already running on
1923 * this route: cancel it
1924 */
1925 THREAD_OFF(eti->timer);
1926
1927 vnc_zlog_debug_verbose(
1928 "%s: calling bgp_update",
1929 __func__);
1930
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 */
1944
1945 bgp_attr_unintern(&iattr);
1946 }
1947 }
1948 }
1949 }
1950 }
1951
1952 void vnc_direct_bgp_rh_vpn_disable(struct bgp *bgp, afi_t afi)
1953 {
1954 struct bgp_dest *dest;
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 */
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);
1973 struct bgp_path_info *ri;
1974 struct bgp_path_info *next;
1975
1976 for (ri = bgp_dest_get_bgp_path_info(dest), next = NULL; ri;
1977 ri = next) {
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(
1990 bgp, EXPORT_TYPE_BGP, dest_p, ri->peer,
1991 ZEBRA_ROUTE_VNC_DIRECT_RH,
1992 BGP_ROUTE_REDISTRIBUTE);
1993 if (eti) {
1994 THREAD_OFF(eti->timer);
1995 vnc_eti_delete(eti);
1996 }
1997
1998 bgp_withdraw(ri->peer, dest_p, /* prefix */
1999 0, /* addpath_id */
2000 AFI_IP, SAFI_UNICAST,
2001 ZEBRA_ROUTE_VNC_DIRECT_RH,
2002 BGP_ROUTE_REDISTRIBUTE,
2003 NULL, /* RD not used for unicast */
2004 NULL, 0, NULL); /* tag not used for
2005 unicast, EVPN
2006 neither */
2007 }
2008 }
2009 }
2010 }
2011
2012 void vnc_direct_bgp_rh_reexport(struct bgp *bgp, afi_t afi)
2013 {
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 }
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 */
2029 void vnc_export_bgp_enable(struct bgp *bgp, afi_t afi)
2030 {
2031 if (!bgp->rfapi_cfg)
2032 return;
2033
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 }
2050 }
2051
2052 void vnc_export_bgp_disable(struct bgp *bgp, afi_t afi)
2053 {
2054 if (!bgp->rfapi_cfg)
2055 return;
2056
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 }
2073 }
2074
2075 void vnc_export_bgp_prechange(struct bgp *bgp)
2076 {
2077 vnc_export_bgp_disable(bgp, AFI_IP);
2078 vnc_export_bgp_disable(bgp, AFI_IP6);
2079 }
2080
2081 void vnc_export_bgp_postchange(struct bgp *bgp)
2082 {
2083 vnc_export_bgp_enable(bgp, AFI_IP);
2084 vnc_export_bgp_enable(bgp, AFI_IP6);
2085 }
2086
2087 void vnc_direct_bgp_reexport(struct bgp *bgp, afi_t afi)
2088 {
2089 vnc_export_bgp_disable(bgp, afi);
2090 vnc_export_bgp_enable(bgp, afi);
2091 }