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