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