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