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