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