]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/rfapi/vnc_import_bgp.c
*: rename zlog_fer -> flog_err
[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/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(LIB_ERR_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(LIB_ERR_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(LIB_ERR_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 info;
1014 route_map_result_t ret;
1015
1016 memset(&info, 0, sizeof(info));
1017 info.peer = peer;
1018 info.attr = &hattr;
1019 ret = route_map_apply(rmap, prefix, RMAP_BGP, &info);
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 route_table *table;
1741 struct route_node *rn;
1742 struct route_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 = route_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 route_lock_node(rn); /* for skiplist */
1825 }
1826 route_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 = rn->parent;
1836 if (par)
1837 route_lock_node(par);
1838 route_unlock_node(rn);
1839 rn = par;
1840 }
1841 if (rn)
1842 route_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 route_table *table;
1932 struct route_node *rn;
1933 struct route_node *par;
1934 struct bgp_info *bi_interior;
1935 int have_usable_route;
1936
1937 table = it->imported_vpn[afi];
1938
1939 for (rn = route_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 route_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 route_unlock_node(
2006 rn); /* skiplist
2007 itself
2008 */
2009 }
2010 }
2011 }
2012 }
2013 par = rn->parent;
2014 if (par)
2015 route_lock_node(par);
2016 route_unlock_node(rn);
2017 rn = par;
2018 }
2019 if (rn)
2020 route_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 route_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 route_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 = rn_interior->parent; par; par = par->parent) {
2165 if (RFAPI_HAS_MONITOR_EXTERIOR(par))
2166 break;
2167 }
2168
2169 if (par) {
2170
2171 vnc_zlog_debug_verbose(
2172 "%s: checking parent %p for possible pulldowns",
2173 __func__, par);
2174
2175 /* check monitors at par for possible pulldown */
2176 cursor = NULL;
2177 for (rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(par)->source,
2178 (void **)&bi_exterior,
2179 (void **)&pfx_exterior, &cursor);
2180 !rc;
2181 rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(par)->source,
2182 (void **)&bi_exterior,
2183 (void **)&pfx_exterior, &cursor)) {
2184
2185 struct prefix pfx_nexthop;
2186
2187 memset(&pfx_nexthop, 0,
2188 sizeof(struct prefix)); /* keep valgrind happy */
2189
2190 /* check original nexthop for prefix match */
2191 rfapiUnicastNexthop2Prefix(afi, bi_exterior->attr,
2192 &pfx_nexthop);
2193
2194 if (prefix_match(&rn_interior->p, &pfx_nexthop)) {
2195
2196 struct bgp_info *bi;
2197 struct prefix_rd *prd;
2198 struct attr new_attr;
2199 uint32_t label = 0;
2200
2201 /* do pull-down */
2202
2203 /*
2204 * add monitor to longer prefix
2205 */
2206 struct prefix *pfx_mon = prefix_new();
2207 prefix_copy(pfx_mon, pfx_exterior);
2208 if (!RFAPI_MONITOR_EXTERIOR(rn_interior)
2209 ->source) {
2210 RFAPI_MONITOR_EXTERIOR(rn_interior)
2211 ->source = skiplist_new(
2212 0, NULL,
2213 (void (*)(void *))prefix_free);
2214 route_lock_node(rn_interior);
2215 }
2216 skiplist_insert(
2217 RFAPI_MONITOR_EXTERIOR(rn_interior)
2218 ->source,
2219 bi_exterior, pfx_mon);
2220 route_lock_node(rn_interior);
2221
2222 /*
2223 * Delete constructed exterior routes based on
2224 * parent routes.
2225 */
2226 for (bi = par->info; bi; bi = bi->next) {
2227
2228 if (bi->extra) {
2229 prd = &bi->extra->vnc.import.rd;
2230 label = decode_label(
2231 &bi->extra->label[0]);
2232 } else
2233 prd = NULL;
2234
2235 rfapiBgpInfoFilteredImportVPN(
2236 it, FIF_ACTION_KILL, bi->peer,
2237 NULL, /* rfd */
2238 pfx_exterior, NULL, afi, prd,
2239 bi->attr,
2240 ZEBRA_ROUTE_BGP_DIRECT_EXT,
2241 BGP_ROUTE_REDISTRIBUTE, &label);
2242 }
2243
2244
2245 /*
2246 * Add constructed exterior routes based on
2247 * the new interior route at longer prefix.
2248 */
2249 if (bi_interior->extra) {
2250 prd = &bi_interior->extra->vnc.import
2251 .rd;
2252 label = decode_label(
2253 &bi_interior->extra->label[0]);
2254 } else
2255 prd = NULL;
2256
2257 /* use local_pref from unicast route */
2258 memset(&new_attr, 0, sizeof(struct attr));
2259 bgp_attr_dup(&new_attr, bi_interior->attr);
2260 if (bi_exterior
2261 && (bi_exterior->attr->flag
2262 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) {
2263 new_attr.local_pref =
2264 bi_exterior->attr->local_pref;
2265 new_attr.flag |= ATTR_FLAG_BIT(
2266 BGP_ATTR_LOCAL_PREF);
2267 }
2268
2269 rfapiBgpInfoFilteredImportVPN(
2270 it, FIF_ACTION_UPDATE,
2271 bi_interior->peer, NULL, /* rfd */
2272 pfx_exterior, NULL, afi, prd, &new_attr,
2273 ZEBRA_ROUTE_BGP_DIRECT_EXT,
2274 BGP_ROUTE_REDISTRIBUTE, &label);
2275 }
2276 }
2277
2278 /*
2279 * The only monitors at rn_interior are the ones we added just
2280 * above, so we can use the rn_interior list to identify which
2281 * monitors to delete from the parent.
2282 */
2283 cursor = NULL;
2284 for (rc = skiplist_next(
2285 RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2286 (void **)&bi_exterior, NULL, &cursor);
2287 !rc; rc = skiplist_next(
2288 RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2289 (void **)&bi_exterior, NULL, &cursor)) {
2290
2291
2292 skiplist_delete(RFAPI_MONITOR_EXTERIOR(par)->source,
2293 bi_exterior, NULL);
2294 route_unlock_node(par); /* sl entry */
2295 }
2296 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(par)->source)) {
2297 skiplist_free(RFAPI_MONITOR_EXTERIOR(par)->source);
2298 RFAPI_MONITOR_EXTERIOR(par)->source = NULL;
2299 route_unlock_node(par); /* sl itself */
2300 }
2301 }
2302
2303 vnc_zlog_debug_verbose("%s: checking orphans", __func__);
2304
2305 /*
2306 * See if any orphans can be pulled down to the current node
2307 */
2308 cursor = NULL;
2309 list_adopted = NULL;
2310 for (rc = skiplist_next(it->monitor_exterior_orphans,
2311 (void **)&bi_exterior, (void **)&pfx_exterior,
2312 &cursor);
2313 !rc; rc = skiplist_next(it->monitor_exterior_orphans,
2314 (void **)&bi_exterior,
2315 (void **)&pfx_exterior, &cursor)) {
2316
2317 struct prefix pfx_nexthop;
2318 char buf[PREFIX_STRLEN];
2319 afi_t afi_exterior = family2afi(pfx_exterior->family);
2320
2321 prefix2str(pfx_exterior, buf, sizeof(buf));
2322 vnc_zlog_debug_verbose(
2323 "%s: checking exterior orphan at prefix %s", __func__,
2324 buf);
2325
2326 if (afi_exterior != afi) {
2327 vnc_zlog_debug_verbose(
2328 "%s: exterior orphan afi %d != interior afi %d, skip",
2329 __func__, afi_exterior, afi);
2330 continue;
2331 }
2332
2333 /* check original nexthop for prefix match */
2334 rfapiUnicastNexthop2Prefix(afi, bi_exterior->attr,
2335 &pfx_nexthop);
2336
2337 if (prefix_match(&rn_interior->p, &pfx_nexthop)) {
2338
2339 struct prefix_rd *prd;
2340 struct attr new_attr;
2341 uint32_t label = 0;
2342
2343 /* do pull-down */
2344
2345 /*
2346 * add monitor to longer prefix
2347 */
2348
2349 struct prefix *pfx_mon = prefix_new();
2350 prefix_copy(pfx_mon, pfx_exterior);
2351 if (!RFAPI_MONITOR_EXTERIOR(rn_interior)->source) {
2352 RFAPI_MONITOR_EXTERIOR(rn_interior)->source =
2353 skiplist_new(
2354 0, NULL,
2355 (void (*)(void *))prefix_free);
2356 route_lock_node(rn_interior); /* sl */
2357 }
2358 skiplist_insert(
2359 RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2360 bi_exterior, pfx_mon);
2361 route_lock_node(rn_interior); /* sl entry */
2362 if (!list_adopted) {
2363 list_adopted = list_new();
2364 }
2365 listnode_add(list_adopted, bi_exterior);
2366
2367 /*
2368 * Add constructed exterior routes based on the
2369 * new interior route at the longer prefix.
2370 */
2371 if (bi_interior->extra) {
2372 prd = &bi_interior->extra->vnc.import.rd;
2373 label = decode_label(
2374 &bi_interior->extra->label[0]);
2375 } else
2376 prd = NULL;
2377
2378 /* use local_pref from unicast route */
2379 memset(&new_attr, 0, sizeof(struct attr));
2380 bgp_attr_dup(&new_attr, bi_interior->attr);
2381 if (bi_exterior
2382 && (bi_exterior->attr->flag
2383 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) {
2384 new_attr.local_pref =
2385 bi_exterior->attr->local_pref;
2386 new_attr.flag |=
2387 ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2388 }
2389
2390 rfapiBgpInfoFilteredImportVPN(
2391 it, FIF_ACTION_UPDATE, bi_interior->peer,
2392 NULL, /* rfd */
2393 pfx_exterior, NULL, afi, prd, &new_attr,
2394 ZEBRA_ROUTE_BGP_DIRECT_EXT,
2395 BGP_ROUTE_REDISTRIBUTE, &label);
2396 }
2397 }
2398 if (list_adopted) {
2399 struct listnode *node;
2400 struct route_node *bi_exterior;
2401
2402 for (ALL_LIST_ELEMENTS_RO(list_adopted, node, bi_exterior)) {
2403 skiplist_delete(it->monitor_exterior_orphans,
2404 bi_exterior, NULL);
2405 }
2406 list_delete_and_null(&list_adopted);
2407 }
2408 }
2409
2410 /*
2411 * This function should be called after an interior VPN route
2412 * has been deleted from an import_table.
2413 * bi_interior must still be valid, but it must already be detached
2414 * from its route node and the route node's valid_interior_count
2415 * must already be decremented.
2416 *
2417 * NB should also be called whenever an existing vpn interior route
2418 * becomes invalid (e.g., valid_interior_count is decremented)
2419 */
2420 void vnc_import_bgp_exterior_del_route_interior(
2421 struct bgp *bgp, struct rfapi_import_table *it,
2422 struct route_node *rn_interior, /* VPN IT node */
2423 struct bgp_info *bi_interior) /* VPN IT route */
2424 {
2425 afi_t afi = family2afi(rn_interior->p.family);
2426 struct route_node *par;
2427 struct bgp_info *bi_exterior;
2428 struct prefix *pfx_exterior; /* exterior pfx */
2429 void *cursor;
2430 int rc;
2431
2432 if (!VALID_INTERIOR_TYPE(bi_interior->type)) {
2433 vnc_zlog_debug_verbose(
2434 "%s: type %d not valid interior type, skipping",
2435 __func__, bi_interior->type);
2436 return;
2437 }
2438
2439 if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
2440 vnc_zlog_debug_verbose(
2441 "%s: redist of exterior routes no enabled, skipping",
2442 __func__);
2443 return;
2444 }
2445
2446 if (it == bgp->rfapi->it_ce) {
2447 vnc_zlog_debug_verbose("%s: it is it_ce, skipping", __func__);
2448 return;
2449 }
2450
2451 /* If no exterior routes depend on this prefix, nothing to do */
2452 if (!RFAPI_HAS_MONITOR_EXTERIOR(rn_interior)) {
2453 vnc_zlog_debug_verbose("%s: no exterior monitor, skipping",
2454 __func__);
2455 return;
2456 }
2457
2458 /*debugging */
2459 {
2460 char str_pfx[PREFIX_STRLEN];
2461
2462 prefix2str(&rn_interior->p, str_pfx, sizeof(str_pfx));
2463
2464 vnc_zlog_debug_verbose("%s: interior prefix=%s, bi type=%d",
2465 __func__, str_pfx, bi_interior->type);
2466 }
2467
2468 /*
2469 * Remove constructed routes based on the deleted interior route
2470 */
2471 cursor = NULL;
2472 for (rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2473 (void **)&bi_exterior, (void **)&pfx_exterior,
2474 &cursor);
2475 !rc;
2476 rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2477 (void **)&bi_exterior, (void **)&pfx_exterior,
2478 &cursor)) {
2479
2480 struct prefix_rd *prd;
2481 uint32_t label = 0;
2482
2483 if (bi_interior->extra) {
2484 prd = &bi_interior->extra->vnc.import.rd;
2485 label = decode_label(&bi_interior->extra->label[0]);
2486 } else
2487 prd = NULL;
2488
2489 rfapiBgpInfoFilteredImportVPN(
2490 it, FIF_ACTION_KILL, bi_interior->peer, NULL, /* rfd */
2491 pfx_exterior, NULL, afi, prd, bi_interior->attr,
2492 ZEBRA_ROUTE_BGP_DIRECT_EXT, BGP_ROUTE_REDISTRIBUTE,
2493 &label);
2494 }
2495
2496 /*
2497 * If there are no remaining valid interior routes at this prefix,
2498 * we need to look up the tree for a possible node to move monitors to
2499 */
2500 if (RFAPI_MONITOR_EXTERIOR(rn_interior)->valid_interior_count) {
2501 vnc_zlog_debug_verbose(
2502 "%s: interior routes still present, skipping",
2503 __func__);
2504 return;
2505 }
2506
2507 /*
2508 * Find nearest parent with at least one valid interior route
2509 * If none is found, par will end up NULL, and we will move
2510 * the monitors to the orphan list for this import table
2511 */
2512 for (par = rn_interior->parent; par; par = par->parent) {
2513 if (RFAPI_MONITOR_EXTERIOR(par)->valid_interior_count)
2514 break;
2515 }
2516
2517 vnc_zlog_debug_verbose("%s: par=%p, ext src: %p", __func__, par,
2518 RFAPI_MONITOR_EXTERIOR(rn_interior)->source);
2519
2520 /* move all monitors */
2521 /*
2522 * We will use and delete every element of the source skiplist
2523 */
2524 while (!skiplist_first(RFAPI_MONITOR_EXTERIOR(rn_interior)->source,
2525 (void **)&bi_exterior, (void **)&pfx_exterior)) {
2526
2527 struct prefix *pfx_mon = prefix_new();
2528
2529 prefix_copy(pfx_mon, pfx_exterior);
2530
2531 if (par) {
2532
2533 struct bgp_info *bi;
2534
2535 /*
2536 * Add monitor to parent node
2537 */
2538 if (!RFAPI_MONITOR_EXTERIOR(par)->source) {
2539 RFAPI_MONITOR_EXTERIOR(par)->source =
2540 skiplist_new(
2541 0, NULL,
2542 (void (*)(void *))prefix_free);
2543 route_lock_node(par); /* sl */
2544 }
2545 skiplist_insert(RFAPI_MONITOR_EXTERIOR(par)->source,
2546 bi_exterior, pfx_mon);
2547 route_lock_node(par); /* sl entry */
2548
2549 /* Add constructed exterior routes based on parent */
2550 for (bi = par->info; bi; bi = bi->next) {
2551
2552 struct prefix_rd *prd;
2553 struct attr new_attr;
2554 uint32_t label = 0;
2555
2556 if (bi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT)
2557 continue;
2558
2559 if (bi->extra) {
2560 prd = &bi->extra->vnc.import.rd;
2561 label = decode_label(
2562 &bi->extra->label[0]);
2563 } else
2564 prd = NULL;
2565
2566 /* use local_pref from unicast route */
2567 memset(&new_attr, 0, sizeof(struct attr));
2568 bgp_attr_dup(&new_attr, bi->attr);
2569 if (bi_exterior
2570 && (bi_exterior->attr->flag
2571 & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) {
2572 new_attr.local_pref =
2573 bi_exterior->attr->local_pref;
2574 new_attr.flag |= ATTR_FLAG_BIT(
2575 BGP_ATTR_LOCAL_PREF);
2576 }
2577
2578 rfapiBgpInfoFilteredImportVPN(
2579 it, FIF_ACTION_UPDATE, bi->peer,
2580 NULL, /* rfd */
2581 pfx_exterior, NULL, afi, prd, &new_attr,
2582 ZEBRA_ROUTE_BGP_DIRECT_EXT,
2583 BGP_ROUTE_REDISTRIBUTE, &label);
2584 }
2585
2586 } else {
2587
2588 /*
2589 * No interior route for exterior's nexthop. Save
2590 * monitor
2591 * in orphan list to await future route.
2592 */
2593 skiplist_insert(it->monitor_exterior_orphans,
2594 bi_exterior, pfx_mon);
2595 }
2596
2597 skiplist_delete_first(
2598 RFAPI_MONITOR_EXTERIOR(rn_interior)->source);
2599 route_unlock_node(rn_interior); /* sl entry */
2600 }
2601 if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(rn_interior)->source)) {
2602 skiplist_free(RFAPI_MONITOR_EXTERIOR(rn_interior)->source);
2603 RFAPI_MONITOR_EXTERIOR(rn_interior)->source = NULL;
2604 route_unlock_node(rn_interior); /* sl itself */
2605 }
2606 }
2607
2608 /***********************************************************************
2609 * Generic add/delete unicast routes
2610 ***********************************************************************/
2611
2612 void vnc_import_bgp_add_route(struct bgp *bgp, struct prefix *prefix,
2613 struct bgp_info *info)
2614 {
2615 afi_t afi = family2afi(prefix->family);
2616
2617 if (VNC_DEBUG(VERBOSE)) {
2618 struct prefix pfx_nexthop;
2619 char buf[PREFIX_STRLEN];
2620 char buf_nh[PREFIX_STRLEN];
2621
2622 prefix2str(prefix, buf, sizeof(buf));
2623 rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_nexthop);
2624 prefix2str(&pfx_nexthop, buf_nh, sizeof(buf_nh));
2625
2626 vnc_zlog_debug_verbose("%s: pfx %s, nh %s", __func__, buf,
2627 buf_nh);
2628 }
2629 #if DEBUG_RHN_LIST
2630 print_rhn_list(__func__, "ENTER ");
2631 #endif
2632 VNC_RHNCK(enter);
2633
2634 if (!afi) {
2635 flog_err(LIB_ERR_DEVELOPMENT, "%s: can't get afi of prefix",
2636 __func__);
2637 return;
2638 }
2639
2640 if (!bgp->rfapi_cfg) {
2641 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2642 __func__);
2643 return;
2644 }
2645
2646 /* check vnc redist flag for bgp direct routes */
2647 if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
2648 vnc_zlog_debug_verbose(
2649 "%s: bgp->rfapi_cfg->redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] is 0, skipping",
2650 __func__, afi, ZEBRA_ROUTE_BGP_DIRECT);
2651 return;
2652 }
2653
2654 switch (bgp->rfapi_cfg->redist_mode) {
2655 case VNC_REDIST_MODE_PLAIN:
2656 vnc_import_bgp_add_route_mode_plain(bgp, prefix, info);
2657 break;
2658
2659 case VNC_REDIST_MODE_RFG:
2660 if (bgp->rfapi_cfg->rfg_redist)
2661 vnc_import_bgp_add_route_mode_nvegroup(
2662 bgp, prefix, info, bgp->rfapi_cfg->rfg_redist);
2663 else
2664 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2665 __func__);
2666 break;
2667
2668 case VNC_REDIST_MODE_RESOLVE_NVE:
2669 vnc_import_bgp_add_route_mode_resolve_nve(bgp, prefix, info);
2670 break;
2671 }
2672 #if DEBUG_RHN_LIST
2673 print_rhn_list(__func__, "LEAVE ");
2674 #endif
2675 VNC_RHNCK(leave);
2676 }
2677
2678 /*
2679 * "Withdrawing a Route" import process
2680 */
2681 void vnc_import_bgp_del_route(struct bgp *bgp, struct prefix *prefix,
2682 struct bgp_info *info) /* unicast info */
2683 {
2684 afi_t afi = family2afi(prefix->family);
2685
2686 assert(afi);
2687
2688 {
2689 struct prefix pfx_nexthop;
2690 char buf[PREFIX_STRLEN];
2691 char buf_nh[PREFIX_STRLEN];
2692
2693 prefix2str(prefix, buf, sizeof(buf));
2694 rfapiUnicastNexthop2Prefix(afi, info->attr, &pfx_nexthop);
2695 prefix2str(&pfx_nexthop, buf_nh, sizeof(buf_nh));
2696
2697 vnc_zlog_debug_verbose("%s: pfx %s, nh %s", __func__, buf,
2698 buf_nh);
2699 }
2700 #if DEBUG_RHN_LIST
2701 print_rhn_list(__func__, "ENTER ");
2702 #endif
2703 VNC_RHNCK(enter);
2704
2705 if (!bgp->rfapi_cfg) {
2706 vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping",
2707 __func__);
2708 return;
2709 }
2710
2711 /* check bgp redist flag for vnc direct ("vpn") routes */
2712 if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
2713 vnc_zlog_debug_verbose(
2714 "%s: bgp redistribution of afi=%d VNC direct routes is off",
2715 __func__, afi);
2716 return;
2717 }
2718
2719 switch (bgp->rfapi_cfg->redist_mode) {
2720 case VNC_REDIST_MODE_PLAIN:
2721 vnc_import_bgp_del_route_mode_plain(bgp, prefix, info);
2722 break;
2723
2724 case VNC_REDIST_MODE_RFG:
2725 if (bgp->rfapi_cfg->rfg_redist)
2726 vnc_import_bgp_del_route_mode_nvegroup(bgp, prefix,
2727 info);
2728 else
2729 vnc_zlog_debug_verbose("%s: mode RFG but no redist RFG",
2730 __func__);
2731 break;
2732
2733 case VNC_REDIST_MODE_RESOLVE_NVE:
2734 vnc_import_bgp_del_route_mode_resolve_nve(bgp, afi, prefix,
2735 info);
2736 break;
2737 }
2738 #if DEBUG_RHN_LIST
2739 print_rhn_list(__func__, "LEAVE ");
2740 #endif
2741 VNC_RHNCK(leave);
2742 }
2743
2744
2745 /***********************************************************************
2746 * Enable/Disable
2747 ***********************************************************************/
2748
2749 void vnc_import_bgp_redist_enable(struct bgp *bgp, afi_t afi)
2750 {
2751 /* iterate over bgp unicast v4 and v6 routes, call
2752 * vnc_import_bgp_add_route */
2753
2754 struct bgp_node *rn;
2755
2756 vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi);
2757
2758 if (bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
2759 vnc_zlog_debug_verbose(
2760 "%s: already enabled for afi %d, skipping", __func__,
2761 afi);
2762 return;
2763 }
2764 bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT] = 1;
2765
2766 for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn;
2767 rn = bgp_route_next(rn)) {
2768
2769 struct bgp_info *bi;
2770
2771 for (bi = rn->info; bi; bi = bi->next) {
2772
2773 if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
2774 continue;
2775
2776 vnc_import_bgp_add_route(bgp, &rn->p, bi);
2777 }
2778 }
2779 vnc_zlog_debug_verbose(
2780 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2781 __func__, afi, ZEBRA_ROUTE_BGP_DIRECT);
2782 }
2783
2784 void vnc_import_bgp_exterior_redist_enable(struct bgp *bgp, afi_t afi)
2785 {
2786 struct bgp *bgp_exterior;
2787 struct bgp_node *rn;
2788
2789 bgp_exterior = bgp->rfapi_cfg->redist_bgp_exterior_view;
2790
2791 if (bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
2792 vnc_zlog_debug_verbose(
2793 "%s: already enabled for afi %d, skipping", __func__,
2794 afi);
2795 return;
2796 }
2797 bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT] = 1;
2798
2799 if (!bgp_exterior) {
2800 vnc_zlog_debug_verbose(
2801 "%s: no exterior view set yet, no routes to import yet",
2802 __func__);
2803 return;
2804 }
2805
2806 for (rn = bgp_table_top(bgp_exterior->rib[afi][SAFI_UNICAST]); rn;
2807 rn = bgp_route_next(rn)) {
2808
2809 struct bgp_info *bi;
2810
2811 for (bi = rn->info; bi; bi = bi->next) {
2812
2813 if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
2814 continue;
2815
2816 vnc_import_bgp_exterior_add_route(bgp_exterior, &rn->p,
2817 bi);
2818 }
2819 }
2820 vnc_zlog_debug_verbose(
2821 "%s: set redist[afi=%d][type=%d=ZEBRA_ROUTE_BGP_DIRECT] return",
2822 __func__, afi, ZEBRA_ROUTE_BGP_DIRECT);
2823 }
2824
2825 /*
2826 * This function is for populating a newly-created Import Table
2827 */
2828 void vnc_import_bgp_exterior_redist_enable_it(
2829 struct bgp *bgp, afi_t afi, struct rfapi_import_table *it_only)
2830 {
2831 struct bgp *bgp_exterior;
2832 struct bgp_node *rn;
2833
2834 vnc_zlog_debug_verbose("%s: entry", __func__);
2835
2836 bgp_exterior = bgp->rfapi_cfg->redist_bgp_exterior_view;
2837
2838 if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
2839 vnc_zlog_debug_verbose("%s: not enabled for afi %d, skipping",
2840 __func__, afi);
2841 return;
2842 }
2843
2844 if (!bgp_exterior) {
2845 vnc_zlog_debug_verbose(
2846 "%s: no exterior view set yet, no routes to import yet",
2847 __func__);
2848 return;
2849 }
2850
2851 for (rn = bgp_table_top(bgp_exterior->rib[afi][SAFI_UNICAST]); rn;
2852 rn = bgp_route_next(rn)) {
2853
2854 struct bgp_info *bi;
2855
2856 for (bi = rn->info; bi; bi = bi->next) {
2857
2858 if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
2859 continue;
2860
2861 vnc_import_bgp_exterior_add_route_it(
2862 bgp_exterior, &rn->p, bi, it_only);
2863 }
2864 }
2865 }
2866
2867
2868 void vnc_import_bgp_redist_disable(struct bgp *bgp, afi_t afi)
2869 {
2870 /*
2871 * iterate over vpn routes, find routes of type ZEBRA_ROUTE_BGP_DIRECT,
2872 * delete (call timer expire immediately)
2873 */
2874 struct bgp_node *rn1;
2875 struct bgp_node *rn2;
2876
2877 vnc_zlog_debug_verbose("%s: entry", __func__);
2878
2879 if (!bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT]) {
2880 vnc_zlog_debug_verbose(
2881 "%s: already disabled for afi %d, skipping", __func__,
2882 afi);
2883 return;
2884 }
2885
2886 /*
2887 * Two-level table for SAFI_MPLS_VPN
2888 * Be careful when changing the things we iterate over
2889 */
2890 for (rn1 = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); rn1;
2891 rn1 = bgp_route_next(rn1)) {
2892
2893 if (rn1->info) {
2894 for (rn2 = bgp_table_top(rn1->info); rn2;
2895 rn2 = bgp_route_next(rn2)) {
2896
2897 struct bgp_info *bi;
2898 struct bgp_info *nextbi;
2899
2900 for (bi = rn2->info; bi; bi = nextbi) {
2901
2902 nextbi = bi->next;
2903
2904 if (bi->type
2905 == ZEBRA_ROUTE_BGP_DIRECT) {
2906
2907 struct rfapi_descriptor *rfd;
2908 vncHDBgpDirect.peer = bi->peer;
2909
2910 assert(bi->extra);
2911
2912 rfd = bi->extra->vnc.export
2913 .rfapi_handle;
2914
2915 vnc_zlog_debug_verbose(
2916 "%s: deleting bi=%p, bi->peer=%p, bi->type=%d, bi->sub_type=%d, bi->extra->vnc.export.rfapi_handle=%p [passing rfd=%p]",
2917 __func__, bi, bi->peer,
2918 bi->type, bi->sub_type,
2919 (bi->extra
2920 ? bi->extra
2921 ->vnc
2922 .export
2923 .rfapi_handle
2924 : NULL),
2925 rfd);
2926
2927
2928 del_vnc_route(
2929 rfd, bi->peer, bgp,
2930 SAFI_MPLS_VPN, &rn2->p,
2931 (struct prefix_rd *)&rn1
2932 ->p,
2933 bi->type, bi->sub_type,
2934 NULL, 1); /* kill */
2935
2936 vncHDBgpDirect.peer = NULL;
2937 }
2938 }
2939 }
2940 }
2941 }
2942 /* Clear RHN list */
2943 if (bgp->rfapi->resolve_nve_nexthop) {
2944 struct prefix_bag *pb;
2945 struct bgp_info *info;
2946 while (!skiplist_first(bgp->rfapi->resolve_nve_nexthop, NULL,
2947 (void *)&pb)) {
2948 info = pb->ubi;
2949 skiplist_delete_first(bgp->rfapi->resolve_nve_nexthop);
2950 bgp_info_unlock(info);
2951 }
2952 }
2953
2954 bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT] = 0;
2955 vnc_zlog_debug_verbose("%s: return", __func__);
2956 }
2957
2958
2959 void vnc_import_bgp_exterior_redist_disable(struct bgp *bgp, afi_t afi)
2960 {
2961 struct rfapi_cfg *hc = bgp->rfapi_cfg;
2962 struct bgp *bgp_exterior = hc->redist_bgp_exterior_view;
2963
2964 vnc_zlog_debug_verbose("%s: entry", __func__);
2965
2966 if (!hc->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT]) {
2967 vnc_zlog_debug_verbose(
2968 "%s: already disabled for afi %d, skipping", __func__,
2969 afi);
2970 return;
2971 }
2972
2973 if (!bgp_exterior) {
2974 vnc_zlog_debug_verbose(
2975 "%s: bgp exterior view not defined, skipping",
2976 __func__);
2977 return;
2978 }
2979
2980
2981 {
2982 struct bgp_node *rn;
2983 for (rn = bgp_table_top(bgp_exterior->rib[afi][SAFI_UNICAST]);
2984 rn; rn = bgp_route_next(rn)) {
2985
2986 struct bgp_info *bi;
2987
2988 for (bi = rn->info; bi; bi = bi->next) {
2989
2990 if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
2991 continue;
2992
2993 vnc_import_bgp_exterior_del_route(bgp_exterior,
2994 &rn->p, bi);
2995 }
2996 }
2997 #if DEBUG_RHN_LIST
2998 print_rhn_list(__func__, NULL);
2999 #endif
3000 }
3001
3002 bgp->rfapi_cfg->redist[afi][ZEBRA_ROUTE_BGP_DIRECT_EXT] = 0;
3003 vnc_zlog_debug_verbose("%s: return", __func__);
3004 }