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