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