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