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