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