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