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