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