]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/rfapi/vnc_import_bgp.c
Merge pull request #12916 from donaldsharp/clang_15_warnings
[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 if (iattr)
838 bgp_attr_unintern(&iattr);
839 }
840
841 static void vnc_import_bgp_add_route_mode_nvegroup(
842 struct bgp *bgp, const struct prefix *prefix,
843 struct bgp_path_info *info, struct rfapi_nve_group_cfg *rfg)
844 {
845 afi_t afi = family2afi(prefix->family);
846 struct peer *peer = info->peer;
847 struct attr *attr = info->attr;
848 struct attr hattr;
849 struct attr *iattr = NULL;
850
851 struct rfapi_ip_addr vnaddr;
852 struct prefix *vn_pfx = NULL;
853 int ahr_flags = 0;
854 struct ecommunity *ecom = NULL;
855 struct prefix_rd prd;
856 struct route_map *rmap = NULL;
857 uint32_t local_pref;
858
859 vnc_zlog_debug_verbose("%s(prefix=%pFX) entry", __func__, prefix);
860
861 assert(rfg);
862
863 if (!afi) {
864 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of prefix",
865 __func__);
866 return;
867 }
868
869 if (!(bgp->rfapi_cfg)) {
870 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
871 __func__);
872 return;
873 }
874
875 /* check vnc redist flag for bgp direct routes */
876 if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
877 vnc_zlog_debug_verbose(
878 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
879 __func__, afi);
880 return;
881 }
882
883
884 /*
885 * RFG-specific code
886 */
887 {
888
889 struct rfapi_ip_prefix pfx_un;
890
891 vnc_zlog_debug_verbose("%s: using redist RFG", __func__);
892
893 /*
894 * RFG prefix list check
895 */
896 if (rfg->plist_redist[ZEBRA_ROUTE_BGP_DIRECT][afi]) {
897 vnc_zlog_debug_verbose(
898 "%s: RFG prefix list is set, checking",
899 __func__);
900 if (prefix_list_apply(
901 rfg->plist_redist[ZEBRA_ROUTE_BGP_DIRECT]
902 [afi],
903 prefix)
904 == PREFIX_DENY) {
905 vnc_zlog_debug_verbose(
906 "%s: prefix list returns DENY, blocking route",
907 __func__);
908 return;
909 }
910 vnc_zlog_debug_verbose(
911 "%s: prefix list returns PASS, allowing route",
912 __func__);
913 }
914
915 /* apply routemap, if any, later */
916 rmap = rfg->routemap_redist[ZEBRA_ROUTE_BGP_DIRECT];
917
918 /*
919 * export nve group's VN addr prefix must be a /32 which
920 * will yield the VN addr to use
921 */
922 vn_pfx = &rfg->vn_prefix;
923
924 /*
925 * UN Address
926 */
927 if (!is_host_prefix(&rfg->un_prefix)) {
928 /* NB prefixlen==0 means it has not been configured */
929 vnc_zlog_debug_verbose(
930 "%s: redist RFG UN pfx not host pfx (plen=%d), skipping",
931 __func__, rfg->un_prefix.prefixlen);
932 return;
933 }
934
935 rfapiQprefix2Rprefix(&rfg->un_prefix, &pfx_un);
936
937 vncHDBgpDirect.un_addr = pfx_un.prefix;
938 }
939
940 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE))
941 vnc_zlog_debug_any("%s vn_pfx=%pFX", __func__, vn_pfx);
942
943 /*
944 * Compute VN address
945 */
946 if (rfapiQprefix2Raddr(vn_pfx, &vnaddr)) {
947 vnc_zlog_debug_verbose("%s: redist VN invalid, skipping",
948 __func__);
949 return;
950 }
951
952 /*
953 * route map handling
954 * This code is here because it allocates an interned attr which
955 * must be freed before we return. It's easier to put it after
956 * all of the possible returns above.
957 */
958 memset(&hattr, 0, sizeof(hattr));
959 /* hattr becomes a ghost attr */
960 hattr = *attr;
961
962 if (rmap) {
963 struct bgp_path_info path;
964 route_map_result_t ret;
965
966 memset(&path, 0, sizeof(path));
967 path.peer = peer;
968 path.attr = &hattr;
969 ret = route_map_apply(rmap, prefix, &path);
970 if (ret == RMAP_DENYMATCH) {
971 bgp_attr_flush(&hattr);
972 vnc_zlog_debug_verbose(
973 "%s: route map \"%s\" says DENY, returning",
974 __func__, rmap->name);
975 return;
976 }
977 }
978
979 iattr = bgp_attr_intern(&hattr);
980 bgp_attr_flush(&hattr);
981
982 /* Now iattr is an allocated interned attr */
983
984 /*
985 * RFG-specific code
986 *
987 * Sets RD in dummy HD
988 * Allocates ecom
989 */
990 {
991
992 memset(&prd, 0, sizeof(prd));
993 prd = rfg->rd;
994 prd.family = AF_UNSPEC;
995 prd.prefixlen = 64;
996
997 if (rfg->rd.family == AF_UNIX) {
998 rfapi_set_autord_from_vn(&prd, &vnaddr);
999 }
1000
1001 if (rfg->rt_export_list)
1002 ecom = ecommunity_dup(
1003 bgp->rfapi_cfg->rfg_redist->rt_export_list);
1004 else
1005 ecom = ecommunity_new();
1006
1007 if (iattr && bgp_attr_get_ecommunity(iattr))
1008 ecom = ecommunity_merge(ecom,
1009 bgp_attr_get_ecommunity(iattr));
1010 }
1011
1012 local_pref = calc_local_pref(iattr, peer);
1013
1014 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE)) {
1015 char buf[BUFSIZ];
1016
1017 buf[0] = 0;
1018 rfapiRfapiIpAddr2Str(&vnaddr, buf, BUFSIZ);
1019 buf[BUFSIZ - 1] = 0;
1020 vnc_zlog_debug_any("%s: setting vnaddr to %s", __func__, buf);
1021 }
1022
1023 vncHDBgpDirect.peer = peer;
1024 add_vnc_route(&vncHDBgpDirect, bgp, SAFI_MPLS_VPN, prefix, &prd,
1025 &vnaddr, &local_pref, &(bgp->rfapi_cfg->redist_lifetime),
1026 NULL, /* RFP options */
1027 NULL, NULL, ecom, NULL, /* med */
1028 NULL, /* label: default */
1029 ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE,
1030 ahr_flags);
1031 vncHDBgpDirect.peer = NULL;
1032
1033 if (ecom)
1034 ecommunity_free(&ecom);
1035 if (iattr)
1036 bgp_attr_unintern(&iattr);
1037 }
1038
1039 static void vnc_import_bgp_del_route_mode_plain(struct bgp *bgp,
1040 const struct prefix *prefix,
1041 struct bgp_path_info *info)
1042 {
1043 struct prefix_rd prd;
1044 afi_t afi = family2afi(prefix->family);
1045 struct prefix *vn_pfx = NULL;
1046 struct rfapi_ip_addr vnaddr;
1047 struct prefix vn_pfx_space;
1048
1049
1050 assert(afi);
1051
1052 /*
1053 * Compute VN address
1054 */
1055
1056 if (info) {
1057 rfapiUnicastNexthop2Prefix(afi, info->attr, &vn_pfx_space);
1058 } else {
1059 vnc_zlog_debug_verbose("%s: no attr, can't delete route",
1060 __func__);
1061 return;
1062 }
1063 vn_pfx = &vn_pfx_space;
1064
1065 vnaddr.addr_family = vn_pfx->family;
1066 switch (vn_pfx->family) {
1067 case AF_INET:
1068 if (vn_pfx->prefixlen != IPV4_MAX_BITLEN) {
1069 vnc_zlog_debug_verbose(
1070 "%s: redist VN plen (%d) != 32, skipping",
1071 __func__, vn_pfx->prefixlen);
1072 return;
1073 }
1074 vnaddr.addr.v4 = vn_pfx->u.prefix4;
1075 break;
1076
1077 case AF_INET6:
1078 if (vn_pfx->prefixlen != IPV6_MAX_BITLEN) {
1079 vnc_zlog_debug_verbose(
1080 "%s: redist VN plen (%d) != 128, skipping",
1081 __func__, vn_pfx->prefixlen);
1082 return;
1083 }
1084 vnaddr.addr.v6 = vn_pfx->u.prefix6;
1085 break;
1086
1087 default:
1088 vnc_zlog_debug_verbose(
1089 "%s: no redist RFG VN host pfx configured, skipping",
1090 __func__);
1091 return;
1092 }
1093
1094
1095 memset(&prd, 0, sizeof(prd));
1096 if (rfapi_set_autord_from_vn(&prd, &vnaddr)) {
1097 vnc_zlog_debug_verbose("%s: can't auto-assign RD, skipping",
1098 __func__);
1099 return;
1100 }
1101
1102 vncHDBgpDirect.peer = info->peer;
1103 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__,
1104 vncHDBgpDirect.peer);
1105 del_vnc_route(&vncHDBgpDirect, info->peer, bgp, SAFI_MPLS_VPN, prefix,
1106 &prd, ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE,
1107 NULL, 1);
1108
1109 vncHDBgpDirect.peer = NULL;
1110 }
1111
1112 static void vnc_import_bgp_del_route_mode_nvegroup(struct bgp *bgp,
1113 const struct prefix *prefix,
1114 struct bgp_path_info *info)
1115 {
1116 struct prefix_rd prd;
1117 afi_t afi = family2afi(prefix->family);
1118 struct rfapi_nve_group_cfg *rfg = NULL;
1119 struct prefix *vn_pfx = NULL;
1120 struct rfapi_ip_addr vnaddr;
1121
1122
1123 assert(afi);
1124
1125 rfg = bgp->rfapi_cfg->rfg_redist;
1126 assert(rfg);
1127
1128 /*
1129 * Compute VN address
1130 */
1131
1132 /*
1133 * export nve group's VN addr prefix must be a /32 which
1134 * will yield the VN addr to use
1135 */
1136 vn_pfx = &rfg->vn_prefix;
1137
1138
1139 vnaddr.addr_family = vn_pfx->family;
1140 switch (vn_pfx->family) {
1141 case AF_INET:
1142 if (vn_pfx->prefixlen != IPV4_MAX_BITLEN) {
1143 vnc_zlog_debug_verbose(
1144 "%s: redist VN plen (%d) != 32, skipping",
1145 __func__, vn_pfx->prefixlen);
1146 return;
1147 }
1148 vnaddr.addr.v4 = vn_pfx->u.prefix4;
1149 break;
1150
1151 case AF_INET6:
1152 if (vn_pfx->prefixlen != IPV6_MAX_BITLEN) {
1153 vnc_zlog_debug_verbose(
1154 "%s: redist VN plen (%d) != 128, skipping",
1155 __func__, vn_pfx->prefixlen);
1156 return;
1157 }
1158 vnaddr.addr.v6 = vn_pfx->u.prefix6;
1159 break;
1160
1161 default:
1162 vnc_zlog_debug_verbose(
1163 "%s: no redist RFG VN host pfx configured, skipping",
1164 __func__);
1165 return;
1166 }
1167
1168 memset(&prd, 0, sizeof(prd));
1169 prd = rfg->rd;
1170 prd.family = AF_UNSPEC;
1171 prd.prefixlen = 64;
1172
1173 if (rfg->rd.family == AF_UNIX) {
1174 /* means "auto" with VN addr */
1175 if (rfapi_set_autord_from_vn(&prd, &vnaddr)) {
1176 vnc_zlog_debug_verbose(
1177 "%s: can't auto-assign RD, skipping", __func__);
1178 return;
1179 }
1180 }
1181
1182
1183 vncHDBgpDirect.peer = info->peer;
1184 vnc_zlog_debug_verbose("%s: setting peer to %p", __func__,
1185 vncHDBgpDirect.peer);
1186 del_vnc_route(&vncHDBgpDirect, info->peer, bgp, SAFI_MPLS_VPN, prefix,
1187 &prd, ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE,
1188 NULL, 1);
1189
1190 vncHDBgpDirect.peer = NULL;
1191 }
1192
1193 static void vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1194 struct bgp *bgp, afi_t afi, struct bgp_path_info *bpi, /* VPN bpi */
1195 struct prefix_rd *prd, /* RD */
1196 const struct prefix *prefix) /* unicast route prefix */
1197 {
1198 struct prefix un;
1199
1200 if (bpi->type != ZEBRA_ROUTE_BGP
1201 && bpi->type != ZEBRA_ROUTE_BGP_DIRECT) {
1202
1203 return;
1204 }
1205 if (bpi->sub_type != BGP_ROUTE_NORMAL
1206 && bpi->sub_type != BGP_ROUTE_STATIC
1207 && bpi->sub_type != BGP_ROUTE_RFP) {
1208
1209 return;
1210 }
1211 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
1212 return;
1213
1214 vncHDResolveNve.peer = bpi->peer;
1215 if (!rfapiGetVncTunnelUnAddr(bpi->attr, &un)) {
1216 if (rfapiQprefix2Raddr(&un, &vncHDResolveNve.un_addr))
1217 return;
1218 } else {
1219 memset(&vncHDResolveNve.un_addr, 0,
1220 sizeof(vncHDResolveNve.un_addr));
1221 }
1222
1223 del_vnc_route(&vncHDResolveNve, vncHDResolveNve.peer, bgp,
1224 SAFI_MPLS_VPN, prefix, /* unicast route prefix */
1225 prd, ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL,
1226 0); /* flags */
1227 }
1228
1229 static void vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1230 struct prefix_rd *prd,
1231 struct bgp_table *table_rd, /* per-rd VPN route table */
1232 afi_t afi, struct bgp *bgp,
1233 const struct prefix *prefix, /* unicast prefix */
1234 const struct prefix *ubpi_nexthop) /* unicast bpi's nexthop */
1235 {
1236 struct bgp_dest *bd;
1237 struct bgp_path_info *bpi;
1238
1239 if (!table_rd)
1240 return;
1241
1242 vnc_zlog_debug_verbose("%s: ubpi_nexthop=%pFX", __func__, ubpi_nexthop);
1243
1244
1245 /* exact match */
1246 bd = bgp_node_lookup(table_rd, ubpi_nexthop);
1247 if (!bd) {
1248 vnc_zlog_debug_verbose(
1249 "%s: no match in RD's table for ubpi_nexthop",
1250 __func__);
1251 return;
1252 }
1253
1254 /* Iterate over bgp_info items at this node */
1255 for (bpi = bgp_dest_get_bgp_path_info(bd); bpi; bpi = bpi->next) {
1256
1257 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1258 bgp, afi, bpi, /* VPN bpi */
1259 prd, /* VPN RD */
1260 prefix); /* unicast route prefix */
1261 }
1262
1263 bgp_dest_unlock_node(bd);
1264 }
1265
1266 static void
1267 vnc_import_bgp_del_route_mode_resolve_nve(struct bgp *bgp, afi_t afi,
1268 const struct prefix *prefix,
1269 struct bgp_path_info *info)
1270 {
1271 struct ecommunity *ecom = NULL;
1272 struct prefix pfx_unicast_nexthop = {0}; /* happy valgrind */
1273
1274 // struct listnode *hnode;
1275 // struct rfapi_descriptor *rfd;
1276 struct prefix_bag *pb;
1277 void *cursor;
1278 struct skiplist *sl = bgp->rfapi->resolve_nve_nexthop;
1279 int rc;
1280 struct bgp_dest *bdp; /* prd table node */
1281
1282 if (!sl) {
1283 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1284 __func__);
1285 return;
1286 }
1287
1288 if (info->type != ZEBRA_ROUTE_BGP) {
1289 vnc_zlog_debug_verbose(
1290 "%s: unicast type %d=\"%s\" is not %d=%s, skipping",
1291 __func__, info->type, zebra_route_string(info->type),
1292 ZEBRA_ROUTE_BGP, "ZEBRA_ROUTE_BGP");
1293 return;
1294 }
1295
1296 if (process_unicast_route(bgp, afi, prefix, info, &ecom,
1297 &pfx_unicast_nexthop)) {
1298
1299 vnc_zlog_debug_verbose(
1300 "%s: process_unicast_route error, skipping", __func__);
1301 return;
1302 }
1303
1304 rc = skiplist_first_value(sl, &pfx_unicast_nexthop, (void *)&pb,
1305 &cursor);
1306 while (!rc) {
1307 if (pb->ubpi == info) {
1308 skiplist_delete(sl, &pfx_unicast_nexthop, pb);
1309 bgp_path_info_unlock(info);
1310 break;
1311 }
1312 rc = skiplist_next_value(sl, &pfx_unicast_nexthop, (void *)&pb,
1313 &cursor);
1314 }
1315
1316 /*
1317 * Iterate over RDs in VPN RIB. For each RD, look up unicast nexthop
1318 * (exact match, /32). If an exact match is found, call add_vnc_route.
1319 */
1320
1321 for (bdp = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); bdp;
1322 bdp = bgp_route_next(bdp)) {
1323
1324 struct bgp_table *table;
1325
1326 table = bgp_dest_get_bgp_table_info(bdp);
1327
1328 if (!table)
1329 continue;
1330
1331 vnc_import_bgp_del_route_mode_resolve_nve_one_rd(
1332 (struct prefix_rd *)bgp_dest_get_prefix(bdp), table,
1333 afi, bgp, prefix, &pfx_unicast_nexthop);
1334 }
1335
1336 if (ecom)
1337 ecommunity_free(&ecom);
1338 }
1339
1340
1341 /***********************************************************************
1342 * Add/Delete CE->NVE routes
1343 ***********************************************************************/
1344
1345 /*
1346 * Should be called whan a bpi is added to VPN RIB. This function
1347 * will check if it is a host route and return immediately if not.
1348 */
1349 void vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
1350 struct bgp *bgp, struct prefix_rd *prd, /* RD */
1351 struct bgp_table *table_rd, /* per-rd VPN route table */
1352 const struct prefix *prefix, /* VPN prefix */
1353 struct bgp_path_info *bpi) /* new VPN host route */
1354 {
1355 afi_t afi = family2afi(prefix->family);
1356 struct skiplist *sl = NULL;
1357 int rc;
1358 struct prefix_bag *pb;
1359 void *cursor;
1360 struct rfapi_cfg *hc = NULL;
1361
1362 vnc_zlog_debug_verbose("%s: entry", __func__);
1363
1364 if (afi != AFI_IP && afi != AFI_IP6) {
1365 vnc_zlog_debug_verbose("%s: bad afi %d, skipping", __func__,
1366 afi);
1367 return;
1368 }
1369
1370 if (!(hc = bgp->rfapi_cfg)) {
1371 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1372 __func__);
1373 return;
1374 }
1375
1376 /* check vnc redist flag for bgp direct routes */
1377 if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
1378 vnc_zlog_debug_verbose(
1379 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1380 __func__, afi);
1381 return;
1382 }
1383
1384 if (hc->redist_mode != VNC_REDIST_MODE_RESOLVE_NVE) {
1385 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1386 __func__);
1387 return;
1388 }
1389
1390 if (bgp->rfapi)
1391 sl = bgp->rfapi->resolve_nve_nexthop;
1392
1393 if (!sl) {
1394 vnc_zlog_debug_verbose(
1395 "%s: no resolve_nve_nexthop skiplist, skipping",
1396 __func__);
1397 return;
1398 }
1399
1400 if (!is_host_prefix(prefix)) {
1401 vnc_zlog_debug_verbose("%s: not host prefix, skipping",
1402 __func__);
1403 return;
1404 }
1405
1406 rc = skiplist_first_value(sl, prefix, (void *)&pb, &cursor);
1407 while (!rc) {
1408 struct ecommunity *ecom;
1409 struct prefix pfx_unicast_nexthop;
1410 uint32_t *med = NULL;
1411 uint32_t local_pref;
1412
1413 memset(&pfx_unicast_nexthop, 0,
1414 sizeof(pfx_unicast_nexthop)); /* keep valgrind happy */
1415
1416 if (VNC_DEBUG(IMPORT_BGP_ADD_ROUTE))
1417 vnc_zlog_debug_any(
1418 "%s: examining RHN Entry (q=%p): upfx=%pFX, hpfx=%pFX, ubpi=%p",
1419 __func__, cursor, &pb->upfx, &pb->hpfx,
1420 pb->ubpi);
1421
1422 if (process_unicast_route(bgp, afi, &pb->upfx, pb->ubpi, &ecom,
1423 &pfx_unicast_nexthop)) {
1424
1425 vnc_zlog_debug_verbose(
1426 "%s: process_unicast_route error, skipping",
1427 __func__);
1428 continue;
1429 }
1430 local_pref = calc_local_pref(pb->ubpi->attr, pb->ubpi->peer);
1431
1432 if (pb->ubpi->attr->flag
1433 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
1434 med = &pb->ubpi->attr->med;
1435
1436 /*
1437 * Sanity check
1438 */
1439 if (vnc_prefix_cmp(&pfx_unicast_nexthop, prefix)) {
1440 vnc_zlog_debug_verbose(
1441 "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %pFX != nve pfx %pFX",
1442 __func__, &pfx_unicast_nexthop, prefix);
1443 assert(0);
1444 }
1445
1446 vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
1447 bgp, afi, bpi, /* VPN bpi */
1448 prd, &pb->upfx, /* unicast prefix */
1449 &local_pref, med, ecom);
1450
1451 if (ecom)
1452 ecommunity_free(&ecom);
1453
1454 #if DEBUG_RHN_LIST
1455 /* debug */
1456 {
1457 vnc_zlog_debug_verbose(
1458 "%s: advancing past RHN Entry (q=%p): with prefix %pFX",
1459 __func__, cursor, prefix);
1460 print_rhn_list(__func__, NULL); /* debug */
1461 }
1462 #endif
1463 rc = skiplist_next_value(sl, prefix, (void *)&pb, &cursor);
1464 }
1465 vnc_zlog_debug_verbose("%s: done", __func__);
1466 }
1467
1468
1469 void vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
1470 struct bgp *bgp, struct prefix_rd *prd, /* RD */
1471 struct bgp_table *table_rd, /* per-rd VPN route table */
1472 const struct prefix *prefix, /* VPN prefix */
1473 struct bgp_path_info *bpi) /* old VPN host route */
1474 {
1475 afi_t afi = family2afi(prefix->family);
1476 struct skiplist *sl = NULL;
1477 struct prefix_bag *pb;
1478 void *cursor;
1479 struct rfapi_cfg *hc = NULL;
1480 int rc;
1481
1482 vnc_zlog_debug_verbose("%s(bgp=%p, nve prefix=%pFX)", __func__, bgp,
1483 prefix);
1484
1485 if (afi != AFI_IP && afi != AFI_IP6)
1486 return;
1487
1488 if (!(hc = bgp->rfapi_cfg)) {
1489 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
1490 __func__);
1491 return;
1492 }
1493
1494 /* check vnc redist flag for bgp direct routes */
1495 if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
1496 vnc_zlog_debug_verbose(
1497 "%s: bgp->rfapi_cfg->redist[afi=%d][type=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
1498 __func__, afi);
1499 return;
1500 }
1501
1502 if (hc->redist_mode != VNC_REDIST_MODE_RESOLVE_NVE) {
1503 vnc_zlog_debug_verbose("%s: not in resolve-nve mode, skipping",
1504 __func__);
1505 return;
1506 }
1507
1508 if (bgp->rfapi)
1509 sl = bgp->rfapi->resolve_nve_nexthop;
1510
1511 if (!sl) {
1512 vnc_zlog_debug_verbose("%s: no RHN entries, skipping",
1513 __func__);
1514 return;
1515 }
1516
1517 if (!is_host_prefix(prefix)) {
1518 vnc_zlog_debug_verbose("%s: not host route, skip", __func__);
1519 return;
1520 }
1521
1522 /*
1523 * Find all entries with key == CE in the RHN list
1524 */
1525 rc = skiplist_first_value(sl, prefix, (void *)&pb, &cursor);
1526 while (!rc) {
1527
1528 struct ecommunity *ecom;
1529 struct prefix pfx_unicast_nexthop;
1530
1531 memset(&pfx_unicast_nexthop, 0,
1532 sizeof(pfx_unicast_nexthop)); /* keep valgrind happy */
1533
1534 if (process_unicast_route(bgp, afi, &pb->upfx, pb->ubpi, &ecom,
1535 &pfx_unicast_nexthop)) {
1536
1537 vnc_zlog_debug_verbose(
1538 "%s: process_unicast_route error, skipping",
1539 __func__);
1540 continue;
1541 }
1542
1543 /*
1544 * Sanity check
1545 */
1546 if (vnc_prefix_cmp(&pfx_unicast_nexthop, prefix)) {
1547 vnc_zlog_debug_verbose(
1548 "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %pFX != nve pfx %pFX",
1549 __func__, &pfx_unicast_nexthop, prefix);
1550 assert(0);
1551 }
1552
1553 vnc_import_bgp_del_route_mode_resolve_nve_one_bi(
1554 bgp, afi, bpi, prd, &pb->upfx);
1555
1556 if (ecom)
1557 ecommunity_free(&ecom);
1558
1559 rc = skiplist_next_value(sl, prefix, (void *)&pb, &cursor);
1560 }
1561 }
1562
1563
1564 /***********************************************************************
1565 * Exterior Routes
1566 ***********************************************************************/
1567
1568 #define DEBUG_IS_USABLE_INTERIOR 1
1569
1570 static int is_usable_interior_route(struct bgp_path_info *bpi_interior)
1571 {
1572 if (!VALID_INTERIOR_TYPE(bpi_interior->type)) {
1573 #if DEBUG_IS_USABLE_INTERIOR
1574 vnc_zlog_debug_verbose(
1575 "%s: NO: type %d is not valid interior type", __func__,
1576 bpi_interior->type);
1577 #endif
1578 return 0;
1579 }
1580 if (!CHECK_FLAG(bpi_interior->flags, BGP_PATH_VALID)) {
1581 #if DEBUG_IS_USABLE_INTERIOR
1582 vnc_zlog_debug_verbose("%s: NO: BGP_PATH_VALID not set",
1583 __func__);
1584 #endif
1585 return 0;
1586 }
1587 return 1;
1588 }
1589
1590 /*
1591 * There should be only one of these per prefix at a time.
1592 * This should be called as a result of selection operation
1593 *
1594 * NB should be called espacially for bgp instances that are named,
1595 * because the exterior routes will always come from one of those.
1596 * We filter here on the instance name to make sure we get only the
1597 * right routes.
1598 */
1599 static void vnc_import_bgp_exterior_add_route_it(
1600 struct bgp *bgp, /* exterior instance, we hope */
1601 const struct prefix *prefix, /* unicast prefix */
1602 struct bgp_path_info *info, /* unicast info */
1603 struct rfapi_import_table *it_only) /* NULL, or limit to this IT */
1604 {
1605 struct rfapi *h;
1606 struct rfapi_cfg *hc;
1607 struct prefix pfx_orig_nexthop;
1608 struct rfapi_import_table *it;
1609 struct bgp *bgp_default = bgp_get_default();
1610 afi_t afi = family2afi(prefix->family);
1611
1612 if (!bgp_default)
1613 return;
1614
1615 h = bgp_default->rfapi;
1616 hc = bgp_default->rfapi_cfg;
1617
1618 vnc_zlog_debug_verbose("%s: entry with it=%p", __func__, it_only);
1619
1620 if (!h || !hc) {
1621 vnc_zlog_debug_verbose(
1622 "%s: rfapi or rfapi_cfg not instantiated, skipping",
1623 __func__);
1624 return;
1625 }
1626 if (!hc->redist_bgp_exterior_view) {
1627 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1628 __func__);
1629 return;
1630 }
1631 if (bgp != hc->redist_bgp_exterior_view) {
1632 vnc_zlog_debug_verbose(
1633 "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1634 __func__, bgp, hc->redist_bgp_exterior_view);
1635 return;
1636 }
1637
1638 if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
1639 vnc_zlog_debug_verbose(
1640 "%s: redist of exterior routes not enabled, skipping",
1641 __func__);
1642 return;
1643 }
1644
1645 /*
1646 * Extract nexthop from exterior route
1647 *
1648 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1649 * but if v4 it is in attr->nexthop
1650 */
1651 rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_orig_nexthop);
1652
1653 for (it = h->imports; it; it = it->next) {
1654 struct agg_table *table;
1655 struct agg_node *rn;
1656 struct agg_node *par;
1657 struct bgp_path_info *bpi_interior;
1658 int have_usable_route;
1659
1660 vnc_zlog_debug_verbose("%s: doing it %p", __func__, it);
1661
1662 if (it_only && (it_only != it)) {
1663 vnc_zlog_debug_verbose("%s: doesn't match it_only %p",
1664 __func__, it_only);
1665 continue;
1666 }
1667
1668 table = it->imported_vpn[afi];
1669
1670 for (rn = agg_node_match(table, &pfx_orig_nexthop),
1671 have_usable_route = 0;
1672 (!have_usable_route) && rn;) {
1673
1674 vnc_zlog_debug_verbose("%s: it %p trying rn %p",
1675 __func__, it, rn);
1676
1677 for (bpi_interior = rn->info; bpi_interior;
1678 bpi_interior = bpi_interior->next) {
1679 struct prefix_rd *prd;
1680 struct attr new_attr;
1681 uint32_t label = 0;
1682
1683 if (!is_usable_interior_route(bpi_interior))
1684 continue;
1685
1686 vnc_zlog_debug_verbose(
1687 "%s: usable: bpi_interior %p", __func__,
1688 bpi_interior);
1689
1690 /*
1691 * have a legitimate route to exterior's nexthop
1692 * via NVE.
1693 *
1694 * Import unicast route to the import table
1695 */
1696 have_usable_route = 1;
1697
1698 if (bpi_interior->extra) {
1699 prd = &bpi_interior->extra->vnc.import
1700 .rd;
1701 label = decode_label(
1702 &bpi_interior->extra->label[0]);
1703 } else
1704 prd = NULL;
1705
1706 /* use local_pref from unicast route */
1707 memset(&new_attr, 0, sizeof(new_attr));
1708 new_attr = *bpi_interior->attr;
1709 if (info->attr->flag
1710 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
1711 new_attr.local_pref =
1712 info->attr->local_pref;
1713 new_attr.flag |= ATTR_FLAG_BIT(
1714 BGP_ATTR_LOCAL_PREF);
1715 }
1716
1717 rfapiBgpInfoFilteredImportVPN(
1718 it, FIF_ACTION_UPDATE,
1719 bpi_interior->peer, NULL, /* rfd */
1720 prefix, NULL, afi, prd, &new_attr,
1721 ZEBRA_ROUTE_BGP_DIRECT_EXT,
1722 BGP_ROUTE_REDISTRIBUTE, &label);
1723 }
1724
1725 if (have_usable_route) {
1726 /*
1727 * Make monitor
1728 *
1729 * TBD factor this out into its own function
1730 */
1731 struct prefix *pfx_mon = prefix_new();
1732 if (!RFAPI_MONITOR_EXTERIOR(rn)->source) {
1733 RFAPI_MONITOR_EXTERIOR(rn)->source =
1734 skiplist_new(
1735 0, NULL,
1736 prefix_free_lists);
1737 agg_lock_node(rn); /* for skiplist */
1738 }
1739 agg_lock_node(rn); /* for skiplist entry */
1740 prefix_copy(pfx_mon, prefix);
1741 if (!skiplist_insert(
1742 RFAPI_MONITOR_EXTERIOR(rn)->source,
1743 info, pfx_mon)) {
1744
1745 bgp_path_info_lock(info);
1746 }
1747 }
1748 par = agg_node_parent(rn);
1749 if (par)
1750 agg_lock_node(par);
1751 agg_unlock_node(rn);
1752 rn = par;
1753 }
1754 if (rn)
1755 agg_unlock_node(rn);
1756
1757 if (!have_usable_route) {
1758 struct prefix *pfx_mon = prefix_new();
1759 prefix_copy(pfx_mon, prefix);
1760 if (!skiplist_insert(it->monitor_exterior_orphans, info,
1761 pfx_mon)) {
1762
1763 bgp_path_info_lock(info);
1764 }
1765 }
1766 }
1767 }
1768
1769 void vnc_import_bgp_exterior_add_route(
1770 struct bgp *bgp, /* exterior instance, we hope */
1771 const struct prefix *prefix, /* unicast prefix */
1772 struct bgp_path_info *info) /* unicast info */
1773 {
1774 vnc_import_bgp_exterior_add_route_it(bgp, prefix, info, NULL);
1775 }
1776
1777 /*
1778 * There should be only one of these per prefix at a time.
1779 * This should probably be called as a result of selection operation.
1780 *
1781 * NB should be called espacially for bgp instances that are named,
1782 * because the exterior routes will always come from one of those.
1783 * We filter here on the instance name to make sure we get only the
1784 * right routes.
1785 */
1786 void vnc_import_bgp_exterior_del_route(
1787 struct bgp *bgp, const struct prefix *prefix, /* unicast prefix */
1788 struct bgp_path_info *info) /* unicast info */
1789 {
1790 struct rfapi *h;
1791 struct rfapi_cfg *hc;
1792 struct rfapi_import_table *it;
1793 struct prefix pfx_orig_nexthop;
1794 afi_t afi = family2afi(prefix->family);
1795 struct bgp *bgp_default = bgp_get_default();
1796
1797 if (!bgp_default)
1798 return;
1799
1800 memset(&pfx_orig_nexthop, 0,
1801 sizeof(pfx_orig_nexthop)); /* keep valgrind happy */
1802
1803 h = bgp_default->rfapi;
1804 hc = bgp_default->rfapi_cfg;
1805
1806 if (!h || !hc) {
1807 vnc_zlog_debug_verbose(
1808 "%s: rfapi or rfapi_cfg not instantiated, skipping",
1809 __func__);
1810 return;
1811 }
1812 if (!hc->redist_bgp_exterior_view) {
1813 vnc_zlog_debug_verbose("%s: exterior view not set, skipping",
1814 __func__);
1815 return;
1816 }
1817 if (bgp != hc->redist_bgp_exterior_view) {
1818 vnc_zlog_debug_verbose(
1819 "%s: bgp %p != hc->redist_bgp_exterior_view %p, skipping",
1820 __func__, bgp, hc->redist_bgp_exterior_view);
1821 return;
1822 }
1823 if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
1824 vnc_zlog_debug_verbose(
1825 "%s: redist of exterior routes no enabled, skipping",
1826 __func__);
1827 return;
1828 }
1829
1830 /*
1831 * Extract nexthop from exterior route
1832 *
1833 * Incoming prefix is unicast. If v6, it is in multiprotocol area,
1834 * but if v4 it is in attr->nexthop
1835 */
1836 rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_orig_nexthop);
1837
1838 for (it = h->imports; it; it = it->next) {
1839 struct agg_table *table;
1840 struct agg_node *rn;
1841 struct agg_node *par;
1842 struct bgp_path_info *bpi_interior;
1843 int have_usable_route;
1844
1845 table = it->imported_vpn[afi];
1846
1847 for (rn = agg_node_match(table, &pfx_orig_nexthop),
1848 have_usable_route = 0;
1849 (!have_usable_route) && rn;) {
1850
1851 for (bpi_interior = rn->info; bpi_interior;
1852 bpi_interior = bpi_interior->next) {
1853 struct prefix_rd *prd;
1854 uint32_t label = 0;
1855
1856 if (!is_usable_interior_route(bpi_interior))
1857 continue;
1858
1859 /*
1860 * have a legitimate route to exterior's nexthop
1861 * via NVE.
1862 *
1863 * Import unicast route to the import table
1864 */
1865 have_usable_route = 1;
1866
1867 if (bpi_interior->extra) {
1868 prd = &bpi_interior->extra->vnc.import
1869 .rd;
1870 label = decode_label(
1871 &bpi_interior->extra->label[0]);
1872 } else
1873 prd = NULL;
1874
1875 rfapiBgpInfoFilteredImportVPN(
1876 it, FIF_ACTION_KILL, bpi_interior->peer,
1877 NULL, /* rfd */
1878 prefix, NULL, afi, prd,
1879 bpi_interior->attr,
1880 ZEBRA_ROUTE_BGP_DIRECT_EXT,
1881 BGP_ROUTE_REDISTRIBUTE, &label);
1882
1883 /*
1884 * Delete monitor
1885 *
1886 * TBD factor this out into its own function
1887 */
1888 {
1889 if (RFAPI_MONITOR_EXTERIOR(rn)
1890 ->source) {
1891 if (!skiplist_delete(
1892 RFAPI_MONITOR_EXTERIOR(
1893 rn)
1894 ->source,
1895 info, NULL)) {
1896
1897 bgp_path_info_unlock(
1898 info);
1899 agg_unlock_node(
1900 rn); /* sl entry
1901 */
1902 }
1903 if (skiplist_empty(
1904 RFAPI_MONITOR_EXTERIOR(
1905 rn)
1906 ->source)) {
1907 skiplist_free(
1908 RFAPI_MONITOR_EXTERIOR(
1909 rn)
1910 ->source);
1911 RFAPI_MONITOR_EXTERIOR(
1912 rn)
1913 ->source = NULL;
1914 agg_unlock_node(
1915 rn); /* skiplist
1916 itself
1917 */
1918 }
1919 }
1920 }
1921 }
1922 par = agg_node_parent(rn);
1923 if (par)
1924 agg_lock_node(par);
1925 agg_unlock_node(rn);
1926 rn = par;
1927 }
1928 if (rn)
1929 agg_unlock_node(rn);
1930
1931 if (!have_usable_route) {
1932 if (!skiplist_delete(it->monitor_exterior_orphans, info,
1933 NULL)) {
1934
1935 bgp_path_info_unlock(info);
1936 }
1937 }
1938 }
1939 }
1940
1941 /*
1942 * This function should be called after a new interior VPN route
1943 * has been added to an import_table.
1944 *
1945 * NB should also be called whenever an existing vpn interior route
1946 * becomes valid (e.g., valid_interior_count is inremented)
1947 */
1948 void vnc_import_bgp_exterior_add_route_interior(
1949 struct bgp *bgp, struct rfapi_import_table *it,
1950 struct agg_node *rn_interior, /* VPN IT node */
1951 struct bgp_path_info *bpi_interior) /* VPN IT route */
1952 {
1953 const struct prefix *p = agg_node_get_prefix(rn_interior);
1954 afi_t afi = family2afi(p->family);
1955 struct agg_node *par;
1956 struct bgp_path_info *bpi_exterior;
1957 struct prefix *pfx_exterior; /* exterior pfx */
1958 void *cursor;
1959 int rc;
1960 struct list *list_adopted;
1961
1962 vnc_zlog_debug_verbose("%s: entry", __func__);
1963
1964 if (!is_usable_interior_route(bpi_interior)) {
1965 vnc_zlog_debug_verbose(
1966 "%s: not usable interior route, skipping", __func__);
1967 return;
1968 }
1969
1970 if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
1971 vnc_zlog_debug_verbose(
1972 "%s: redist of exterior routes no enabled, skipping",
1973 __func__);
1974 return;
1975 }
1976
1977 if (it == bgp->rfapi->it_ce) {
1978 vnc_zlog_debug_verbose("%s: import table is it_ce, skipping",
1979 __func__);
1980 return;
1981 }
1982
1983 /*debugging */
1984 vnc_zlog_debug_verbose("%s: interior prefix=%pRN, bpi type=%d",
1985 __func__, rn_interior, bpi_interior->type);
1986
1987 if (RFAPI_HAS_MONITOR_EXTERIOR(rn_interior)) {
1988
1989 vnc_zlog_debug_verbose(
1990 "%s: has exterior monitor; ext src: %p", __func__,
1991 RFAPI_MONITOR_EXTERIOR(rn_interior)->source);
1992
1993 /*
1994 * There is a monitor here already. Therefore, we do not need
1995 * to do any pulldown. Just construct exterior routes based
1996 * on the new interior route.
1997 */
1998 cursor = NULL;
1999 for (rc = skiplist_next(
2000 RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2001 (void **)&bpi_exterior, (void **)&pfx_exterior,
2002 &cursor);
2003 !rc; rc = skiplist_next(
2004 RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2005 (void **)&bpi_exterior,
2006 (void **)&pfx_exterior, &cursor)) {
2007
2008 struct prefix_rd *prd;
2009 struct attr new_attr;
2010 uint32_t label = 0;
2011
2012 assert(bpi_exterior);
2013 assert(pfx_exterior);
2014
2015 if (bpi_interior->extra) {
2016 prd = &bpi_interior->extra->vnc.import.rd;
2017 label = decode_label(
2018 &bpi_interior->extra->label[0]);
2019 } else
2020 prd = NULL;
2021
2022 /* use local_pref from unicast route */
2023 memset(&new_attr, 0, sizeof(struct attr));
2024 new_attr = *bpi_interior->attr;
2025 if (bpi_exterior
2026 && (bpi_exterior->attr->flag
2027 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) {
2028 new_attr.local_pref =
2029 bpi_exterior->attr->local_pref;
2030 new_attr.flag |=
2031 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2032 }
2033
2034 rfapiBgpInfoFilteredImportVPN(
2035 it, FIF_ACTION_UPDATE, bpi_interior->peer,
2036 NULL, /* rfd */
2037 pfx_exterior, NULL, afi, prd, &new_attr,
2038 ZEBRA_ROUTE_BGP_DIRECT_EXT,
2039 BGP_ROUTE_REDISTRIBUTE, &label);
2040 }
2041 vnc_zlog_debug_verbose(
2042 "%s: finished constructing exteriors based on existing monitors",
2043 __func__);
2044 return;
2045 }
2046
2047 vnc_zlog_debug_verbose("%s: no exterior monitor", __func__);
2048
2049 /*
2050 * No monitor at this node. Is this the first valid interior
2051 * route at this node?
2052 */
2053 if (RFAPI_MONITOR_EXTERIOR(rn_interior)->valid_interior_count > 1) {
2054 vnc_zlog_debug_verbose(
2055 "%s: new interior route not first valid one, skipping pulldown",
2056 __func__);
2057 return;
2058 }
2059
2060 /*
2061 * Look up the tree for possible pulldown candidates.
2062 * Find nearest parent with an exterior route monitor
2063 */
2064 for (par = agg_node_parent(rn_interior); par;
2065 par = agg_node_parent(par)) {
2066 if (RFAPI_HAS_MONITOR_EXTERIOR(par))
2067 break;
2068 }
2069
2070 if (par) {
2071
2072 vnc_zlog_debug_verbose(
2073 "%s: checking parent %p for possible pulldowns",
2074 __func__, par);
2075
2076 /* check monitors at par for possible pulldown */
2077 cursor = NULL;
2078 for (rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(par)->source,
2079 (void **)&bpi_exterior,
2080 (void **)&pfx_exterior, &cursor);
2081 !rc;
2082 rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(par)->source,
2083 (void **)&bpi_exterior,
2084 (void **)&pfx_exterior, &cursor)) {
2085
2086 struct prefix pfx_nexthop;
2087
2088 memset(&pfx_nexthop, 0,
2089 sizeof(struct prefix)); /* keep valgrind happy */
2090
2091 /* check original nexthop for prefix match */
2092 rfapiUnicastNexthop2Prefix(afi, bpi_exterior->attr,
2093 &pfx_nexthop);
2094
2095 if (prefix_match(p, &pfx_nexthop)) {
2096
2097 struct bgp_path_info *bpi;
2098 struct prefix_rd *prd;
2099 struct attr new_attr;
2100 uint32_t label = 0;
2101
2102 /* do pull-down */
2103
2104 /*
2105 * add monitor to longer prefix
2106 */
2107 struct prefix *pfx_mon = prefix_new();
2108 prefix_copy(pfx_mon, pfx_exterior);
2109 if (!RFAPI_MONITOR_EXTERIOR(rn_interior)
2110 ->source) {
2111 RFAPI_MONITOR_EXTERIOR(rn_interior)
2112 ->source = skiplist_new(
2113 0, NULL, prefix_free_lists);
2114 agg_lock_node(rn_interior);
2115 }
2116 skiplist_insert(
2117 RFAPI_MONITOR_EXTERIOR(rn_interior)
2118 ->source,
2119 bpi_exterior, pfx_mon);
2120 agg_lock_node(rn_interior);
2121
2122 /*
2123 * Delete constructed exterior routes based on
2124 * parent routes.
2125 */
2126 for (bpi = par->info; bpi; bpi = bpi->next) {
2127
2128 if (bpi->extra) {
2129 prd = &bpi->extra->vnc.import
2130 .rd;
2131 label = decode_label(
2132 &bpi->extra->label[0]);
2133 } else
2134 prd = NULL;
2135
2136 rfapiBgpInfoFilteredImportVPN(
2137 it, FIF_ACTION_KILL, bpi->peer,
2138 NULL, /* rfd */
2139 pfx_exterior, NULL, afi, prd,
2140 bpi->attr,
2141 ZEBRA_ROUTE_BGP_DIRECT_EXT,
2142 BGP_ROUTE_REDISTRIBUTE, &label);
2143 }
2144
2145
2146 /*
2147 * Add constructed exterior routes based on
2148 * the new interior route at longer prefix.
2149 */
2150 if (bpi_interior->extra) {
2151 prd = &bpi_interior->extra->vnc.import
2152 .rd;
2153 label = decode_label(
2154 &bpi_interior->extra->label[0]);
2155 } else
2156 prd = NULL;
2157
2158 /* use local_pref from unicast route */
2159 memset(&new_attr, 0, sizeof(struct attr));
2160 new_attr = *bpi_interior->attr;
2161 if (bpi_exterior
2162 && (bpi_exterior->attr->flag
2163 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) {
2164 new_attr.local_pref =
2165 bpi_exterior->attr->local_pref;
2166 new_attr.flag |= ATTR_FLAG_BIT(
2167 BGP_ATTR_LOCAL_PREF);
2168 }
2169
2170 rfapiBgpInfoFilteredImportVPN(
2171 it, FIF_ACTION_UPDATE,
2172 bpi_interior->peer, NULL, /* rfd */
2173 pfx_exterior, NULL, afi, prd, &new_attr,
2174 ZEBRA_ROUTE_BGP_DIRECT_EXT,
2175 BGP_ROUTE_REDISTRIBUTE, &label);
2176 }
2177 }
2178
2179 /*
2180 * The only monitors at rn_interior are the ones we added just
2181 * above, so we can use the rn_interior list to identify which
2182 * monitors to delete from the parent.
2183 */
2184 cursor = NULL;
2185 for (rc = skiplist_next(
2186 RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2187 (void **)&bpi_exterior, NULL, &cursor);
2188 !rc; rc = skiplist_next(
2189 RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2190 (void **)&bpi_exterior, NULL, &cursor)) {
2191
2192
2193 skiplist_delete(RFAPI_MONITOR_EXTERIOR(par)->source,
2194 bpi_exterior, NULL);
2195 agg_unlock_node(par); /* sl entry */
2196 }
2197 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(par)->source)) {
2198 skiplist_free(RFAPI_MONITOR_EXTERIOR(par)->source);
2199 RFAPI_MONITOR_EXTERIOR(par)->source = NULL;
2200 agg_unlock_node(par); /* sl itself */
2201 }
2202 }
2203
2204 vnc_zlog_debug_verbose("%s: checking orphans", __func__);
2205
2206 /*
2207 * See if any orphans can be pulled down to the current node
2208 */
2209 cursor = NULL;
2210 list_adopted = NULL;
2211 for (rc = skiplist_next(it->monitor_exterior_orphans,
2212 (void **)&bpi_exterior, (void **)&pfx_exterior,
2213 &cursor);
2214 !rc; rc = skiplist_next(it->monitor_exterior_orphans,
2215 (void **)&bpi_exterior,
2216 (void **)&pfx_exterior, &cursor)) {
2217
2218 struct prefix pfx_nexthop;
2219 afi_t afi_exterior = family2afi(pfx_exterior->family);
2220
2221 vnc_zlog_debug_verbose(
2222 "%s: checking exterior orphan at prefix %pFX", __func__,
2223 pfx_exterior);
2224
2225 if (afi_exterior != afi) {
2226 vnc_zlog_debug_verbose(
2227 "%s: exterior orphan afi %d != interior afi %d, skip",
2228 __func__, afi_exterior, afi);
2229 continue;
2230 }
2231
2232 /* check original nexthop for prefix match */
2233 rfapiUnicastNexthop2Prefix(afi, bpi_exterior->attr,
2234 &pfx_nexthop);
2235
2236 if (prefix_match(p, &pfx_nexthop)) {
2237
2238 struct prefix_rd *prd;
2239 struct attr new_attr;
2240 uint32_t label = 0;
2241
2242 /* do pull-down */
2243
2244 /*
2245 * add monitor to longer prefix
2246 */
2247
2248 struct prefix *pfx_mon = prefix_new();
2249 prefix_copy(pfx_mon, pfx_exterior);
2250 if (!RFAPI_MONITOR_EXTERIOR(rn_interior)->source) {
2251 RFAPI_MONITOR_EXTERIOR(rn_interior)->source =
2252 skiplist_new(
2253 0, NULL, prefix_free_lists);
2254 agg_lock_node(rn_interior); /* sl */
2255 }
2256 skiplist_insert(
2257 RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2258 bpi_exterior, pfx_mon);
2259 agg_lock_node(rn_interior); /* sl entry */
2260 if (!list_adopted) {
2261 list_adopted = list_new();
2262 }
2263 listnode_add(list_adopted, bpi_exterior);
2264
2265 /*
2266 * Add constructed exterior routes based on the
2267 * new interior route at the longer prefix.
2268 */
2269 if (bpi_interior->extra) {
2270 prd = &bpi_interior->extra->vnc.import.rd;
2271 label = decode_label(
2272 &bpi_interior->extra->label[0]);
2273 } else
2274 prd = NULL;
2275
2276 /* use local_pref from unicast route */
2277 memset(&new_attr, 0, sizeof(struct attr));
2278 new_attr = *bpi_interior->attr;
2279 if (bpi_exterior
2280 && (bpi_exterior->attr->flag
2281 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) {
2282 new_attr.local_pref =
2283 bpi_exterior->attr->local_pref;
2284 new_attr.flag |=
2285 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2286 }
2287
2288 rfapiBgpInfoFilteredImportVPN(
2289 it, FIF_ACTION_UPDATE, bpi_interior->peer,
2290 NULL, /* rfd */
2291 pfx_exterior, NULL, afi, prd, &new_attr,
2292 ZEBRA_ROUTE_BGP_DIRECT_EXT,
2293 BGP_ROUTE_REDISTRIBUTE, &label);
2294 }
2295 }
2296 if (list_adopted) {
2297 struct listnode *node;
2298 struct agg_node *an_bpi_exterior;
2299
2300 for (ALL_LIST_ELEMENTS_RO(list_adopted, node,
2301 an_bpi_exterior)) {
2302 skiplist_delete(it->monitor_exterior_orphans,
2303 an_bpi_exterior, NULL);
2304 }
2305 list_delete(&list_adopted);
2306 }
2307 }
2308
2309 /*
2310 * This function should be called after an interior VPN route
2311 * has been deleted from an import_table.
2312 * bpi_interior must still be valid, but it must already be detached
2313 * from its route node and the route node's valid_interior_count
2314 * must already be decremented.
2315 *
2316 * NB should also be called whenever an existing vpn interior route
2317 * becomes invalid (e.g., valid_interior_count is decremented)
2318 */
2319 void vnc_import_bgp_exterior_del_route_interior(
2320 struct bgp *bgp, struct rfapi_import_table *it,
2321 struct agg_node *rn_interior, /* VPN IT node */
2322 struct bgp_path_info *bpi_interior) /* VPN IT route */
2323 {
2324 const struct prefix *p = agg_node_get_prefix(rn_interior);
2325 afi_t afi = family2afi(p->family);
2326 struct agg_node *par;
2327 struct bgp_path_info *bpi_exterior;
2328 struct prefix *pfx_exterior; /* exterior pfx */
2329 void *cursor;
2330 int rc;
2331
2332 if (!VALID_INTERIOR_TYPE(bpi_interior->type)) {
2333 vnc_zlog_debug_verbose(
2334 "%s: type %d not valid interior type, skipping",
2335 __func__, bpi_interior->type);
2336 return;
2337 }
2338
2339 if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
2340 vnc_zlog_debug_verbose(
2341 "%s: redist of exterior routes no enabled, skipping",
2342 __func__);
2343 return;
2344 }
2345
2346 if (it == bgp->rfapi->it_ce) {
2347 vnc_zlog_debug_verbose("%s: it is it_ce, skipping", __func__);
2348 return;
2349 }
2350
2351 /* If no exterior routes depend on this prefix, nothing to do */
2352 if (!RFAPI_HAS_MONITOR_EXTERIOR(rn_interior)) {
2353 vnc_zlog_debug_verbose("%s: no exterior monitor, skipping",
2354 __func__);
2355 return;
2356 }
2357
2358 /*debugging */
2359 vnc_zlog_debug_verbose("%s: interior prefix=%pRN, bpi type=%d",
2360 __func__, rn_interior, bpi_interior->type);
2361
2362 /*
2363 * Remove constructed routes based on the deleted interior route
2364 */
2365 cursor = NULL;
2366 for (rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2367 (void **)&bpi_exterior, (void **)&pfx_exterior,
2368 &cursor);
2369 !rc;
2370 rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2371 (void **)&bpi_exterior, (void **)&pfx_exterior,
2372 &cursor)) {
2373
2374 struct prefix_rd *prd;
2375 uint32_t label = 0;
2376
2377 if (bpi_interior->extra) {
2378 prd = &bpi_interior->extra->vnc.import.rd;
2379 label = decode_label(&bpi_interior->extra->label[0]);
2380 } else
2381 prd = NULL;
2382
2383 rfapiBgpInfoFilteredImportVPN(
2384 it, FIF_ACTION_KILL, bpi_interior->peer, NULL, /* rfd */
2385 pfx_exterior, NULL, afi, prd, bpi_interior->attr,
2386 ZEBRA_ROUTE_BGP_DIRECT_EXT, BGP_ROUTE_REDISTRIBUTE,
2387 &label);
2388 }
2389
2390 /*
2391 * If there are no remaining valid interior routes at this prefix,
2392 * we need to look up the tree for a possible node to move monitors to
2393 */
2394 if (RFAPI_MONITOR_EXTERIOR(rn_interior)->valid_interior_count) {
2395 vnc_zlog_debug_verbose(
2396 "%s: interior routes still present, skipping",
2397 __func__);
2398 return;
2399 }
2400
2401 /*
2402 * Find nearest parent with at least one valid interior route
2403 * If none is found, par will end up NULL, and we will move
2404 * the monitors to the orphan list for this import table
2405 */
2406 for (par = agg_node_parent(rn_interior); par;
2407 par = agg_node_parent(par)) {
2408 if (RFAPI_MONITOR_EXTERIOR(par)->valid_interior_count)
2409 break;
2410 }
2411
2412 vnc_zlog_debug_verbose("%s: par=%p, ext src: %p", __func__, par,
2413 RFAPI_MONITOR_EXTERIOR(rn_interior)->source);
2414
2415 /* move all monitors */
2416 /*
2417 * We will use and delete every element of the source skiplist
2418 */
2419 while (!skiplist_first(RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2420 (void **)&bpi_exterior,
2421 (void **)&pfx_exterior)) {
2422
2423 struct prefix *pfx_mon = prefix_new();
2424
2425 prefix_copy(pfx_mon, pfx_exterior);
2426
2427 if (par) {
2428
2429 struct bgp_path_info *bpi;
2430
2431 /*
2432 * Add monitor to parent node
2433 */
2434 if (!RFAPI_MONITOR_EXTERIOR(par)->source) {
2435 RFAPI_MONITOR_EXTERIOR(par)->source =
2436 skiplist_new(
2437 0, NULL, prefix_free_lists);
2438 agg_lock_node(par); /* sl */
2439 }
2440 skiplist_insert(RFAPI_MONITOR_EXTERIOR(par)->source,
2441 bpi_exterior, pfx_mon);
2442 agg_lock_node(par); /* sl entry */
2443
2444 /* Add constructed exterior routes based on parent */
2445 for (bpi = par->info; bpi; bpi = bpi->next) {
2446
2447 struct prefix_rd *prd;
2448 struct attr new_attr;
2449 uint32_t label = 0;
2450
2451 if (bpi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT)
2452 continue;
2453
2454 if (bpi->extra) {
2455 prd = &bpi->extra->vnc.import.rd;
2456 label = decode_label(
2457 &bpi->extra->label[0]);
2458 } else
2459 prd = NULL;
2460
2461 /* use local_pref from unicast route */
2462 memset(&new_attr, 0, sizeof(new_attr));
2463 new_attr = *bpi->attr;
2464 if (bpi_exterior
2465 && (bpi_exterior->attr->flag
2466 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) {
2467 new_attr.local_pref =
2468 bpi_exterior->attr->local_pref;
2469 new_attr.flag |= ATTR_FLAG_BIT(
2470 BGP_ATTR_LOCAL_PREF);
2471 }
2472
2473 rfapiBgpInfoFilteredImportVPN(
2474 it, FIF_ACTION_UPDATE, bpi->peer,
2475 NULL, /* rfd */
2476 pfx_exterior, NULL, afi, prd, &new_attr,
2477 ZEBRA_ROUTE_BGP_DIRECT_EXT,
2478 BGP_ROUTE_REDISTRIBUTE, &label);
2479 }
2480
2481 } else {
2482
2483 /*
2484 * No interior route for exterior's nexthop. Save
2485 * monitor
2486 * in orphan list to await future route.
2487 */
2488 skiplist_insert(it->monitor_exterior_orphans,
2489 bpi_exterior, pfx_mon);
2490 }
2491
2492 skiplist_delete_first(
2493 RFAPI_MONITOR_EXTERIOR(rn_interior)->source);
2494 agg_unlock_node(rn_interior); /* sl entry */
2495 }
2496 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(rn_interior)->source)) {
2497 skiplist_free(RFAPI_MONITOR_EXTERIOR(rn_interior)->source);
2498 RFAPI_MONITOR_EXTERIOR(rn_interior)->source = NULL;
2499 agg_unlock_node(rn_interior); /* sl itself */
2500 }
2501 }
2502
2503 /***********************************************************************
2504 * Generic add/delete unicast routes
2505 ***********************************************************************/
2506
2507 void vnc_import_bgp_add_route(struct bgp *bgp, const struct prefix *prefix,
2508 struct bgp_path_info *info)
2509 {
2510 afi_t afi = family2afi(prefix->family);
2511
2512 if (VNC_DEBUG(VERBOSE)) {
2513 struct prefix pfx_nexthop;
2514
2515 rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_nexthop);
2516 vnc_zlog_debug_verbose("%s: pfx %pFX, nh %pFX", __func__,
2517 prefix, &pfx_nexthop);
2518 }
2519 #if DEBUG_RHN_LIST
2520 print_rhn_list(__func__, "ENTER ");
2521 #endif
2522 VNC_RHNCK(enter);
2523
2524 if (!afi) {
2525 flog_err(EC_LIB_DEVELOPMENT, "%s: can't get afi of prefix",
2526 __func__);
2527 return;
2528 }
2529
2530 if (!bgp->rfapi_cfg) {
2531 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2532 __func__);
2533 return;
2534 }
2535
2536 /* check vnc redist flag for bgp direct routes */
2537 if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
2538 vnc_zlog_debug_verbose(
2539 "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
2540 __func__, afi, ZEBRA_ROUTE_BGP_DIRECT);
2541 return;
2542 }
2543
2544 switch (bgp->rfapi_cfg->redist_mode) {
2545 case VNC_REDIST_MODE_PLAIN:
2546 vnc_import_bgp_add_route_mode_plain(bgp, prefix, info);
2547 break;
2548
2549 case VNC_REDIST_MODE_RFG:
2550 if (bgp->rfapi_cfg->rfg_redist)
2551 vnc_import_bgp_add_route_mode_nvegroup(
2552 bgp, prefix, info, bgp->rfapi_cfg->rfg_redist);
2553 else
2554 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2555 __func__);
2556 break;
2557
2558 case VNC_REDIST_MODE_RESOLVE_NVE:
2559 vnc_import_bgp_add_route_mode_resolve_nve(bgp, prefix, info);
2560 break;
2561 }
2562 #if DEBUG_RHN_LIST
2563 print_rhn_list(__func__, "LEAVE ");
2564 #endif
2565 VNC_RHNCK(leave);
2566 }
2567
2568 /*
2569 * "Withdrawing a Route" import process
2570 */
2571 void vnc_import_bgp_del_route(struct bgp *bgp, const struct prefix *prefix,
2572 struct bgp_path_info *info) /* unicast info */
2573 {
2574 afi_t afi = family2afi(prefix->family);
2575
2576 assert(afi);
2577
2578 {
2579 struct prefix pfx_nexthop;
2580
2581 rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_nexthop);
2582 vnc_zlog_debug_verbose("%s: pfx %pFX, nh %pFX", __func__,
2583 prefix, &pfx_nexthop);
2584 }
2585 #if DEBUG_RHN_LIST
2586 print_rhn_list(__func__, "ENTER ");
2587 #endif
2588 VNC_RHNCK(enter);
2589
2590 if (!bgp->rfapi_cfg) {
2591 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2592 __func__);
2593 return;
2594 }
2595
2596 /* check bgp redist flag for vnc direct ("vpn") routes */
2597 if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
2598 vnc_zlog_debug_verbose(
2599 "%s: bgp redistribution of afi=%d VNC direct routes is off",
2600 __func__, afi);
2601 return;
2602 }
2603
2604 switch (bgp->rfapi_cfg->redist_mode) {
2605 case VNC_REDIST_MODE_PLAIN:
2606 vnc_import_bgp_del_route_mode_plain(bgp, prefix, info);
2607 break;
2608
2609 case VNC_REDIST_MODE_RFG:
2610 if (bgp->rfapi_cfg->rfg_redist)
2611 vnc_import_bgp_del_route_mode_nvegroup(bgp, prefix,
2612 info);
2613 else
2614 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2615 __func__);
2616 break;
2617
2618 case VNC_REDIST_MODE_RESOLVE_NVE:
2619 vnc_import_bgp_del_route_mode_resolve_nve(bgp, afi, prefix,
2620 info);
2621 break;
2622 }
2623 #if DEBUG_RHN_LIST
2624 print_rhn_list(__func__, "LEAVE ");
2625 #endif
2626 VNC_RHNCK(leave);
2627 }
2628
2629
2630 /***********************************************************************
2631 * Enable/Disable
2632 ***********************************************************************/
2633
2634 void vnc_import_bgp_redist_enable(struct bgp *bgp, afi_t afi)
2635 {
2636 /* iterate over bgp unicast v4 and v6 routes, call
2637 * vnc_import_bgp_add_route */
2638
2639 struct bgp_dest *dest;
2640
2641 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
2642
2643 if (bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
2644 vnc_zlog_debug_verbose(
2645 "%s: already enabled for afi %d, skipping", __func__,
2646 afi);
2647 return;
2648 }
2649 bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT] = 1;
2650
2651 for (dest = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); dest;
2652 dest = bgp_route_next(dest)) {
2653
2654 struct bgp_path_info *bpi;
2655
2656 for (bpi = bgp_dest_get_bgp_path_info(dest); bpi;
2657 bpi = bpi->next) {
2658
2659 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
2660 continue;
2661
2662 vnc_import_bgp_add_route(bgp, bgp_dest_get_prefix(dest),
2663 bpi);
2664 }
2665 }
2666 vnc_zlog_debug_verbose(
2667 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2668 __func__, afi, ZEBRA_ROUTE_BGP_DIRECT);
2669 }
2670
2671 void vnc_import_bgp_exterior_redist_enable(struct bgp *bgp, afi_t afi)
2672 {
2673 struct bgp *bgp_exterior;
2674 struct bgp_dest *dest;
2675
2676 bgp_exterior = bgp->rfapi_cfg->redist_bgp_exterior_view;
2677
2678 if (bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
2679 vnc_zlog_debug_verbose(
2680 "%s: already enabled for afi %d, skipping", __func__,
2681 afi);
2682 return;
2683 }
2684 bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT] = 1;
2685
2686 if (!bgp_exterior) {
2687 vnc_zlog_debug_verbose(
2688 "%s: no exterior view set yet, no routes to import yet",
2689 __func__);
2690 return;
2691 }
2692
2693 for (dest = bgp_table_top(bgp_exterior->rib[afi][SAFI_UNICAST]); dest;
2694 dest = bgp_route_next(dest)) {
2695
2696 struct bgp_path_info *bpi;
2697
2698 for (bpi = bgp_dest_get_bgp_path_info(dest); bpi;
2699 bpi = bpi->next) {
2700
2701 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
2702 continue;
2703
2704 vnc_import_bgp_exterior_add_route(
2705 bgp_exterior, bgp_dest_get_prefix(dest), bpi);
2706 }
2707 }
2708 vnc_zlog_debug_verbose(
2709 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2710 __func__, afi, ZEBRA_ROUTE_BGP_DIRECT);
2711 }
2712
2713 /*
2714 * This function is for populating a newly-created Import Table
2715 */
2716 void vnc_import_bgp_exterior_redist_enable_it(
2717 struct bgp *bgp, afi_t afi, struct rfapi_import_table *it_only)
2718 {
2719 struct bgp *bgp_exterior;
2720 struct bgp_dest *dest;
2721
2722 vnc_zlog_debug_verbose("%s: entry", __func__);
2723
2724 bgp_exterior = bgp->rfapi_cfg->redist_bgp_exterior_view;
2725
2726 if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
2727 vnc_zlog_debug_verbose("%s: not enabled for afi %d, skipping",
2728 __func__, afi);
2729 return;
2730 }
2731
2732 if (!bgp_exterior) {
2733 vnc_zlog_debug_verbose(
2734 "%s: no exterior view set yet, no routes to import yet",
2735 __func__);
2736 return;
2737 }
2738
2739 for (dest = bgp_table_top(bgp_exterior->rib[afi][SAFI_UNICAST]); dest;
2740 dest = bgp_route_next(dest)) {
2741
2742 struct bgp_path_info *bpi;
2743
2744 for (bpi = bgp_dest_get_bgp_path_info(dest); bpi;
2745 bpi = bpi->next) {
2746
2747 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
2748 continue;
2749
2750 vnc_import_bgp_exterior_add_route_it(
2751 bgp_exterior, bgp_dest_get_prefix(dest), bpi,
2752 it_only);
2753 }
2754 }
2755 }
2756
2757
2758 void vnc_import_bgp_redist_disable(struct bgp *bgp, afi_t afi)
2759 {
2760 /*
2761 * iterate over vpn routes, find routes of type ZEBRA_ROUTE_BGP_DIRECT,
2762 * delete (call timer expire immediately)
2763 */
2764 struct bgp_dest *dest1;
2765 struct bgp_dest *dest2;
2766
2767 vnc_zlog_debug_verbose("%s: entry", __func__);
2768
2769 if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
2770 vnc_zlog_debug_verbose(
2771 "%s: already disabled for afi %d, skipping", __func__,
2772 afi);
2773 return;
2774 }
2775
2776 /*
2777 * Two-level table for SAFI_MPLS_VPN
2778 * Be careful when changing the things we iterate over
2779 */
2780 for (dest1 = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); dest1;
2781 dest1 = bgp_route_next(dest1)) {
2782 const struct prefix *dest1_p;
2783
2784 if (!bgp_dest_has_bgp_path_info_data(dest1))
2785 continue;
2786
2787 dest1_p = bgp_dest_get_prefix(dest1);
2788 for (dest2 = bgp_table_top(bgp_dest_get_bgp_table_info(dest1));
2789 dest2; dest2 = bgp_route_next(dest2)) {
2790 const struct prefix *dest2_p =
2791 bgp_dest_get_prefix(dest2);
2792 struct bgp_path_info *bpi;
2793 struct bgp_path_info *nextbpi;
2794
2795 for (bpi = bgp_dest_get_bgp_path_info(dest2); bpi;
2796 bpi = nextbpi) {
2797
2798 nextbpi = bpi->next;
2799
2800 if (bpi->type != ZEBRA_ROUTE_BGP_DIRECT)
2801 continue;
2802
2803 struct rfapi_descriptor *rfd;
2804 vncHDBgpDirect.peer = bpi->peer;
2805
2806 assert(bpi->extra);
2807
2808 rfd = bpi->extra->vnc.export.rfapi_handle;
2809
2810 vnc_zlog_debug_verbose(
2811 "%s: deleting bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p [passing rfd=%p]",
2812 __func__, bpi, bpi->peer, bpi->type,
2813 bpi->sub_type,
2814 (bpi->extra ? bpi->extra->vnc.export
2815 .rfapi_handle
2816 : NULL),
2817 rfd);
2818
2819 del_vnc_route(rfd, bpi->peer, bgp,
2820 SAFI_MPLS_VPN, dest2_p,
2821 (struct prefix_rd *)dest1_p,
2822 bpi->type, bpi->sub_type, NULL,
2823 1); /* kill */
2824
2825 vncHDBgpDirect.peer = NULL;
2826 }
2827 }
2828 }
2829 /* Clear RHN list */
2830 if (bgp->rfapi->resolve_nve_nexthop) {
2831 struct prefix_bag *pb;
2832 struct bgp_path_info *info;
2833 while (!skiplist_first(bgp->rfapi->resolve_nve_nexthop, NULL,
2834 (void *)&pb)) {
2835 info = pb->ubpi;
2836 skiplist_delete_first(bgp->rfapi->resolve_nve_nexthop);
2837 bgp_path_info_unlock(info);
2838 }
2839 }
2840
2841 bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT] = 0;
2842 vnc_zlog_debug_verbose("%s: return", __func__);
2843 }
2844
2845
2846 void vnc_import_bgp_exterior_redist_disable(struct bgp *bgp, afi_t afi)
2847 {
2848 struct rfapi_cfg *hc = bgp->rfapi_cfg;
2849 struct bgp *bgp_exterior = hc->redist_bgp_exterior_view;
2850
2851 vnc_zlog_debug_verbose("%s: entry", __func__);
2852
2853 if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
2854 vnc_zlog_debug_verbose(
2855 "%s: already disabled for afi %d, skipping", __func__,
2856 afi);
2857 return;
2858 }
2859
2860 if (!bgp_exterior) {
2861 vnc_zlog_debug_verbose(
2862 "%s: bgp exterior view not defined, skipping",
2863 __func__);
2864 return;
2865 }
2866
2867
2868 {
2869 struct bgp_dest *dest;
2870 for (dest = bgp_table_top(bgp_exterior->rib[afi][SAFI_UNICAST]);
2871 dest; dest = bgp_route_next(dest)) {
2872
2873 struct bgp_path_info *bpi;
2874
2875 for (bpi = bgp_dest_get_bgp_path_info(dest); bpi;
2876 bpi = bpi->next) {
2877
2878 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
2879 continue;
2880
2881 vnc_import_bgp_exterior_del_route(
2882 bgp_exterior, bgp_dest_get_prefix(dest),
2883 bpi);
2884 }
2885 }
2886 #if DEBUG_RHN_LIST
2887 print_rhn_list(__func__, NULL);
2888 #endif
2889 }
2890
2891 bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT] = 0;
2892 vnc_zlog_debug_verbose("%s: return", __func__);
2893 }