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