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