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