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