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