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