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