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