]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/rfapi/vnc_import_bgp.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / bgpd / rfapi / vnc_import_bgp.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 *
4 * Copyright 2009-2016, LabN Consulting, L.L.C.
5 *
6 */
7
8 /*
9 * File: vnc_import_bgp.c
10 * Purpose: Import routes from BGP unicast directly (not via zebra)
11 */
12
13 #include "lib/zebra.h"
14 #include "lib/prefix.h"
15 #include "lib/agg_table.h"
16 #include "lib/vty.h"
17 #include "lib/log.h"
18 #include "lib/memory.h"
19 #include "lib/linklist.h"
20 #include "lib/plist.h"
21 #include "lib/routemap.h"
22 #include "lib/lib_errors.h"
23
24 #include "bgpd/bgpd.h"
25 #include "bgpd/bgp_ecommunity.h"
26 #include "bgpd/bgp_attr.h"
27 #include "bgpd/bgp_route.h"
28 #include "bgpd/bgp_mplsvpn.h" /* for RD_TYPE_IP */
29
30 #include "bgpd/rfapi/vnc_export_bgp.h"
31 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
32 #include "bgpd/rfapi/rfapi.h"
33 #include "bgpd/rfapi/rfapi_import.h"
34 #include "bgpd/rfapi/rfapi_private.h"
35 #include "bgpd/rfapi/rfapi_monitor.h"
36 #include "bgpd/rfapi/rfapi_vty.h"
37 #include "bgpd/rfapi/vnc_import_bgp.h"
38 #include "bgpd/rfapi/vnc_import_bgp_p.h"
39 #include "bgpd/rfapi/vnc_debug.h"
40
41 #define ENABLE_VNC_RHNCK
42
43 #define DEBUG_RHN_LIST 0
44
45 static struct rfapi_descriptor vncHDBgpDirect; /* dummy nve descriptor */
46 static struct rfapi_descriptor vncHDResolveNve; /* dummy nve descriptor */
47
48 /*
49 * For routes from another AS:
50 *
51 * If MED is set,
52 * LOCAL_PREF = 255 - MIN(255, MED)
53 * else
54 * LOCAL_PREF = default_local_pref
55 *
56 * For routes from the same AS:
57 *
58 * LOCAL_PREF unchanged
59 */
60 uint32_t calc_local_pref(struct attr *attr, struct peer *peer)
61 {
62 uint32_t local_pref = 0;
63
64 if (!attr) {
65 if (peer) {
66 return peer->bgp->default_local_pref;
67 }
68 return bgp_get_default()->default_local_pref;
69 }
70
71 if (peer && (peer->as != peer->bgp->as)) {
72 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
73 if (attr->med > 255) {
74 local_pref = 0;
75 } else {
76 local_pref = 255 - attr->med;
77 }
78 } else {
79 local_pref = peer->bgp->default_local_pref;
80 }
81 } else {
82 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
83 local_pref = attr->local_pref;
84 } else {
85 if (peer && peer->bgp) {
86 local_pref = peer->bgp->default_local_pref;
87 }
88 }
89 }
90
91 return local_pref;
92 }
93
94 static int is_host_prefix(const struct prefix *p)
95 {
96 switch (p->family) {
97 case AF_INET:
98 return (p->prefixlen == IPV4_MAX_BITLEN);
99 case AF_INET6:
100 return (p->prefixlen == IPV6_MAX_BITLEN);
101 }
102 return 0;
103 }
104
105 /***********************************************************************
106 * RHN list
107 ***********************************************************************/
108
109 struct prefix_bag {
110 struct prefix hpfx; /* ce address = unicast nexthop */
111 struct prefix upfx; /* unicast prefix */
112 struct bgp_path_info *ubpi; /* unicast route */
113 };
114
115 static const uint8_t maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
116 0xf8, 0xfc, 0xfe, 0xff};
117
118 int vnc_prefix_cmp(const void *pfx1, const void *pfx2)
119 {
120 int offset;
121 int shift;
122 uint8_t mask;
123
124 const struct prefix *p1 = pfx1;
125 const struct prefix *p2 = pfx2;
126
127 if (p1->family < p2->family)
128 return -1;
129 if (p1->family > p2->family)
130 return 1;
131
132 if (p1->prefixlen < p2->prefixlen)
133 return -1;
134 if (p1->prefixlen > p2->prefixlen)
135 return 1;
136
137 offset = p1->prefixlen / 8;
138 shift = p1->prefixlen % 8;
139 if (shift == 0 && offset) { /* catch aligned case */
140 offset--;
141 shift = 8;
142 }
143
144 /* Set both prefix's head pointer. */
145 const uint8_t *pp1 = (const uint8_t *)&p1->u.prefix;
146 const uint8_t *pp2 = (const uint8_t *)&p2->u.prefix;
147
148 while (offset--) {
149 if (*pp1 < *pp2)
150 return -1;
151 if (*pp1 > *pp2)
152 return 1;
153 ++pp1;
154 ++pp2;
155 }
156
157 mask = maskbit[shift];
158 if ((*pp1 & mask) < (*pp2 & mask))
159 return -1;
160 if ((*pp1 & mask) > (*pp2 & mask))
161 return 1;
162
163 return 0;
164 }
165
166 static void prefix_bag_free(void *pb)
167 {
168 XFREE(MTYPE_RFAPI_PREFIX_BAG, pb);
169 }
170
171 #if DEBUG_RHN_LIST
172 static void print_rhn_list(const char *tag1, const char *tag2)
173 {
174 struct bgp *bgp;
175 struct skiplist *sl;
176 struct skiplistnode *p;
177 struct prefix_bag *pb;
178 int count = 0;
179
180 bgp = bgp_get_default();
181 if (!bgp)
182 return;
183
184 sl = bgp->frapi->resolve_nve_nexthop;
185 if (!sl) {
186 vnc_zlog_debug_verbose("%s: %s: RHN List is empty",
187 (tag1 ? tag1 : ""), (tag2 ? tag2 : ""));
188 return;
189 }
190
191 vnc_zlog_debug_verbose("%s: %s: RHN list:", (tag1 ? tag1 : ""),
192 (tag2 ? tag2 : ""));
193
194 /* XXX uses secret knowledge of skiplist structure */
195 for (p = sl->header->forward[0]; p; p = p->forward[0]) {
196 pb = p->value;
197
198 vnc_zlog_debug_verbose(
199 "RHN Entry %d (q=%p): kpfx=%pFX, upfx=%pFX, hpfx=%pFX, ubpi=%p",
200 ++count, p, p->key, &pb->upfx, &pb->hpfx, pb->ubpi);
201 }
202 }
203 #endif
204
205 #ifdef ENABLE_VNC_RHNCK
206 static void vnc_rhnck(char *tag)
207 {
208 struct bgp *bgp;
209 struct skiplist *sl;
210 struct skiplistnode *p;
211
212 bgp = bgp_get_default();
213 if (!bgp)
214 return;
215 sl = bgp->rfapi->resolve_nve_nexthop;
216
217 if (!sl)
218 return;
219
220 /* XXX uses secret knowledge of skiplist structure */
221 for (p = sl->header->forward[0]; p; p = p->forward[0]) {
222 struct prefix_bag *pb;
223 struct prefix *pkey;
224 afi_t afi;
225 struct prefix pfx_orig_nexthop;
226
227 memset(&pfx_orig_nexthop, 0,
228 sizeof(pfx_orig_nexthop)); /* keep valgrind happy */
229
230 pkey = p->key;
231 pb = p->value;
232
233 afi = family2afi(pb->upfx.family);
234
235 rfapiUnicastNexthop2Prefix(afi, pb->ubpi->attr,
236 &pfx_orig_nexthop);
237
238 /* pb->hpfx, pb->ubpi nexthop, pkey should all reflect the same
239 * pfx */
240 assert(!vnc_prefix_cmp(&pb->hpfx, pkey));
241 if (vnc_prefix_cmp(&pb->hpfx, &pfx_orig_nexthop)) {
242 vnc_zlog_debug_verbose(
243 "%s: %s: FATAL: resolve_nve_nexthop list item bpi nexthop %pFX != nve pfx %pFX",
244 __func__, tag, &pfx_orig_nexthop, &pb->hpfx);
245 assert(0);
246 }
247 }
248 vnc_zlog_debug_verbose("%s: vnc_rhnck OK", tag);
249 }
250
251 #define VNC_RHNCK(n) \
252 do { \
253 char buf[BUFSIZ]; \
254 snprintf(buf, sizeof(buf), "%s: %s", __func__, #n); \
255 vnc_rhnck(buf); \
256 } while (0)
257
258 #else
259
260 #define VNC_RHNCK(n)
261
262 #endif
263
264 /***********************************************************************
265 * Add/Delete Unicast Route
266 ***********************************************************************/
267
268 /*
269 * "Adding a Route" import process
270 */
271
272 /*
273 * extract and package information from the BGP unicast route.
274 * Return code 0 means OK, non-0 means drop.
275 *
276 * If return code is 0, caller MUST release ecom
277 */
278 static int process_unicast_route(struct bgp *bgp, /* in */
279 afi_t afi, /* in */
280 const struct prefix *prefix, /* in */
281 struct bgp_path_info *info, /* in */
282 struct ecommunity **ecom, /* OUT */
283 struct prefix *unicast_nexthop) /* OUT */
284 {
285 struct rfapi_cfg *hc = bgp->rfapi_cfg;
286 struct peer *peer = info->peer;
287 struct attr *attr = info->attr;
288 struct attr hattr;
289 struct route_map *rmap = NULL;
290 struct prefix pfx_orig_nexthop;
291
292 memset(&pfx_orig_nexthop, 0,
293 sizeof(pfx_orig_nexthop)); /* keep valgrind happy */
294
295 /*
296 * prefix list check
297 */
298 if (hc->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi]) {
299 vnc_zlog_debug_verbose("%s: HC prefix list is set, checking",
300 __func__);
301 if (prefix_list_apply(
302 hc->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi],
303 prefix)
304 == PREFIX_DENY) {
305 vnc_zlog_debug_verbose(
306 "%s: prefix list returns DENY, blocking route",
307 __func__);
308 return -1;
309 }
310 vnc_zlog_debug_verbose(
311 "%s: prefix list returns PASS, allowing route",
312 __func__);
313 }
314
315 /* apply routemap, if any, later */
316 rmap = hc->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT];
317
318 /*
319 * Extract original nexthop, which we expect to be a NVE connected
320 * router
321 * Note that this is the nexthop before any possible application of
322 * policy
323 */
324 /*
325 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
326 * but if v4 it is in attr->nexthop
327 */
328 rfapiUnicastNexthop2Prefix(afi, attr, &pfx_orig_nexthop);
329
330 /*
331 * route map handling
332 * This code is here because it allocates an interned attr which
333 * must be freed before we return. It's easier to put it after
334 * all of the possible returns above.
335 */
336 memset(&hattr, 0, sizeof(hattr));
337 /* hattr becomes a ghost attr */
338 hattr = *attr;
339
340 if (rmap) {
341 struct bgp_path_info info;
342 route_map_result_t ret;
343
344 memset(&info, 0, sizeof(info));
345 info.peer = peer;
346 info.attr = &hattr;
347 ret = route_map_apply(rmap, prefix, &info);
348 if (ret == RMAP_DENYMATCH) {
349 bgp_attr_flush(&hattr);
350 vnc_zlog_debug_verbose(
351 "%s: route map \"%s\" says DENY, returning",
352 __func__, rmap->name);
353 return -1;
354 }
355 }
356
357 /*
358 * Get the (possibly altered by policy) unicast nexthop
359 * for later lookup in the Import Table by caller
360 */
361 rfapiUnicastNexthop2Prefix(afi, &hattr, unicast_nexthop);
362
363 if (bgp_attr_get_ecommunity(&hattr))
364 *ecom = ecommunity_dup(bgp_attr_get_ecommunity(&hattr));
365 else
366 *ecom = ecommunity_new();
367
368 /*
369 * Done with hattr, clean up
370 */
371 bgp_attr_flush(&hattr);
372
373 /*
374 * Add EC that carries original NH of iBGP route (2 bytes = magic
375 * value indicating it came from an VNC gateway; default 5226, but
376 * must be user configurable). Note that this is the nexthop before
377 * any application of policy.
378 */
379 {
380 struct ecommunity_val vnc_gateway_magic;
381 uint16_t localadmin;
382
383 /* Using route origin extended community type */
384 memset(&vnc_gateway_magic, 0, sizeof(vnc_gateway_magic));
385 vnc_gateway_magic.val[0] = 0x01;
386 vnc_gateway_magic.val[1] = 0x03;
387
388 /* Only works for IPv4 nexthops */
389 if (prefix->family == AF_INET) {
390 memcpy(vnc_gateway_magic.val + 2,
391 &unicast_nexthop->u.prefix4, 4);
392 }
393 localadmin = htons(hc->resolve_nve_roo_local_admin);
394 memcpy(vnc_gateway_magic.val + 6, (char *)&localadmin, 2);
395
396 ecommunity_add_val(*ecom, &vnc_gateway_magic, false, false);
397 }
398
399 return 0;
400 }
401
402
403 static void vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
404 struct bgp *bgp, afi_t afi, struct bgp_path_info *bpi, /* VPN bpi */
405 struct prefix_rd *prd, /* RD */
406 const struct prefix *prefix, /* unicast route prefix */
407 uint32_t *local_pref, /* NULL = no local_pref */
408 uint32_t *med, /* NULL = no med */
409 struct ecommunity *ecom) /* generated ecoms */
410 {
411 struct prefix un;
412 struct prefix nexthop;
413 struct rfapi_ip_addr nexthop_h;
414 uint32_t lifetime;
415 uint32_t *plifetime;
416 struct bgp_attr_encap_subtlv *encaptlvs;
417 uint32_t label = 0;
418
419 struct rfapi_un_option optary[3];
420 struct rfapi_un_option *opt = NULL;
421 int cur_opt = 0;
422
423 vnc_zlog_debug_verbose("%s: entry", __func__);
424
425 if (bpi->type != ZEBRA_ROUTE_BGP
426 && bpi->type != ZEBRA_ROUTE_BGP_DIRECT) {
427
428 return;
429 }
430 if (bpi->sub_type != BGP_ROUTE_NORMAL
431 && bpi->sub_type != BGP_ROUTE_STATIC
432 && bpi->sub_type != BGP_ROUTE_RFP) {
433
434 return;
435 }
436 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
437 return;
438
439 vncHDResolveNve.peer = bpi->peer;
440 if (!rfapiGetVncTunnelUnAddr(bpi->attr, &un)) {
441 if (rfapiQprefix2Raddr(&un, &vncHDResolveNve.un_addr))
442 return;
443 } else {
444 memset(&vncHDResolveNve.un_addr, 0,
445 sizeof(vncHDResolveNve.un_addr));
446 }
447
448 /* Use nexthop of VPN route as nexthop of constructed route */
449 rfapiNexthop2Prefix(bpi->attr, &nexthop);
450 rfapiQprefix2Raddr(&nexthop, &nexthop_h);
451
452 if (rfapiGetVncLifetime(bpi->attr, &lifetime)) {
453 plifetime = NULL;
454 } else {
455 plifetime = &lifetime;
456 }
457
458 encaptlvs = bgp_attr_get_vnc_subtlvs(bpi->attr);
459 if (bpi->attr->encap_tunneltype != BGP_ENCAP_TYPE_RESERVED
460 && bpi->attr->encap_tunneltype != BGP_ENCAP_TYPE_MPLS) {
461 opt = &optary[cur_opt++];
462 memset(opt, 0, sizeof(struct rfapi_un_option));
463 opt->type = RFAPI_UN_OPTION_TYPE_TUNNELTYPE;
464 opt->v.tunnel.type = bpi->attr->encap_tunneltype;
465 /* TBD parse bpi->attr->extra->encap_subtlvs */
466 }
467
468 struct ecommunity *new_ecom = ecommunity_dup(ecom);
469
470 if (bgp_attr_get_ecommunity(bpi->attr))
471 ecommunity_merge(new_ecom, bgp_attr_get_ecommunity(bpi->attr));
472
473 if (bpi->extra)
474 label = decode_label(&bpi->extra->label[0]);
475
476 add_vnc_route(&vncHDResolveNve, bgp, SAFI_MPLS_VPN,
477 prefix, /* unicast route prefix */
478 prd, &nexthop_h, /* new nexthop */
479 local_pref, plifetime,
480 (struct bgp_tea_options *)encaptlvs, /* RFP options */
481 opt, NULL, new_ecom, med, /* NULL => don't set med */
482 (label ? &label : NULL), /* NULL= default */
483 ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE,
484 RFAPI_AHR_RFPOPT_IS_VNCTLV); /* flags */
485
486 ecommunity_free(&new_ecom);
487 }
488
489 static void vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
490 struct prefix_rd *prd, /* RD */
491 struct bgp_table *table_rd, /* per-rd VPN route table */
492 afi_t afi, struct bgp *bgp,
493 const struct prefix *prefix, /* unicast prefix */
494 struct ecommunity *ecom, /* generated ecoms */
495 uint32_t *local_pref, /* NULL = no local_pref */
496 uint32_t *med, /* NULL = no med */
497 struct prefix *ubpi_nexthop) /* unicast nexthop */
498 {
499 struct bgp_dest *bd;
500 struct bgp_path_info *bpi;
501
502 if (!table_rd)
503 return;
504
505 vnc_zlog_debug_verbose("%s: ubpi_nexthop=%pFX", __func__, ubpi_nexthop);
506
507 /* exact match */
508 bd = bgp_node_lookup(table_rd, ubpi_nexthop);
509 if (!bd) {
510 vnc_zlog_debug_verbose(
511 "%s: no match in RD's table for ubpi_nexthop",
512 __func__);
513 return;
514 }
515
516 /* Iterate over bgp_info items at this node */
517 for (bpi = bgp_dest_get_bgp_path_info(bd); bpi; bpi = bpi->next) {
518
519 vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
520 bgp, afi, bpi, /* VPN bpi */
521 prd, prefix, local_pref, med, ecom);
522 }
523
524 bgp_dest_unlock_node(bd);
525 }
526
527 static void vnc_import_bgp_add_route_mode_resolve_nve(
528 struct bgp *bgp, const struct prefix *prefix, /* unicast prefix */
529 struct bgp_path_info *info) /* unicast info */
530 {
531 afi_t afi = family2afi(prefix->family);
532
533 struct prefix pfx_unicast_nexthop = {0}; /* happy valgrind */
534
535 struct ecommunity *ecom = NULL;
536 uint32_t local_pref;
537 uint32_t *med = NULL;
538
539 struct prefix_bag *pb;
540 struct bgp_dest *bdp; /* prd table node */
541
542 /*debugging */
543 if (VNC_DEBUG(VERBOSE)) {
544 char str_nh[PREFIX_STRLEN];
545 struct prefix nh;
546
547 nh.prefixlen = 0;
548 rfapiUnicastNexthop2Prefix(afi, info->attr, &nh);
549 if (nh.prefixlen) {
550 prefix2str(&nh, str_nh, sizeof(str_nh));
551 } else {
552 str_nh[0] = '?';
553 str_nh[1] = 0;
554 }
555
556 vnc_zlog_debug_verbose(
557 "%s(bgp=%p, unicast prefix=%pFX, unicast nh=%s)",
558 __func__, bgp, prefix, str_nh);
559 }
560
561 if (info->type != ZEBRA_ROUTE_BGP) {
562 vnc_zlog_debug_verbose(
563 "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
564 __func__, info->type, zebra_route_string(info->type),
565 ZEBRA_ROUTE_BGP, "ZEBRA_ROUTE_BGP");
566 return;
567 }
568
569 /*
570 * Preliminary checks
571 */
572
573 if (!afi) {
574 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of prefix",
575 __func__);
576 return;
577 }
578
579 if (!(bgp->rfapi_cfg)) {
580 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
581 __func__);
582 return;
583 }
584
585 /* check vnc redist flag for bgp direct routes */
586 if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
587 vnc_zlog_debug_verbose(
588 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
589 __func__, afi);
590 return;
591 }
592
593
594 if (process_unicast_route(bgp, afi, prefix, info, &ecom,
595 &pfx_unicast_nexthop)) {
596
597 vnc_zlog_debug_verbose(
598 "%s: process_unicast_route error, skipping", __func__);
599 return;
600 }
601
602 local_pref = calc_local_pref(info->attr, info->peer);
603 if (info->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
604 med = &info->attr->med;
605
606 /*
607 * At this point, we have allocated:
608 *
609 * ecom ecommunity ptr, union of unicast and ROO parts (no NVE part)
610 *
611 * And we have set:
612 *
613 * pfx_unicast_nexthop nexthop of uncast route
614 */
615
616 if (!bgp->rfapi->resolve_nve_nexthop) {
617 bgp->rfapi->resolve_nve_nexthop =
618 skiplist_new(SKIPLIST_FLAG_ALLOW_DUPLICATES,
619 vnc_prefix_cmp, prefix_bag_free);
620 }
621
622 pb = XCALLOC(MTYPE_RFAPI_PREFIX_BAG, sizeof(struct prefix_bag));
623 pb->hpfx = pfx_unicast_nexthop;
624 pb->ubpi = info;
625 pb->upfx = *prefix;
626
627 bgp_path_info_lock(info); /* skiplist refers to it */
628 skiplist_insert(bgp->rfapi->resolve_nve_nexthop, &pb->hpfx, pb);
629
630 /*
631 * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
632 * (exact match, /32). If an exact match is found, call add_vnc_route.
633 */
634
635 for (bdp = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); bdp;
636 bdp = bgp_route_next(bdp)) {
637
638 struct bgp_table *table;
639
640 table = bgp_dest_get_bgp_table_info(bdp);
641
642 if (!table)
643 continue;
644
645 vnc_import_bgp_add_route_mode_resolve_nve_one_rd(
646 (struct prefix_rd *)bgp_dest_get_prefix(bdp), table,
647 afi, bgp, prefix, ecom, &local_pref, med,
648 &pfx_unicast_nexthop);
649 }
650
651
652 if (ecom)
653 ecommunity_free(&ecom);
654
655 vnc_zlog_debug_verbose("%s: done", __func__);
656 }
657
658
659 static void vnc_import_bgp_add_route_mode_plain(struct bgp *bgp,
660 const struct prefix *prefix,
661 struct bgp_path_info *info)
662 {
663 afi_t afi = family2afi(prefix->family);
664 struct peer *peer = info->peer;
665 struct attr *attr = info->attr;
666 struct attr hattr;
667 struct rfapi_cfg *hc = bgp->rfapi_cfg;
668 struct attr *iattr = NULL;
669
670 struct rfapi_ip_addr vnaddr;
671 struct prefix vn_pfx_space;
672 struct prefix *vn_pfx = NULL;
673 int ahr_flags = 0;
674 struct ecommunity *ecom = NULL;
675 struct prefix_rd prd;
676 struct route_map *rmap = NULL;
677 uint32_t local_pref;
678 uint32_t *med = NULL;
679
680 vnc_zlog_debug_verbose("%s(prefix=%pFX) entry", __func__, prefix);
681
682 if (!afi) {
683 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of prefix",
684 __func__);
685 return;
686 }
687
688 if (!hc) {
689 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
690 __func__);
691 return;
692 }
693
694 /* check vnc redist flag for bgp direct routes */
695 if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
696 vnc_zlog_debug_verbose(
697 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
698 __func__, afi);
699 return;
700 }
701
702 /*
703 * mode "plain" specific code
704 */
705 {
706 vnc_zlog_debug_verbose("%s: NOT using redist RFG", __func__);
707
708 /*
709 * prefix list check
710 */
711 if (hc->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi]) {
712 vnc_zlog_debug_verbose(
713 "%s: HC prefix list is set, checking",
714 __func__);
715 if (prefix_list_apply(
716 hc->plist_redist[ZEBRA_ROUTE_BGP_DIRECT]
717 [afi],
718 prefix)
719 == PREFIX_DENY) {
720 vnc_zlog_debug_verbose(
721 "%s: prefix list returns DENY, blocking route",
722 __func__);
723 return;
724 }
725 vnc_zlog_debug_verbose(
726 "%s: prefix list returns PASS, allowing route",
727 __func__);
728 }
729
730 /* apply routemap, if any, later */
731 rmap = hc->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT];
732
733 /*
734 * Incoming prefix is unicast. If v6, it is in multiprotocol
735 * area,
736 * but if v4 it is in attr->nexthop
737 */
738 rfapiUnicastNexthop2Prefix(afi, attr, &vn_pfx_space);
739 vn_pfx = &vn_pfx_space;
740
741 /* UN address */
742 ahr_flags |= RFAPI_AHR_NO_TUNNEL_SUBTLV;
743 }
744
745 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE))
746 vnc_zlog_debug_any("%s vn_pfx=%pFX", __func__, vn_pfx);
747
748 /*
749 * Compute VN address
750 */
751 if (rfapiQprefix2Raddr(vn_pfx, &vnaddr)) {
752 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
753 __func__);
754 return;
755 }
756
757 /*
758 * route map handling
759 * This code is here because it allocates an interned attr which
760 * must be freed before we return. It's easier to put it after
761 * all of the possible returns above.
762 */
763 memset(&hattr, 0, sizeof(hattr));
764 /* hattr becomes a ghost attr */
765 hattr = *attr;
766
767 if (rmap) {
768 struct bgp_path_info info;
769 route_map_result_t ret;
770
771 memset(&info, 0, sizeof(info));
772 info.peer = peer;
773 info.attr = &hattr;
774 ret = route_map_apply(rmap, prefix, &info);
775 if (ret == RMAP_DENYMATCH) {
776 bgp_attr_flush(&hattr);
777 vnc_zlog_debug_verbose(
778 "%s: route map \"%s\" says DENY, returning",
779 __func__, rmap->name);
780 return;
781 }
782 }
783
784 iattr = bgp_attr_intern(&hattr);
785 bgp_attr_flush(&hattr);
786
787 /* Now iattr is an allocated interned attr */
788
789 /*
790 * Mode "plain" specific code
791 *
792 * Sets RD in dummy HD
793 * Allocates ecom
794 */
795 {
796 if (vnaddr.addr_family != AF_INET) {
797 vnc_zlog_debug_verbose(
798 "%s: can't auto-assign RD, VN AF (%d) is not IPv4, skipping",
799 __func__, vnaddr.addr_family);
800 if (iattr) {
801 bgp_attr_unintern(&iattr);
802 }
803 return;
804 }
805 memset(&prd, 0, sizeof(prd));
806 rfapi_set_autord_from_vn(&prd, &vnaddr);
807
808 if (iattr && bgp_attr_get_ecommunity(iattr))
809 ecom = ecommunity_dup(bgp_attr_get_ecommunity(iattr));
810 }
811
812 local_pref = calc_local_pref(iattr, peer);
813
814 if (iattr && (iattr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))) {
815 med = &iattr->med;
816 }
817
818 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE)) {
819 char buf[PREFIX_STRLEN];
820
821 rfapiRfapiIpAddr2Str(&vnaddr, buf, sizeof(buf));
822 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__, buf);
823 }
824
825 vncHDBgpDirect.peer = peer;
826 add_vnc_route(&vncHDBgpDirect, bgp, SAFI_MPLS_VPN, prefix, &prd,
827 &vnaddr, &local_pref, &(bgp->rfapi_cfg->redist_lifetime),
828 NULL, /* RFP options */
829 NULL, NULL, ecom, med, /* med */
830 NULL, /* label: default */
831 ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE,
832 ahr_flags);
833 vncHDBgpDirect.peer = NULL;
834
835 if (ecom)
836 ecommunity_free(&ecom);
837 }
838
839 static void vnc_import_bgp_add_route_mode_nvegroup(
840 struct bgp *bgp, const struct prefix *prefix,
841 struct bgp_path_info *info, struct rfapi_nve_group_cfg *rfg)
842 {
843 afi_t afi = family2afi(prefix->family);
844 struct peer *peer = info->peer;
845 struct attr *attr = info->attr;
846 struct attr hattr;
847 struct attr *iattr = NULL;
848
849 struct rfapi_ip_addr vnaddr;
850 struct prefix *vn_pfx = NULL;
851 int ahr_flags = 0;
852 struct ecommunity *ecom = NULL;
853 struct prefix_rd prd;
854 struct route_map *rmap = NULL;
855 uint32_t local_pref;
856
857 vnc_zlog_debug_verbose("%s(prefix=%pFX) entry", __func__, prefix);
858
859 assert(rfg);
860
861 if (!afi) {
862 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of prefix",
863 __func__);
864 return;
865 }
866
867 if (!(bgp->rfapi_cfg)) {
868 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
869 __func__);
870 return;
871 }
872
873 /* check vnc redist flag for bgp direct routes */
874 if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
875 vnc_zlog_debug_verbose(
876 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
877 __func__, afi);
878 return;
879 }
880
881
882 /*
883 * RFG-specific code
884 */
885 {
886
887 struct rfapi_ip_prefix pfx_un;
888
889 vnc_zlog_debug_verbose("%s: using redist RFG", __func__);
890
891 /*
892 * RFG prefix list check
893 */
894 if (rfg->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi]) {
895 vnc_zlog_debug_verbose(
896 "%s: RFG prefix list is set, checking",
897 __func__);
898 if (prefix_list_apply(
899 rfg->plist_redist[ZEBRA_ROUTE_BGP_DIRECT]
900 [afi],
901 prefix)
902 == PREFIX_DENY) {
903 vnc_zlog_debug_verbose(
904 "%s: prefix list returns DENY, blocking route",
905 __func__);
906 return;
907 }
908 vnc_zlog_debug_verbose(
909 "%s: prefix list returns PASS, allowing route",
910 __func__);
911 }
912
913 /* apply routemap, if any, later */
914 rmap = rfg->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT];
915
916 /*
917 * export nve group's VN addr prefix must be a /32 which
918 * will yield the VN addr to use
919 */
920 vn_pfx = &rfg->vn_prefix;
921
922 /*
923 * UN Address
924 */
925 if (!is_host_prefix(&rfg->un_prefix)) {
926 /* NB prefixlen==0 means it has not been configured */
927 vnc_zlog_debug_verbose(
928 "%s: redist RFG UN pfx not host pfx (plen=%d), skipping",
929 __func__, rfg->un_prefix.prefixlen);
930 return;
931 }
932
933 rfapiQprefix2Rprefix(&rfg->un_prefix, &pfx_un);
934
935 vncHDBgpDirect.un_addr = pfx_un.prefix;
936 }
937
938 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE))
939 vnc_zlog_debug_any("%s vn_pfx=%pFX", __func__, vn_pfx);
940
941 /*
942 * Compute VN address
943 */
944 if (rfapiQprefix2Raddr(vn_pfx, &vnaddr)) {
945 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
946 __func__);
947 return;
948 }
949
950 /*
951 * route map handling
952 * This code is here because it allocates an interned attr which
953 * must be freed before we return. It's easier to put it after
954 * all of the possible returns above.
955 */
956 memset(&hattr, 0, sizeof(hattr));
957 /* hattr becomes a ghost attr */
958 hattr = *attr;
959
960 if (rmap) {
961 struct bgp_path_info path;
962 route_map_result_t ret;
963
964 memset(&path, 0, sizeof(path));
965 path.peer = peer;
966 path.attr = &hattr;
967 ret = route_map_apply(rmap, prefix, &path);
968 if (ret == RMAP_DENYMATCH) {
969 bgp_attr_flush(&hattr);
970 vnc_zlog_debug_verbose(
971 "%s: route map \"%s\" says DENY, returning",
972 __func__, rmap->name);
973 return;
974 }
975 }
976
977 iattr = bgp_attr_intern(&hattr);
978 bgp_attr_flush(&hattr);
979
980 /* Now iattr is an allocated interned attr */
981
982 /*
983 * RFG-specific code
984 *
985 * Sets RD in dummy HD
986 * Allocates ecom
987 */
988 {
989
990 memset(&prd, 0, sizeof(prd));
991 prd = rfg->rd;
992 prd.family = AF_UNSPEC;
993 prd.prefixlen = 64;
994
995 if (rfg->rd.family == AF_UNIX) {
996 rfapi_set_autord_from_vn(&prd, &vnaddr);
997 }
998
999 if (rfg->rt_export_list)
1000 ecom = ecommunity_dup(
1001 bgp->rfapi_cfg->rfg_redist->rt_export_list);
1002 else
1003 ecom = ecommunity_new();
1004
1005 if (iattr && bgp_attr_get_ecommunity(iattr))
1006 ecom = ecommunity_merge(ecom,
1007 bgp_attr_get_ecommunity(iattr));
1008 }
1009
1010 local_pref = calc_local_pref(iattr, peer);
1011
1012 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE)) {
1013 char buf[BUFSIZ];
1014
1015 buf[0] = 0;
1016 rfapiRfapiIpAddr2Str(&vnaddr, buf, BUFSIZ);
1017 buf[BUFSIZ - 1] = 0;
1018 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__, buf);
1019 }
1020
1021 vncHDBgpDirect.peer = peer;
1022 add_vnc_route(&vncHDBgpDirect, bgp, SAFI_MPLS_VPN, prefix, &prd,
1023 &vnaddr, &local_pref, &(bgp->rfapi_cfg->redist_lifetime),
1024 NULL, /* RFP options */
1025 NULL, NULL, ecom, NULL, /* med */
1026 NULL, /* label: default */
1027 ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE,
1028 ahr_flags);
1029 vncHDBgpDirect.peer = NULL;
1030
1031 if (ecom)
1032 ecommunity_free(&ecom);
1033 }
1034
1035 static void vnc_import_bgp_del_route_mode_plain(struct bgp *bgp,
1036 const struct prefix *prefix,
1037 struct bgp_path_info *info)
1038 {
1039 struct prefix_rd prd;
1040 afi_t afi = family2afi(prefix->family);
1041 struct prefix *vn_pfx = NULL;
1042 struct rfapi_ip_addr vnaddr;
1043 struct prefix vn_pfx_space;
1044
1045
1046 assert(afi);
1047
1048 /*
1049 * Compute VN address
1050 */
1051
1052 if (info) {
1053 rfapiUnicastNexthop2Prefix(afi, info->attr, &vn_pfx_space);
1054 } else {
1055 vnc_zlog_debug_verbose("%s: no attr, can't delete route",
1056 __func__);
1057 return;
1058 }
1059 vn_pfx = &vn_pfx_space;
1060
1061 vnaddr.addr_family = vn_pfx->family;
1062 switch (vn_pfx->family) {
1063 case AF_INET:
1064 if (vn_pfx->prefixlen != IPV4_MAX_BITLEN) {
1065 vnc_zlog_debug_verbose(
1066 "%s: redist VN plen (%d) != 32, skipping",
1067 __func__, vn_pfx->prefixlen);
1068 return;
1069 }
1070 vnaddr.addr.v4 = vn_pfx->u.prefix4;
1071 break;
1072
1073 case AF_INET6:
1074 if (vn_pfx->prefixlen != IPV6_MAX_BITLEN) {
1075 vnc_zlog_debug_verbose(
1076 "%s: redist VN plen (%d) != 128, skipping",
1077 __func__, vn_pfx->prefixlen);
1078 return;
1079 }
1080 vnaddr.addr.v6 = vn_pfx->u.prefix6;
1081 break;
1082
1083 default:
1084 vnc_zlog_debug_verbose(
1085 "%s: no redist RFG VN host pfx configured, skipping",
1086 __func__);
1087 return;
1088 }
1089
1090
1091 memset(&prd, 0, sizeof(prd));
1092 if (rfapi_set_autord_from_vn(&prd, &vnaddr)) {
1093 vnc_zlog_debug_verbose("%s: can't auto-assign RD, skipping",
1094 __func__);
1095 return;
1096 }
1097
1098 vncHDBgpDirect.peer = info->peer;
1099 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__,
1100 vncHDBgpDirect.peer);
1101 del_vnc_route(&vncHDBgpDirect, info->peer, bgp, SAFI_MPLS_VPN, prefix,
1102 &prd, ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE,
1103 NULL, 1);
1104
1105 vncHDBgpDirect.peer = NULL;
1106 }
1107
1108 static void vnc_import_bgp_del_route_mode_nvegroup(struct bgp *bgp,
1109 const struct prefix *prefix,
1110 struct bgp_path_info *info)
1111 {
1112 struct prefix_rd prd;
1113 afi_t afi = family2afi(prefix->family);
1114 struct rfapi_nve_group_cfg *rfg = NULL;
1115 struct prefix *vn_pfx = NULL;
1116 struct rfapi_ip_addr vnaddr;
1117
1118
1119 assert(afi);
1120
1121 rfg = bgp->rfapi_cfg->rfg_redist;
1122 assert(rfg);
1123
1124 /*
1125 * Compute VN address
1126 */
1127
1128 /*
1129 * export nve group's VN addr prefix must be a /32 which
1130 * will yield the VN addr to use
1131 */
1132 vn_pfx = &rfg->vn_prefix;
1133
1134
1135 vnaddr.addr_family = vn_pfx->family;
1136 switch (vn_pfx->family) {
1137 case AF_INET:
1138 if (vn_pfx->prefixlen != IPV4_MAX_BITLEN) {
1139 vnc_zlog_debug_verbose(
1140 "%s: redist VN plen (%d) != 32, skipping",
1141 __func__, vn_pfx->prefixlen);
1142 return;
1143 }
1144 vnaddr.addr.v4 = vn_pfx->u.prefix4;
1145 break;
1146
1147 case AF_INET6:
1148 if (vn_pfx->prefixlen != IPV6_MAX_BITLEN) {
1149 vnc_zlog_debug_verbose(
1150 "%s: redist VN plen (%d) != 128, skipping",
1151 __func__, vn_pfx->prefixlen);
1152 return;
1153 }
1154 vnaddr.addr.v6 = vn_pfx->u.prefix6;
1155 break;
1156
1157 default:
1158 vnc_zlog_debug_verbose(
1159 "%s: no redist RFG VN host pfx configured, skipping",
1160 __func__);
1161 return;
1162 }
1163
1164 memset(&prd, 0, sizeof(prd));
1165 prd = rfg->rd;
1166 prd.family = AF_UNSPEC;
1167 prd.prefixlen = 64;
1168
1169 if (rfg->rd.family == AF_UNIX) {
1170 /* means "auto" with VN addr */
1171 if (rfapi_set_autord_from_vn(&prd, &vnaddr)) {
1172 vnc_zlog_debug_verbose(
1173 "%s: can't auto-assign RD, skipping", __func__);
1174 return;
1175 }
1176 }
1177
1178
1179 vncHDBgpDirect.peer = info->peer;
1180 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__,
1181 vncHDBgpDirect.peer);
1182 del_vnc_route(&vncHDBgpDirect, info->peer, bgp, SAFI_MPLS_VPN, prefix,
1183 &prd, ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE,
1184 NULL, 1);
1185
1186 vncHDBgpDirect.peer = NULL;
1187 }
1188
1189 static void vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1190 struct bgp *bgp, afi_t afi, struct bgp_path_info *bpi, /* VPN bpi */
1191 struct prefix_rd *prd, /* RD */
1192 const struct prefix *prefix) /* unicast route prefix */
1193 {
1194 struct prefix un;
1195
1196 if (bpi->type != ZEBRA_ROUTE_BGP
1197 && bpi->type != ZEBRA_ROUTE_BGP_DIRECT) {
1198
1199 return;
1200 }
1201 if (bpi->sub_type != BGP_ROUTE_NORMAL
1202 && bpi->sub_type != BGP_ROUTE_STATIC
1203 && bpi->sub_type != BGP_ROUTE_RFP) {
1204
1205 return;
1206 }
1207 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
1208 return;
1209
1210 vncHDResolveNve.peer = bpi->peer;
1211 if (!rfapiGetVncTunnelUnAddr(bpi->attr, &un)) {
1212 if (rfapiQprefix2Raddr(&un, &vncHDResolveNve.un_addr))
1213 return;
1214 } else {
1215 memset(&vncHDResolveNve.un_addr, 0,
1216 sizeof(vncHDResolveNve.un_addr));
1217 }
1218
1219 del_vnc_route(&vncHDResolveNve, vncHDResolveNve.peer, bgp,
1220 SAFI_MPLS_VPN, prefix, /* unicast route prefix */
1221 prd, ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL,
1222 0); /* flags */
1223 }
1224
1225 static void vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1226 struct prefix_rd *prd,
1227 struct bgp_table *table_rd, /* per-rd VPN route table */
1228 afi_t afi, struct bgp *bgp,
1229 const struct prefix *prefix, /* unicast prefix */
1230 const struct prefix *ubpi_nexthop) /* unicast bpi's nexthop */
1231 {
1232 struct bgp_dest *bd;
1233 struct bgp_path_info *bpi;
1234
1235 if (!table_rd)
1236 return;
1237
1238 vnc_zlog_debug_verbose("%s: ubpi_nexthop=%pFX", __func__, ubpi_nexthop);
1239
1240
1241 /* exact match */
1242 bd = bgp_node_lookup(table_rd, ubpi_nexthop);
1243 if (!bd) {
1244 vnc_zlog_debug_verbose(
1245 "%s: no match in RD's table for ubpi_nexthop",
1246 __func__);
1247 return;
1248 }
1249
1250 /* Iterate over bgp_info items at this node */
1251 for (bpi = bgp_dest_get_bgp_path_info(bd); bpi; bpi = bpi->next) {
1252
1253 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1254 bgp, afi, bpi, /* VPN bpi */
1255 prd, /* VPN RD */
1256 prefix); /* unicast route prefix */
1257 }
1258
1259 bgp_dest_unlock_node(bd);
1260 }
1261
1262 static void
1263 vnc_import_bgp_del_route_mode_resolve_nve(struct bgp *bgp, afi_t afi,
1264 const struct prefix *prefix,
1265 struct bgp_path_info *info)
1266 {
1267 struct ecommunity *ecom = NULL;
1268 struct prefix pfx_unicast_nexthop = {0}; /* happy valgrind */
1269
1270 // struct listnode *hnode;
1271 // struct rfapi_descriptor *rfd;
1272 struct prefix_bag *pb;
1273 void *cursor;
1274 struct skiplist *sl = bgp->rfapi->resolve_nve_nexthop;
1275 int rc;
1276 struct bgp_dest *bdp; /* prd table node */
1277
1278 if (!sl) {
1279 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1280 __func__);
1281 return;
1282 }
1283
1284 if (info->type != ZEBRA_ROUTE_BGP) {
1285 vnc_zlog_debug_verbose(
1286 "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
1287 __func__, info->type, zebra_route_string(info->type),
1288 ZEBRA_ROUTE_BGP, "ZEBRA_ROUTE_BGP");
1289 return;
1290 }
1291
1292 if (process_unicast_route(bgp, afi, prefix, info, &ecom,
1293 &pfx_unicast_nexthop)) {
1294
1295 vnc_zlog_debug_verbose(
1296 "%s: process_unicast_route error, skipping", __func__);
1297 return;
1298 }
1299
1300 rc = skiplist_first_value(sl, &pfx_unicast_nexthop, (void *)&pb,
1301 &cursor);
1302 while (!rc) {
1303 if (pb->ubpi == info) {
1304 skiplist_delete(sl, &pfx_unicast_nexthop, pb);
1305 bgp_path_info_unlock(info);
1306 break;
1307 }
1308 rc = skiplist_next_value(sl, &pfx_unicast_nexthop, (void *)&pb,
1309 &cursor);
1310 }
1311
1312 /*
1313 * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
1314 * (exact match, /32). If an exact match is found, call add_vnc_route.
1315 */
1316
1317 for (bdp = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); bdp;
1318 bdp = bgp_route_next(bdp)) {
1319
1320 struct bgp_table *table;
1321
1322 table = bgp_dest_get_bgp_table_info(bdp);
1323
1324 if (!table)
1325 continue;
1326
1327 vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1328 (struct prefix_rd *)bgp_dest_get_prefix(bdp), table,
1329 afi, bgp, prefix, &pfx_unicast_nexthop);
1330 }
1331
1332 if (ecom)
1333 ecommunity_free(&ecom);
1334 }
1335
1336
1337 /***********************************************************************
1338 * Add/Delete CE->NVE routes
1339 ***********************************************************************/
1340
1341 /*
1342 * Should be called whan a bpi is added to VPN RIB. This function
1343 * will check if it is a host route and return immediately if not.
1344 */
1345 void vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1346 struct bgp *bgp, struct prefix_rd *prd, /* RD */
1347 struct bgp_table *table_rd, /* per-rd VPN route table */
1348 const struct prefix *prefix, /* VPN prefix */
1349 struct bgp_path_info *bpi) /* new VPN host route */
1350 {
1351 afi_t afi = family2afi(prefix->family);
1352 struct skiplist *sl = NULL;
1353 int rc;
1354 struct prefix_bag *pb;
1355 void *cursor;
1356 struct rfapi_cfg *hc = NULL;
1357
1358 vnc_zlog_debug_verbose("%s: entry", __func__);
1359
1360 if (afi != AFI_IP && afi != AFI_IP6) {
1361 vnc_zlog_debug_verbose("%s: bad afi %d, skipping", __func__,
1362 afi);
1363 return;
1364 }
1365
1366 if (!(hc = bgp->rfapi_cfg)) {
1367 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1368 __func__);
1369 return;
1370 }
1371
1372 /* check vnc redist flag for bgp direct routes */
1373 if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
1374 vnc_zlog_debug_verbose(
1375 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1376 __func__, afi);
1377 return;
1378 }
1379
1380 if (hc->redist_mode != VNC_REDIST_MODE_RESOLVE_NVE) {
1381 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1382 __func__);
1383 return;
1384 }
1385
1386 if (bgp->rfapi)
1387 sl = bgp->rfapi->resolve_nve_nexthop;
1388
1389 if (!sl) {
1390 vnc_zlog_debug_verbose(
1391 "%s: no resolve_nve_nexthop skiplist, skipping",
1392 __func__);
1393 return;
1394 }
1395
1396 if (!is_host_prefix(prefix)) {
1397 vnc_zlog_debug_verbose("%s: not host prefix, skipping",
1398 __func__);
1399 return;
1400 }
1401
1402 rc = skiplist_first_value(sl, prefix, (void *)&pb, &cursor);
1403 while (!rc) {
1404 struct ecommunity *ecom;
1405 struct prefix pfx_unicast_nexthop;
1406 uint32_t *med = NULL;
1407 uint32_t local_pref;
1408
1409 memset(&pfx_unicast_nexthop, 0,
1410 sizeof(pfx_unicast_nexthop)); /* keep valgrind happy */
1411
1412 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE))
1413 vnc_zlog_debug_any(
1414 "%s: examining RHN Entry (q=%p): upfx=%pFX, hpfx=%pFX, ubpi=%p",
1415 __func__, cursor, &pb->upfx, &pb->hpfx,
1416 pb->ubpi);
1417
1418 if (process_unicast_route(bgp, afi, &pb->upfx, pb->ubpi, &ecom,
1419 &pfx_unicast_nexthop)) {
1420
1421 vnc_zlog_debug_verbose(
1422 "%s: process_unicast_route error, skipping",
1423 __func__);
1424 continue;
1425 }
1426 local_pref = calc_local_pref(pb->ubpi->attr, pb->ubpi->peer);
1427
1428 if (pb->ubpi->attr->flag
1429 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
1430 med = &pb->ubpi->attr->med;
1431
1432 /*
1433 * Sanity check
1434 */
1435 if (vnc_prefix_cmp(&pfx_unicast_nexthop, prefix)) {
1436 vnc_zlog_debug_verbose(
1437 "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %pFX != nve pfx %pFX",
1438 __func__, &pfx_unicast_nexthop, prefix);
1439 assert(0);
1440 }
1441
1442 vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
1443 bgp, afi, bpi, /* VPN bpi */
1444 prd, &pb->upfx, /* unicast prefix */
1445 &local_pref, med, ecom);
1446
1447 if (ecom)
1448 ecommunity_free(&ecom);
1449
1450 #if DEBUG_RHN_LIST
1451 /* debug */
1452 {
1453 vnc_zlog_debug_verbose(
1454 "%s: advancing past RHN Entry (q=%p): with prefix %pFX",
1455 __func__, cursor, prefix);
1456 print_rhn_list(__func__, NULL); /* debug */
1457 }
1458 #endif
1459 rc = skiplist_next_value(sl, prefix, (void *)&pb, &cursor);
1460 }
1461 vnc_zlog_debug_verbose("%s: done", __func__);
1462 }
1463
1464
1465 void vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
1466 struct bgp *bgp, struct prefix_rd *prd, /* RD */
1467 struct bgp_table *table_rd, /* per-rd VPN route table */
1468 const struct prefix *prefix, /* VPN prefix */
1469 struct bgp_path_info *bpi) /* old VPN host route */
1470 {
1471 afi_t afi = family2afi(prefix->family);
1472 struct skiplist *sl = NULL;
1473 struct prefix_bag *pb;
1474 void *cursor;
1475 struct rfapi_cfg *hc = NULL;
1476 int rc;
1477
1478 vnc_zlog_debug_verbose("%s(bgp=%p, nve prefix=%pFX)", __func__, bgp,
1479 prefix);
1480
1481 if (afi != AFI_IP && afi != AFI_IP6)
1482 return;
1483
1484 if (!(hc = bgp->rfapi_cfg)) {
1485 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1486 __func__);
1487 return;
1488 }
1489
1490 /* check vnc redist flag for bgp direct routes */
1491 if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
1492 vnc_zlog_debug_verbose(
1493 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1494 __func__, afi);
1495 return;
1496 }
1497
1498 if (hc->redist_mode != VNC_REDIST_MODE_RESOLVE_NVE) {
1499 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1500 __func__);
1501 return;
1502 }
1503
1504 if (bgp->rfapi)
1505 sl = bgp->rfapi->resolve_nve_nexthop;
1506
1507 if (!sl) {
1508 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1509 __func__);
1510 return;
1511 }
1512
1513 if (!is_host_prefix(prefix)) {
1514 vnc_zlog_debug_verbose("%s: not host route, skip", __func__);
1515 return;
1516 }
1517
1518 /*
1519 * Find all entries with key == CE in the RHN list
1520 */
1521 rc = skiplist_first_value(sl, prefix, (void *)&pb, &cursor);
1522 while (!rc) {
1523
1524 struct ecommunity *ecom;
1525 struct prefix pfx_unicast_nexthop;
1526
1527 memset(&pfx_unicast_nexthop, 0,
1528 sizeof(pfx_unicast_nexthop)); /* keep valgrind happy */
1529
1530 if (process_unicast_route(bgp, afi, &pb->upfx, pb->ubpi, &ecom,
1531 &pfx_unicast_nexthop)) {
1532
1533 vnc_zlog_debug_verbose(
1534 "%s: process_unicast_route error, skipping",
1535 __func__);
1536 continue;
1537 }
1538
1539 /*
1540 * Sanity check
1541 */
1542 if (vnc_prefix_cmp(&pfx_unicast_nexthop, prefix)) {
1543 vnc_zlog_debug_verbose(
1544 "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %pFX != nve pfx %pFX",
1545 __func__, &pfx_unicast_nexthop, prefix);
1546 assert(0);
1547 }
1548
1549 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1550 bgp, afi, bpi, prd, &pb->upfx);
1551
1552 if (ecom)
1553 ecommunity_free(&ecom);
1554
1555 rc = skiplist_next_value(sl, prefix, (void *)&pb, &cursor);
1556 }
1557 }
1558
1559
1560 /***********************************************************************
1561 * Exterior Routes
1562 ***********************************************************************/
1563
1564 #define DEBUG_IS_USABLE_INTERIOR 1
1565
1566 static int is_usable_interior_route(struct bgp_path_info *bpi_interior)
1567 {
1568 if (!VALID_INTERIOR_TYPE(bpi_interior->type)) {
1569 #if DEBUG_IS_USABLE_INTERIOR
1570 vnc_zlog_debug_verbose(
1571 "%s: NO: type %d is not valid interior type", __func__,
1572 bpi_interior->type);
1573 #endif
1574 return 0;
1575 }
1576 if (!CHECK_FLAG(bpi_interior->flags, BGP_PATH_VALID)) {
1577 #if DEBUG_IS_USABLE_INTERIOR
1578 vnc_zlog_debug_verbose("%s: NO: BGP_PATH_VALID not set",
1579 __func__);
1580 #endif
1581 return 0;
1582 }
1583 return 1;
1584 }
1585
1586 /*
1587 * There should be only one of these per prefix at a time.
1588 * This should be called as a result of selection operation
1589 *
1590 * NB should be called espacially for bgp instances that are named,
1591 * because the exterior routes will always come from one of those.
1592 * We filter here on the instance name to make sure we get only the
1593 * right routes.
1594 */
1595 static void vnc_import_bgp_exterior_add_route_it(
1596 struct bgp *bgp, /* exterior instance, we hope */
1597 const struct prefix *prefix, /* unicast prefix */
1598 struct bgp_path_info *info, /* unicast info */
1599 struct rfapi_import_table *it_only) /* NULL, or limit to this IT */
1600 {
1601 struct rfapi *h;
1602 struct rfapi_cfg *hc;
1603 struct prefix pfx_orig_nexthop;
1604 struct rfapi_import_table *it;
1605 struct bgp *bgp_default = bgp_get_default();
1606 afi_t afi = family2afi(prefix->family);
1607
1608 if (!bgp_default)
1609 return;
1610
1611 h = bgp_default->rfapi;
1612 hc = bgp_default->rfapi_cfg;
1613
1614 vnc_zlog_debug_verbose("%s: entry with it=%p", __func__, it_only);
1615
1616 if (!h || !hc) {
1617 vnc_zlog_debug_verbose(
1618 "%s: rfapi or rfapi_cfg not instantiated, skipping",
1619 __func__);
1620 return;
1621 }
1622 if (!hc->redist_bgp_exterior_view) {
1623 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1624 __func__);
1625 return;
1626 }
1627 if (bgp != hc->redist_bgp_exterior_view) {
1628 vnc_zlog_debug_verbose(
1629 "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1630 __func__, bgp, hc->redist_bgp_exterior_view);
1631 return;
1632 }
1633
1634 if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
1635 vnc_zlog_debug_verbose(
1636 "%s: redist of exterior routes not enabled, skipping",
1637 __func__);
1638 return;
1639 }
1640
1641 /*
1642 * Extract nexthop from exterior route
1643 *
1644 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1645 * but if v4 it is in attr->nexthop
1646 */
1647 rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_orig_nexthop);
1648
1649 for (it = h->imports; it; it = it->next) {
1650 struct agg_table *table;
1651 struct agg_node *rn;
1652 struct agg_node *par;
1653 struct bgp_path_info *bpi_interior;
1654 int have_usable_route;
1655
1656 vnc_zlog_debug_verbose("%s: doing it %p", __func__, it);
1657
1658 if (it_only && (it_only != it)) {
1659 vnc_zlog_debug_verbose("%s: doesn't match it_only %p",
1660 __func__, it_only);
1661 continue;
1662 }
1663
1664 table = it->imported_vpn[afi];
1665
1666 for (rn = agg_node_match(table, &pfx_orig_nexthop),
1667 have_usable_route = 0;
1668 (!have_usable_route) && rn;) {
1669
1670 vnc_zlog_debug_verbose("%s: it %p trying rn %p",
1671 __func__, it, rn);
1672
1673 for (bpi_interior = rn->info; bpi_interior;
1674 bpi_interior = bpi_interior->next) {
1675 struct prefix_rd *prd;
1676 struct attr new_attr;
1677 uint32_t label = 0;
1678
1679 if (!is_usable_interior_route(bpi_interior))
1680 continue;
1681
1682 vnc_zlog_debug_verbose(
1683 "%s: usable: bpi_interior %p", __func__,
1684 bpi_interior);
1685
1686 /*
1687 * have a legitimate route to exterior's nexthop
1688 * via NVE.
1689 *
1690 * Import unicast route to the import table
1691 */
1692 have_usable_route = 1;
1693
1694 if (bpi_interior->extra) {
1695 prd = &bpi_interior->extra->vnc.import
1696 .rd;
1697 label = decode_label(
1698 &bpi_interior->extra->label[0]);
1699 } else
1700 prd = NULL;
1701
1702 /* use local_pref from unicast route */
1703 memset(&new_attr, 0, sizeof(new_attr));
1704 new_attr = *bpi_interior->attr;
1705 if (info->attr->flag
1706 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
1707 new_attr.local_pref =
1708 info->attr->local_pref;
1709 new_attr.flag |= ATTR_FLAG_BIT(
1710 BGP_ATTR_LOCAL_PREF);
1711 }
1712
1713 rfapiBgpInfoFilteredImportVPN(
1714 it, FIF_ACTION_UPDATE,
1715 bpi_interior->peer, NULL, /* rfd */
1716 prefix, NULL, afi, prd, &new_attr,
1717 ZEBRA_ROUTE_BGP_DIRECT_EXT,
1718 BGP_ROUTE_REDISTRIBUTE, &label);
1719 }
1720
1721 if (have_usable_route) {
1722 /*
1723 * Make monitor
1724 *
1725 * TBD factor this out into its own function
1726 */
1727 struct prefix *pfx_mon = prefix_new();
1728 if (!RFAPI_MONITOR_EXTERIOR(rn)->source) {
1729 RFAPI_MONITOR_EXTERIOR(rn)->source =
1730 skiplist_new(
1731 0, NULL,
1732 prefix_free_lists);
1733 agg_lock_node(rn); /* for skiplist */
1734 }
1735 agg_lock_node(rn); /* for skiplist entry */
1736 prefix_copy(pfx_mon, prefix);
1737 if (!skiplist_insert(
1738 RFAPI_MONITOR_EXTERIOR(rn)->source,
1739 info, pfx_mon)) {
1740
1741 bgp_path_info_lock(info);
1742 }
1743 }
1744 par = agg_node_parent(rn);
1745 if (par)
1746 agg_lock_node(par);
1747 agg_unlock_node(rn);
1748 rn = par;
1749 }
1750 if (rn)
1751 agg_unlock_node(rn);
1752
1753 if (!have_usable_route) {
1754 struct prefix *pfx_mon = prefix_new();
1755 prefix_copy(pfx_mon, prefix);
1756 if (!skiplist_insert(it->monitor_exterior_orphans, info,
1757 pfx_mon)) {
1758
1759 bgp_path_info_lock(info);
1760 }
1761 }
1762 }
1763 }
1764
1765 void vnc_import_bgp_exterior_add_route(
1766 struct bgp *bgp, /* exterior instance, we hope */
1767 const struct prefix *prefix, /* unicast prefix */
1768 struct bgp_path_info *info) /* unicast info */
1769 {
1770 vnc_import_bgp_exterior_add_route_it(bgp, prefix, info, NULL);
1771 }
1772
1773 /*
1774 * There should be only one of these per prefix at a time.
1775 * This should probably be called as a result of selection operation.
1776 *
1777 * NB should be called espacially for bgp instances that are named,
1778 * because the exterior routes will always come from one of those.
1779 * We filter here on the instance name to make sure we get only the
1780 * right routes.
1781 */
1782 void vnc_import_bgp_exterior_del_route(
1783 struct bgp *bgp, const struct prefix *prefix, /* unicast prefix */
1784 struct bgp_path_info *info) /* unicast info */
1785 {
1786 struct rfapi *h;
1787 struct rfapi_cfg *hc;
1788 struct rfapi_import_table *it;
1789 struct prefix pfx_orig_nexthop;
1790 afi_t afi = family2afi(prefix->family);
1791 struct bgp *bgp_default = bgp_get_default();
1792
1793 if (!bgp_default)
1794 return;
1795
1796 memset(&pfx_orig_nexthop, 0,
1797 sizeof(pfx_orig_nexthop)); /* keep valgrind happy */
1798
1799 h = bgp_default->rfapi;
1800 hc = bgp_default->rfapi_cfg;
1801
1802 if (!h || !hc) {
1803 vnc_zlog_debug_verbose(
1804 "%s: rfapi or rfapi_cfg not instantiated, skipping",
1805 __func__);
1806 return;
1807 }
1808 if (!hc->redist_bgp_exterior_view) {
1809 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1810 __func__);
1811 return;
1812 }
1813 if (bgp != hc->redist_bgp_exterior_view) {
1814 vnc_zlog_debug_verbose(
1815 "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1816 __func__, bgp, hc->redist_bgp_exterior_view);
1817 return;
1818 }
1819 if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
1820 vnc_zlog_debug_verbose(
1821 "%s: redist of exterior routes no enabled, skipping",
1822 __func__);
1823 return;
1824 }
1825
1826 /*
1827 * Extract nexthop from exterior route
1828 *
1829 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1830 * but if v4 it is in attr->nexthop
1831 */
1832 rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_orig_nexthop);
1833
1834 for (it = h->imports; it; it = it->next) {
1835 struct agg_table *table;
1836 struct agg_node *rn;
1837 struct agg_node *par;
1838 struct bgp_path_info *bpi_interior;
1839 int have_usable_route;
1840
1841 table = it->imported_vpn[afi];
1842
1843 for (rn = agg_node_match(table, &pfx_orig_nexthop),
1844 have_usable_route = 0;
1845 (!have_usable_route) && rn;) {
1846
1847 for (bpi_interior = rn->info; bpi_interior;
1848 bpi_interior = bpi_interior->next) {
1849 struct prefix_rd *prd;
1850 uint32_t label = 0;
1851
1852 if (!is_usable_interior_route(bpi_interior))
1853 continue;
1854
1855 /*
1856 * have a legitimate route to exterior's nexthop
1857 * via NVE.
1858 *
1859 * Import unicast route to the import table
1860 */
1861 have_usable_route = 1;
1862
1863 if (bpi_interior->extra) {
1864 prd = &bpi_interior->extra->vnc.import
1865 .rd;
1866 label = decode_label(
1867 &bpi_interior->extra->label[0]);
1868 } else
1869 prd = NULL;
1870
1871 rfapiBgpInfoFilteredImportVPN(
1872 it, FIF_ACTION_KILL, bpi_interior->peer,
1873 NULL, /* rfd */
1874 prefix, NULL, afi, prd,
1875 bpi_interior->attr,
1876 ZEBRA_ROUTE_BGP_DIRECT_EXT,
1877 BGP_ROUTE_REDISTRIBUTE, &label);
1878
1879 /*
1880 * Delete monitor
1881 *
1882 * TBD factor this out into its own function
1883 */
1884 {
1885 if (RFAPI_MONITOR_EXTERIOR(rn)
1886 ->source) {
1887 if (!skiplist_delete(
1888 RFAPI_MONITOR_EXTERIOR(
1889 rn)
1890 ->source,
1891 info, NULL)) {
1892
1893 bgp_path_info_unlock(
1894 info);
1895 agg_unlock_node(
1896 rn); /* sl entry
1897 */
1898 }
1899 if (skiplist_empty(
1900 RFAPI_MONITOR_EXTERIOR(
1901 rn)
1902 ->source)) {
1903 skiplist_free(
1904 RFAPI_MONITOR_EXTERIOR(
1905 rn)
1906 ->source);
1907 RFAPI_MONITOR_EXTERIOR(
1908 rn)
1909 ->source = NULL;
1910 agg_unlock_node(
1911 rn); /* skiplist
1912 itself
1913 */
1914 }
1915 }
1916 }
1917 }
1918 par = agg_node_parent(rn);
1919 if (par)
1920 agg_lock_node(par);
1921 agg_unlock_node(rn);
1922 rn = par;
1923 }
1924 if (rn)
1925 agg_unlock_node(rn);
1926
1927 if (!have_usable_route) {
1928 if (!skiplist_delete(it->monitor_exterior_orphans, info,
1929 NULL)) {
1930
1931 bgp_path_info_unlock(info);
1932 }
1933 }
1934 }
1935 }
1936
1937 /*
1938 * This function should be called after a new interior VPN route
1939 * has been added to an import_table.
1940 *
1941 * NB should also be called whenever an existing vpn interior route
1942 * becomes valid (e.g., valid_interior_count is inremented)
1943 */
1944 void vnc_import_bgp_exterior_add_route_interior(
1945 struct bgp *bgp, struct rfapi_import_table *it,
1946 struct agg_node *rn_interior, /* VPN IT node */
1947 struct bgp_path_info *bpi_interior) /* VPN IT route */
1948 {
1949 const struct prefix *p = agg_node_get_prefix(rn_interior);
1950 afi_t afi = family2afi(p->family);
1951 struct agg_node *par;
1952 struct bgp_path_info *bpi_exterior;
1953 struct prefix *pfx_exterior; /* exterior pfx */
1954 void *cursor;
1955 int rc;
1956 struct list *list_adopted;
1957
1958 vnc_zlog_debug_verbose("%s: entry", __func__);
1959
1960 if (!is_usable_interior_route(bpi_interior)) {
1961 vnc_zlog_debug_verbose(
1962 "%s: not usable interior route, skipping", __func__);
1963 return;
1964 }
1965
1966 if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
1967 vnc_zlog_debug_verbose(
1968 "%s: redist of exterior routes no enabled, skipping",
1969 __func__);
1970 return;
1971 }
1972
1973 if (it == bgp->rfapi->it_ce) {
1974 vnc_zlog_debug_verbose("%s: import table is it_ce, skipping",
1975 __func__);
1976 return;
1977 }
1978
1979 /*debugging */
1980 vnc_zlog_debug_verbose("%s: interior prefix=%pRN, bpi type=%d",
1981 __func__, rn_interior, bpi_interior->type);
1982
1983 if (RFAPI_HAS_MONITOR_EXTERIOR(rn_interior)) {
1984
1985 int count = 0; /* debugging */
1986
1987 vnc_zlog_debug_verbose(
1988 "%s: has exterior monitor; ext src: %p", __func__,
1989 RFAPI_MONITOR_EXTERIOR(rn_interior)->source);
1990
1991 /*
1992 * There is a monitor here already. Therefore, we do not need
1993 * to do any pulldown. Just construct exterior routes based
1994 * on the new interior route.
1995 */
1996 cursor = NULL;
1997 for (rc = skiplist_next(
1998 RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
1999 (void **)&bpi_exterior, (void **)&pfx_exterior,
2000 &cursor);
2001 !rc; rc = skiplist_next(
2002 RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2003 (void **)&bpi_exterior,
2004 (void **)&pfx_exterior, &cursor)) {
2005
2006 struct prefix_rd *prd;
2007 struct attr new_attr;
2008 uint32_t label = 0;
2009
2010
2011 ++count; /* debugging */
2012
2013 assert(bpi_exterior);
2014 assert(pfx_exterior);
2015
2016 if (bpi_interior->extra) {
2017 prd = &bpi_interior->extra->vnc.import.rd;
2018 label = decode_label(
2019 &bpi_interior->extra->label[0]);
2020 } else
2021 prd = NULL;
2022
2023 /* use local_pref from unicast route */
2024 memset(&new_attr, 0, sizeof(struct attr));
2025 new_attr = *bpi_interior->attr;
2026 if (bpi_exterior
2027 && (bpi_exterior->attr->flag
2028 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) {
2029 new_attr.local_pref =
2030 bpi_exterior->attr->local_pref;
2031 new_attr.flag |=
2032 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2033 }
2034
2035 rfapiBgpInfoFilteredImportVPN(
2036 it, FIF_ACTION_UPDATE, bpi_interior->peer,
2037 NULL, /* rfd */
2038 pfx_exterior, NULL, afi, prd, &new_attr,
2039 ZEBRA_ROUTE_BGP_DIRECT_EXT,
2040 BGP_ROUTE_REDISTRIBUTE, &label);
2041 }
2042 vnc_zlog_debug_verbose(
2043 "%s: finished constructing exteriors based on existing monitors",
2044 __func__);
2045 return;
2046 }
2047
2048 vnc_zlog_debug_verbose("%s: no exterior monitor", __func__);
2049
2050 /*
2051 * No monitor at this node. Is this the first valid interior
2052 * route at this node?
2053 */
2054 if (RFAPI_MONITOR_EXTERIOR(rn_interior)->valid_interior_count > 1) {
2055 vnc_zlog_debug_verbose(
2056 "%s: new interior route not first valid one, skipping pulldown",
2057 __func__);
2058 return;
2059 }
2060
2061 /*
2062 * Look up the tree for possible pulldown candidates.
2063 * Find nearest parent with an exterior route monitor
2064 */
2065 for (par = agg_node_parent(rn_interior); par;
2066 par = agg_node_parent(par)) {
2067 if (RFAPI_HAS_MONITOR_EXTERIOR(par))
2068 break;
2069 }
2070
2071 if (par) {
2072
2073 vnc_zlog_debug_verbose(
2074 "%s: checking parent %p for possible pulldowns",
2075 __func__, par);
2076
2077 /* check monitors at par for possible pulldown */
2078 cursor = NULL;
2079 for (rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(par)->source,
2080 (void **)&bpi_exterior,
2081 (void **)&pfx_exterior, &cursor);
2082 !rc;
2083 rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(par)->source,
2084 (void **)&bpi_exterior,
2085 (void **)&pfx_exterior, &cursor)) {
2086
2087 struct prefix pfx_nexthop;
2088
2089 memset(&pfx_nexthop, 0,
2090 sizeof(struct prefix)); /* keep valgrind happy */
2091
2092 /* check original nexthop for prefix match */
2093 rfapiUnicastNexthop2Prefix(afi, bpi_exterior->attr,
2094 &pfx_nexthop);
2095
2096 if (prefix_match(p, &pfx_nexthop)) {
2097
2098 struct bgp_path_info *bpi;
2099 struct prefix_rd *prd;
2100 struct attr new_attr;
2101 uint32_t label = 0;
2102
2103 /* do pull-down */
2104
2105 /*
2106 * add monitor to longer prefix
2107 */
2108 struct prefix *pfx_mon = prefix_new();
2109 prefix_copy(pfx_mon, pfx_exterior);
2110 if (!RFAPI_MONITOR_EXTERIOR(rn_interior)
2111 ->source) {
2112 RFAPI_MONITOR_EXTERIOR(rn_interior)
2113 ->source = skiplist_new(
2114 0, NULL, prefix_free_lists);
2115 agg_lock_node(rn_interior);
2116 }
2117 skiplist_insert(
2118 RFAPI_MONITOR_EXTERIOR(rn_interior)
2119 ->source,
2120 bpi_exterior, pfx_mon);
2121 agg_lock_node(rn_interior);
2122
2123 /*
2124 * Delete constructed exterior routes based on
2125 * parent routes.
2126 */
2127 for (bpi = par->info; bpi; bpi = bpi->next) {
2128
2129 if (bpi->extra) {
2130 prd = &bpi->extra->vnc.import
2131 .rd;
2132 label = decode_label(
2133 &bpi->extra->label[0]);
2134 } else
2135 prd = NULL;
2136
2137 rfapiBgpInfoFilteredImportVPN(
2138 it, FIF_ACTION_KILL, bpi->peer,
2139 NULL, /* rfd */
2140 pfx_exterior, NULL, afi, prd,
2141 bpi->attr,
2142 ZEBRA_ROUTE_BGP_DIRECT_EXT,
2143 BGP_ROUTE_REDISTRIBUTE, &label);
2144 }
2145
2146
2147 /*
2148 * Add constructed exterior routes based on
2149 * the new interior route at longer prefix.
2150 */
2151 if (bpi_interior->extra) {
2152 prd = &bpi_interior->extra->vnc.import
2153 .rd;
2154 label = decode_label(
2155 &bpi_interior->extra->label[0]);
2156 } else
2157 prd = NULL;
2158
2159 /* use local_pref from unicast route */
2160 memset(&new_attr, 0, sizeof(struct attr));
2161 new_attr = *bpi_interior->attr;
2162 if (bpi_exterior
2163 && (bpi_exterior->attr->flag
2164 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) {
2165 new_attr.local_pref =
2166 bpi_exterior->attr->local_pref;
2167 new_attr.flag |= ATTR_FLAG_BIT(
2168 BGP_ATTR_LOCAL_PREF);
2169 }
2170
2171 rfapiBgpInfoFilteredImportVPN(
2172 it, FIF_ACTION_UPDATE,
2173 bpi_interior->peer, NULL, /* rfd */
2174 pfx_exterior, NULL, afi, prd, &new_attr,
2175 ZEBRA_ROUTE_BGP_DIRECT_EXT,
2176 BGP_ROUTE_REDISTRIBUTE, &label);
2177 }
2178 }
2179
2180 /*
2181 * The only monitors at rn_interior are the ones we added just
2182 * above, so we can use the rn_interior list to identify which
2183 * monitors to delete from the parent.
2184 */
2185 cursor = NULL;
2186 for (rc = skiplist_next(
2187 RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2188 (void **)&bpi_exterior, NULL, &cursor);
2189 !rc; rc = skiplist_next(
2190 RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2191 (void **)&bpi_exterior, NULL, &cursor)) {
2192
2193
2194 skiplist_delete(RFAPI_MONITOR_EXTERIOR(par)->source,
2195 bpi_exterior, NULL);
2196 agg_unlock_node(par); /* sl entry */
2197 }
2198 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(par)->source)) {
2199 skiplist_free(RFAPI_MONITOR_EXTERIOR(par)->source);
2200 RFAPI_MONITOR_EXTERIOR(par)->source = NULL;
2201 agg_unlock_node(par); /* sl itself */
2202 }
2203 }
2204
2205 vnc_zlog_debug_verbose("%s: checking orphans", __func__);
2206
2207 /*
2208 * See if any orphans can be pulled down to the current node
2209 */
2210 cursor = NULL;
2211 list_adopted = NULL;
2212 for (rc = skiplist_next(it->monitor_exterior_orphans,
2213 (void **)&bpi_exterior, (void **)&pfx_exterior,
2214 &cursor);
2215 !rc; rc = skiplist_next(it->monitor_exterior_orphans,
2216 (void **)&bpi_exterior,
2217 (void **)&pfx_exterior, &cursor)) {
2218
2219 struct prefix pfx_nexthop;
2220 afi_t afi_exterior = family2afi(pfx_exterior->family);
2221
2222 vnc_zlog_debug_verbose(
2223 "%s: checking exterior orphan at prefix %pFX", __func__,
2224 pfx_exterior);
2225
2226 if (afi_exterior != afi) {
2227 vnc_zlog_debug_verbose(
2228 "%s: exterior orphan afi %d != interior afi %d, skip",
2229 __func__, afi_exterior, afi);
2230 continue;
2231 }
2232
2233 /* check original nexthop for prefix match */
2234 rfapiUnicastNexthop2Prefix(afi, bpi_exterior->attr,
2235 &pfx_nexthop);
2236
2237 if (prefix_match(p, &pfx_nexthop)) {
2238
2239 struct prefix_rd *prd;
2240 struct attr new_attr;
2241 uint32_t label = 0;
2242
2243 /* do pull-down */
2244
2245 /*
2246 * add monitor to longer prefix
2247 */
2248
2249 struct prefix *pfx_mon = prefix_new();
2250 prefix_copy(pfx_mon, pfx_exterior);
2251 if (!RFAPI_MONITOR_EXTERIOR(rn_interior)->source) {
2252 RFAPI_MONITOR_EXTERIOR(rn_interior)->source =
2253 skiplist_new(
2254 0, NULL, prefix_free_lists);
2255 agg_lock_node(rn_interior); /* sl */
2256 }
2257 skiplist_insert(
2258 RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2259 bpi_exterior, pfx_mon);
2260 agg_lock_node(rn_interior); /* sl entry */
2261 if (!list_adopted) {
2262 list_adopted = list_new();
2263 }
2264 listnode_add(list_adopted, bpi_exterior);
2265
2266 /*
2267 * Add constructed exterior routes based on the
2268 * new interior route at the longer prefix.
2269 */
2270 if (bpi_interior->extra) {
2271 prd = &bpi_interior->extra->vnc.import.rd;
2272 label = decode_label(
2273 &bpi_interior->extra->label[0]);
2274 } else
2275 prd = NULL;
2276
2277 /* use local_pref from unicast route */
2278 memset(&new_attr, 0, sizeof(struct attr));
2279 new_attr = *bpi_interior->attr;
2280 if (bpi_exterior
2281 && (bpi_exterior->attr->flag
2282 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) {
2283 new_attr.local_pref =
2284 bpi_exterior->attr->local_pref;
2285 new_attr.flag |=
2286 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2287 }
2288
2289 rfapiBgpInfoFilteredImportVPN(
2290 it, FIF_ACTION_UPDATE, bpi_interior->peer,
2291 NULL, /* rfd */
2292 pfx_exterior, NULL, afi, prd, &new_attr,
2293 ZEBRA_ROUTE_BGP_DIRECT_EXT,
2294 BGP_ROUTE_REDISTRIBUTE, &label);
2295 }
2296 }
2297 if (list_adopted) {
2298 struct listnode *node;
2299 struct agg_node *an_bpi_exterior;
2300
2301 for (ALL_LIST_ELEMENTS_RO(list_adopted, node,
2302 an_bpi_exterior)) {
2303 skiplist_delete(it->monitor_exterior_orphans,
2304 an_bpi_exterior, NULL);
2305 }
2306 list_delete(&list_adopted);
2307 }
2308 }
2309
2310 /*
2311 * This function should be called after an interior VPN route
2312 * has been deleted from an import_table.
2313 * bpi_interior must still be valid, but it must already be detached
2314 * from its route node and the route node's valid_interior_count
2315 * must already be decremented.
2316 *
2317 * NB should also be called whenever an existing vpn interior route
2318 * becomes invalid (e.g., valid_interior_count is decremented)
2319 */
2320 void vnc_import_bgp_exterior_del_route_interior(
2321 struct bgp *bgp, struct rfapi_import_table *it,
2322 struct agg_node *rn_interior, /* VPN IT node */
2323 struct bgp_path_info *bpi_interior) /* VPN IT route */
2324 {
2325 const struct prefix *p = agg_node_get_prefix(rn_interior);
2326 afi_t afi = family2afi(p->family);
2327 struct agg_node *par;
2328 struct bgp_path_info *bpi_exterior;
2329 struct prefix *pfx_exterior; /* exterior pfx */
2330 void *cursor;
2331 int rc;
2332
2333 if (!VALID_INTERIOR_TYPE(bpi_interior->type)) {
2334 vnc_zlog_debug_verbose(
2335 "%s: type %d not valid interior type, skipping",
2336 __func__, bpi_interior->type);
2337 return;
2338 }
2339
2340 if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
2341 vnc_zlog_debug_verbose(
2342 "%s: redist of exterior routes no enabled, skipping",
2343 __func__);
2344 return;
2345 }
2346
2347 if (it == bgp->rfapi->it_ce) {
2348 vnc_zlog_debug_verbose("%s: it is it_ce, skipping", __func__);
2349 return;
2350 }
2351
2352 /* If no exterior routes depend on this prefix, nothing to do */
2353 if (!RFAPI_HAS_MONITOR_EXTERIOR(rn_interior)) {
2354 vnc_zlog_debug_verbose("%s: no exterior monitor, skipping",
2355 __func__);
2356 return;
2357 }
2358
2359 /*debugging */
2360 vnc_zlog_debug_verbose("%s: interior prefix=%pRN, bpi type=%d",
2361 __func__, rn_interior, bpi_interior->type);
2362
2363 /*
2364 * Remove constructed routes based on the deleted interior route
2365 */
2366 cursor = NULL;
2367 for (rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2368 (void **)&bpi_exterior, (void **)&pfx_exterior,
2369 &cursor);
2370 !rc;
2371 rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2372 (void **)&bpi_exterior, (void **)&pfx_exterior,
2373 &cursor)) {
2374
2375 struct prefix_rd *prd;
2376 uint32_t label = 0;
2377
2378 if (bpi_interior->extra) {
2379 prd = &bpi_interior->extra->vnc.import.rd;
2380 label = decode_label(&bpi_interior->extra->label[0]);
2381 } else
2382 prd = NULL;
2383
2384 rfapiBgpInfoFilteredImportVPN(
2385 it, FIF_ACTION_KILL, bpi_interior->peer, NULL, /* rfd */
2386 pfx_exterior, NULL, afi, prd, bpi_interior->attr,
2387 ZEBRA_ROUTE_BGP_DIRECT_EXT, BGP_ROUTE_REDISTRIBUTE,
2388 &label);
2389 }
2390
2391 /*
2392 * If there are no remaining valid interior routes at this prefix,
2393 * we need to look up the tree for a possible node to move monitors to
2394 */
2395 if (RFAPI_MONITOR_EXTERIOR(rn_interior)->valid_interior_count) {
2396 vnc_zlog_debug_verbose(
2397 "%s: interior routes still present, skipping",
2398 __func__);
2399 return;
2400 }
2401
2402 /*
2403 * Find nearest parent with at least one valid interior route
2404 * If none is found, par will end up NULL, and we will move
2405 * the monitors to the orphan list for this import table
2406 */
2407 for (par = agg_node_parent(rn_interior); par;
2408 par = agg_node_parent(par)) {
2409 if (RFAPI_MONITOR_EXTERIOR(par)->valid_interior_count)
2410 break;
2411 }
2412
2413 vnc_zlog_debug_verbose("%s: par=%p, ext src: %p", __func__, par,
2414 RFAPI_MONITOR_EXTERIOR(rn_interior)->source);
2415
2416 /* move all monitors */
2417 /*
2418 * We will use and delete every element of the source skiplist
2419 */
2420 while (!skiplist_first(RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2421 (void **)&bpi_exterior,
2422 (void **)&pfx_exterior)) {
2423
2424 struct prefix *pfx_mon = prefix_new();
2425
2426 prefix_copy(pfx_mon, pfx_exterior);
2427
2428 if (par) {
2429
2430 struct bgp_path_info *bpi;
2431
2432 /*
2433 * Add monitor to parent node
2434 */
2435 if (!RFAPI_MONITOR_EXTERIOR(par)->source) {
2436 RFAPI_MONITOR_EXTERIOR(par)->source =
2437 skiplist_new(
2438 0, NULL, prefix_free_lists);
2439 agg_lock_node(par); /* sl */
2440 }
2441 skiplist_insert(RFAPI_MONITOR_EXTERIOR(par)->source,
2442 bpi_exterior, pfx_mon);
2443 agg_lock_node(par); /* sl entry */
2444
2445 /* Add constructed exterior routes based on parent */
2446 for (bpi = par->info; bpi; bpi = bpi->next) {
2447
2448 struct prefix_rd *prd;
2449 struct attr new_attr;
2450 uint32_t label = 0;
2451
2452 if (bpi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT)
2453 continue;
2454
2455 if (bpi->extra) {
2456 prd = &bpi->extra->vnc.import.rd;
2457 label = decode_label(
2458 &bpi->extra->label[0]);
2459 } else
2460 prd = NULL;
2461
2462 /* use local_pref from unicast route */
2463 memset(&new_attr, 0, sizeof(new_attr));
2464 new_attr = *bpi->attr;
2465 if (bpi_exterior
2466 && (bpi_exterior->attr->flag
2467 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) {
2468 new_attr.local_pref =
2469 bpi_exterior->attr->local_pref;
2470 new_attr.flag |= ATTR_FLAG_BIT(
2471 BGP_ATTR_LOCAL_PREF);
2472 }
2473
2474 rfapiBgpInfoFilteredImportVPN(
2475 it, FIF_ACTION_UPDATE, bpi->peer,
2476 NULL, /* rfd */
2477 pfx_exterior, NULL, afi, prd, &new_attr,
2478 ZEBRA_ROUTE_BGP_DIRECT_EXT,
2479 BGP_ROUTE_REDISTRIBUTE, &label);
2480 }
2481
2482 } else {
2483
2484 /*
2485 * No interior route for exterior's nexthop. Save
2486 * monitor
2487 * in orphan list to await future route.
2488 */
2489 skiplist_insert(it->monitor_exterior_orphans,
2490 bpi_exterior, pfx_mon);
2491 }
2492
2493 skiplist_delete_first(
2494 RFAPI_MONITOR_EXTERIOR(rn_interior)->source);
2495 agg_unlock_node(rn_interior); /* sl entry */
2496 }
2497 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(rn_interior)->source)) {
2498 skiplist_free(RFAPI_MONITOR_EXTERIOR(rn_interior)->source);
2499 RFAPI_MONITOR_EXTERIOR(rn_interior)->source = NULL;
2500 agg_unlock_node(rn_interior); /* sl itself */
2501 }
2502 }
2503
2504 /***********************************************************************
2505 * Generic add/delete unicast routes
2506 ***********************************************************************/
2507
2508 void vnc_import_bgp_add_route(struct bgp *bgp, const struct prefix *prefix,
2509 struct bgp_path_info *info)
2510 {
2511 afi_t afi = family2afi(prefix->family);
2512
2513 if (VNC_DEBUG(VERBOSE)) {
2514 struct prefix pfx_nexthop;
2515
2516 rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_nexthop);
2517 vnc_zlog_debug_verbose("%s: pfx %pFX, nh %pFX", __func__,
2518 prefix, &pfx_nexthop);
2519 }
2520 #if DEBUG_RHN_LIST
2521 print_rhn_list(__func__, "ENTER ");
2522 #endif
2523 VNC_RHNCK(enter);
2524
2525 if (!afi) {
2526 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of prefix",
2527 __func__);
2528 return;
2529 }
2530
2531 if (!bgp->rfapi_cfg) {
2532 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2533 __func__);
2534 return;
2535 }
2536
2537 /* check vnc redist flag for bgp direct routes */
2538 if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
2539 vnc_zlog_debug_verbose(
2540 "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
2541 __func__, afi, ZEBRA_ROUTE_BGP_DIRECT);
2542 return;
2543 }
2544
2545 switch (bgp->rfapi_cfg->redist_mode) {
2546 case VNC_REDIST_MODE_PLAIN:
2547 vnc_import_bgp_add_route_mode_plain(bgp, prefix, info);
2548 break;
2549
2550 case VNC_REDIST_MODE_RFG:
2551 if (bgp->rfapi_cfg->rfg_redist)
2552 vnc_import_bgp_add_route_mode_nvegroup(
2553 bgp, prefix, info, bgp->rfapi_cfg->rfg_redist);
2554 else
2555 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2556 __func__);
2557 break;
2558
2559 case VNC_REDIST_MODE_RESOLVE_NVE:
2560 vnc_import_bgp_add_route_mode_resolve_nve(bgp, prefix, info);
2561 break;
2562 }
2563 #if DEBUG_RHN_LIST
2564 print_rhn_list(__func__, "LEAVE ");
2565 #endif
2566 VNC_RHNCK(leave);
2567 }
2568
2569 /*
2570 * "Withdrawing a Route" import process
2571 */
2572 void vnc_import_bgp_del_route(struct bgp *bgp, const struct prefix *prefix,
2573 struct bgp_path_info *info) /* unicast info */
2574 {
2575 afi_t afi = family2afi(prefix->family);
2576
2577 assert(afi);
2578
2579 {
2580 struct prefix pfx_nexthop;
2581
2582 rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_nexthop);
2583 vnc_zlog_debug_verbose("%s: pfx %pFX, nh %pFX", __func__,
2584 prefix, &pfx_nexthop);
2585 }
2586 #if DEBUG_RHN_LIST
2587 print_rhn_list(__func__, "ENTER ");
2588 #endif
2589 VNC_RHNCK(enter);
2590
2591 if (!bgp->rfapi_cfg) {
2592 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2593 __func__);
2594 return;
2595 }
2596
2597 /* check bgp redist flag for vnc direct ("vpn") routes */
2598 if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
2599 vnc_zlog_debug_verbose(
2600 "%s: bgp redistribution of afi=%d VNC direct routes is off",
2601 __func__, afi);
2602 return;
2603 }
2604
2605 switch (bgp->rfapi_cfg->redist_mode) {
2606 case VNC_REDIST_MODE_PLAIN:
2607 vnc_import_bgp_del_route_mode_plain(bgp, prefix, info);
2608 break;
2609
2610 case VNC_REDIST_MODE_RFG:
2611 if (bgp->rfapi_cfg->rfg_redist)
2612 vnc_import_bgp_del_route_mode_nvegroup(bgp, prefix,
2613 info);
2614 else
2615 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2616 __func__);
2617 break;
2618
2619 case VNC_REDIST_MODE_RESOLVE_NVE:
2620 vnc_import_bgp_del_route_mode_resolve_nve(bgp, afi, prefix,
2621 info);
2622 break;
2623 }
2624 #if DEBUG_RHN_LIST
2625 print_rhn_list(__func__, "LEAVE ");
2626 #endif
2627 VNC_RHNCK(leave);
2628 }
2629
2630
2631 /***********************************************************************
2632 * Enable/Disable
2633 ***********************************************************************/
2634
2635 void vnc_import_bgp_redist_enable(struct bgp *bgp, afi_t afi)
2636 {
2637 /* iterate over bgp unicast v4 and v6 routes, call
2638 * vnc_import_bgp_add_route */
2639
2640 struct bgp_dest *dest;
2641
2642 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
2643
2644 if (bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
2645 vnc_zlog_debug_verbose(
2646 "%s: already enabled for afi %d, skipping", __func__,
2647 afi);
2648 return;
2649 }
2650 bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT] = 1;
2651
2652 for (dest = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); dest;
2653 dest = bgp_route_next(dest)) {
2654
2655 struct bgp_path_info *bpi;
2656
2657 for (bpi = bgp_dest_get_bgp_path_info(dest); bpi;
2658 bpi = bpi->next) {
2659
2660 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
2661 continue;
2662
2663 vnc_import_bgp_add_route(bgp, bgp_dest_get_prefix(dest),
2664 bpi);
2665 }
2666 }
2667 vnc_zlog_debug_verbose(
2668 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2669 __func__, afi, ZEBRA_ROUTE_BGP_DIRECT);
2670 }
2671
2672 void vnc_import_bgp_exterior_redist_enable(struct bgp *bgp, afi_t afi)
2673 {
2674 struct bgp *bgp_exterior;
2675 struct bgp_dest *dest;
2676
2677 bgp_exterior = bgp->rfapi_cfg->redist_bgp_exterior_view;
2678
2679 if (bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
2680 vnc_zlog_debug_verbose(
2681 "%s: already enabled for afi %d, skipping", __func__,
2682 afi);
2683 return;
2684 }
2685 bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT] = 1;
2686
2687 if (!bgp_exterior) {
2688 vnc_zlog_debug_verbose(
2689 "%s: no exterior view set yet, no routes to import yet",
2690 __func__);
2691 return;
2692 }
2693
2694 for (dest = bgp_table_top(bgp_exterior->rib[afi][SAFI_UNICAST]); dest;
2695 dest = bgp_route_next(dest)) {
2696
2697 struct bgp_path_info *bpi;
2698
2699 for (bpi = bgp_dest_get_bgp_path_info(dest); bpi;
2700 bpi = bpi->next) {
2701
2702 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
2703 continue;
2704
2705 vnc_import_bgp_exterior_add_route(
2706 bgp_exterior, bgp_dest_get_prefix(dest), bpi);
2707 }
2708 }
2709 vnc_zlog_debug_verbose(
2710 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2711 __func__, afi, ZEBRA_ROUTE_BGP_DIRECT);
2712 }
2713
2714 /*
2715 * This function is for populating a newly-created Import Table
2716 */
2717 void vnc_import_bgp_exterior_redist_enable_it(
2718 struct bgp *bgp, afi_t afi, struct rfapi_import_table *it_only)
2719 {
2720 struct bgp *bgp_exterior;
2721 struct bgp_dest *dest;
2722
2723 vnc_zlog_debug_verbose("%s: entry", __func__);
2724
2725 bgp_exterior = bgp->rfapi_cfg->redist_bgp_exterior_view;
2726
2727 if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
2728 vnc_zlog_debug_verbose("%s: not enabled for afi %d, skipping",
2729 __func__, afi);
2730 return;
2731 }
2732
2733 if (!bgp_exterior) {
2734 vnc_zlog_debug_verbose(
2735 "%s: no exterior view set yet, no routes to import yet",
2736 __func__);
2737 return;
2738 }
2739
2740 for (dest = bgp_table_top(bgp_exterior->rib[afi][SAFI_UNICAST]); dest;
2741 dest = bgp_route_next(dest)) {
2742
2743 struct bgp_path_info *bpi;
2744
2745 for (bpi = bgp_dest_get_bgp_path_info(dest); bpi;
2746 bpi = bpi->next) {
2747
2748 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
2749 continue;
2750
2751 vnc_import_bgp_exterior_add_route_it(
2752 bgp_exterior, bgp_dest_get_prefix(dest), bpi,
2753 it_only);
2754 }
2755 }
2756 }
2757
2758
2759 void vnc_import_bgp_redist_disable(struct bgp *bgp, afi_t afi)
2760 {
2761 /*
2762 * iterate over vpn routes, find routes of type ZEBRA_ROUTE_BGP_DIRECT,
2763 * delete (call timer expire immediately)
2764 */
2765 struct bgp_dest *dest1;
2766 struct bgp_dest *dest2;
2767
2768 vnc_zlog_debug_verbose("%s: entry", __func__);
2769
2770 if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
2771 vnc_zlog_debug_verbose(
2772 "%s: already disabled for afi %d, skipping", __func__,
2773 afi);
2774 return;
2775 }
2776
2777 /*
2778 * Two-level table for SAFI_MPLS_VPN
2779 * Be careful when changing the things we iterate over
2780 */
2781 for (dest1 = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); dest1;
2782 dest1 = bgp_route_next(dest1)) {
2783 const struct prefix *dest1_p;
2784
2785 if (!bgp_dest_has_bgp_path_info_data(dest1))
2786 continue;
2787
2788 dest1_p = bgp_dest_get_prefix(dest1);
2789 for (dest2 = bgp_table_top(bgp_dest_get_bgp_table_info(dest1));
2790 dest2; dest2 = bgp_route_next(dest2)) {
2791 const struct prefix *dest2_p =
2792 bgp_dest_get_prefix(dest2);
2793 struct bgp_path_info *bpi;
2794 struct bgp_path_info *nextbpi;
2795
2796 for (bpi = bgp_dest_get_bgp_path_info(dest2); bpi;
2797 bpi = nextbpi) {
2798
2799 nextbpi = bpi->next;
2800
2801 if (bpi->type != ZEBRA_ROUTE_BGP_DIRECT)
2802 continue;
2803
2804 struct rfapi_descriptor *rfd;
2805 vncHDBgpDirect.peer = bpi->peer;
2806
2807 assert(bpi->extra);
2808
2809 rfd = bpi->extra->vnc.export.rfapi_handle;
2810
2811 vnc_zlog_debug_verbose(
2812 "%s: deleting bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p [passing rfd=%p]",
2813 __func__, bpi, bpi->peer, bpi->type,
2814 bpi->sub_type,
2815 (bpi->extra ? bpi->extra->vnc.export
2816 .rfapi_handle
2817 : NULL),
2818 rfd);
2819
2820 del_vnc_route(rfd, bpi->peer, bgp,
2821 SAFI_MPLS_VPN, dest2_p,
2822 (struct prefix_rd *)dest1_p,
2823 bpi->type, bpi->sub_type, NULL,
2824 1); /* kill */
2825
2826 vncHDBgpDirect.peer = NULL;
2827 }
2828 }
2829 }
2830 /* Clear RHN list */
2831 if (bgp->rfapi->resolve_nve_nexthop) {
2832 struct prefix_bag *pb;
2833 struct bgp_path_info *info;
2834 while (!skiplist_first(bgp->rfapi->resolve_nve_nexthop, NULL,
2835 (void *)&pb)) {
2836 info = pb->ubpi;
2837 skiplist_delete_first(bgp->rfapi->resolve_nve_nexthop);
2838 bgp_path_info_unlock(info);
2839 }
2840 }
2841
2842 bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT] = 0;
2843 vnc_zlog_debug_verbose("%s: return", __func__);
2844 }
2845
2846
2847 void vnc_import_bgp_exterior_redist_disable(struct bgp *bgp, afi_t afi)
2848 {
2849 struct rfapi_cfg *hc = bgp->rfapi_cfg;
2850 struct bgp *bgp_exterior = hc->redist_bgp_exterior_view;
2851
2852 vnc_zlog_debug_verbose("%s: entry", __func__);
2853
2854 if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
2855 vnc_zlog_debug_verbose(
2856 "%s: already disabled for afi %d, skipping", __func__,
2857 afi);
2858 return;
2859 }
2860
2861 if (!bgp_exterior) {
2862 vnc_zlog_debug_verbose(
2863 "%s: bgp exterior view not defined, skipping",
2864 __func__);
2865 return;
2866 }
2867
2868
2869 {
2870 struct bgp_dest *dest;
2871 for (dest = bgp_table_top(bgp_exterior->rib[afi][SAFI_UNICAST]);
2872 dest; dest = bgp_route_next(dest)) {
2873
2874 struct bgp_path_info *bpi;
2875
2876 for (bpi = bgp_dest_get_bgp_path_info(dest); bpi;
2877 bpi = bpi->next) {
2878
2879 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
2880 continue;
2881
2882 vnc_import_bgp_exterior_del_route(
2883 bgp_exterior, bgp_dest_get_prefix(dest),
2884 bpi);
2885 }
2886 }
2887 #if DEBUG_RHN_LIST
2888 print_rhn_list(__func__, NULL);
2889 #endif
2890 }
2891
2892 bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT] = 0;
2893 vnc_zlog_debug_verbose("%s: return", __func__);
2894 }