]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/rfapi/rfapi_import.c
bgpd: add L3/L2VPN Virtual Network Control feature
[mirror_frr.git] / bgpd / rfapi / rfapi_import.c
CommitLineData
65efcfce
LB
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: rfapi_import.c
24 * Purpose: Handle import of routes from BGP to RFAPI
25 */
26
27#include <errno.h>
28
29#include "zebra.h"
30#include "prefix.h"
31#include "table.h"
32#include "vty.h"
33#include "memory.h"
34#include "log.h"
35#include "skiplist.h"
36#include "thread.h"
37
38#include "bgpd.h"
39#include "bgp_ecommunity.h"
40#include "bgp_attr.h"
41#include "bgp_route.h"
42#include "bgp_mplsvpn.h" /* prefix_rd2str() */
43#include "bgp_vnc_types.h"
44
45#include "rfapi.h"
46#include "bgp_rfapi_cfg.h"
47#include "rfapi_backend.h"
48#include "rfapi_import.h"
49#include "rfapi_private.h"
50#include "rfapi_monitor.h"
51#include "rfapi_nve_addr.h"
52#include "rfapi_vty.h"
53#include "vnc_export_bgp.h"
54#include "vnc_export_bgp_p.h"
55#include "vnc_zebra.h"
56#include "vnc_import_bgp.h"
57#include "vnc_import_bgp_p.h"
58#include "rfapi_rib.h"
59#include "rfapi_encap_tlv.h"
60#include "vnc_debug.h"
61
62#ifdef HAVE_GLIBC_BACKTRACE
63/* for backtrace and friends */
64#include <execinfo.h>
65#endif /* HAVE_GLIBC_BACKTRACE */
66
67#undef DEBUG_MONITOR_MOVE_SHORTER
68#undef DEBUG_RETURNED_NHL
69#undef DEBUG_ROUTE_COUNTERS
70#undef DEBUG_ENCAP_MONITOR
71#undef DEBUG_L2_EXTRA
72#undef DEBUG_IT_NODES
73#undef DEBUG_BI_SEARCH
74
75/*
76 * Allocated for each withdraw timer instance; freed when the timer
77 * expires or is canceled
78 */
79struct rfapi_withdraw
80{
81 struct rfapi_import_table *import_table;
82 struct route_node *node;
83 struct bgp_info *info;
84 safi_t safi; /* used only for bulk operations */
85 /*
86 * For import table node reference count checking (i.e., debugging).
87 * Normally when a timer expires, lockoffset should be 0. However, if
88 * the timer expiration function is called directly (e.g.,
89 * rfapiExpireVpnNow), the node could be locked by a preceding
90 * route_top() or route_next() in a loop, so we need to pass this
91 * value in.
92 */
93 int lockoffset;
94};
95
96/*
97 * DEBUG FUNCTION
98 * It's evil and fiendish. It's compiler-dependent.
99 * ? Might need LDFLAGS -rdynamic to produce all function names
100 */
101void
102rfapiDebugBacktrace (void)
103{
104#ifdef HAVE_GLIBC_BACKTRACE
105#define RFAPI_DEBUG_BACKTRACE_NENTRIES 200
106 void *buf[RFAPI_DEBUG_BACKTRACE_NENTRIES];
107 char **syms;
108 size_t i;
109 size_t size;
110
111 size = backtrace (buf, RFAPI_DEBUG_BACKTRACE_NENTRIES);
112 syms = backtrace_symbols (buf, size);
113
114 for (i = 0; i < size && i < RFAPI_DEBUG_BACKTRACE_NENTRIES; ++i)
115 {
116 zlog_debug ("backtrace[%2lu]: %s", i, syms[i]);
117 }
118
119 free (syms);
120#else
121#endif
122}
123
124/*
125 * DEBUG FUNCTION
126 * Count remote routes and compare with actively-maintained values.
127 * Abort if they disagree.
128 */
129void
130rfapiCheckRouteCount ()
131{
132 struct bgp *bgp = bgp_get_default ();
133 struct rfapi *h;
134 struct rfapi_import_table *it;
135 afi_t afi;
136
137 assert (bgp);
138
139 h = bgp->rfapi;
140 assert (h);
141
142 for (it = h->imports; it; it = it->next)
143 {
144 for (afi = AFI_IP; afi < AFI_MAX; ++afi)
145 {
146
147 struct route_table *rt;
148 struct route_node *rn;
149
150 int holddown_count = 0;
151 int local_count = 0;
152 int imported_count = 0;
153 int remote_count = 0;
154
155 rt = it->imported_vpn[afi];
156
157 for (rn = route_top (rt); rn; rn = route_next (rn))
158 {
159 struct bgp_info *bi;
160 struct bgp_info *next;
161
162 for (bi = rn->info; bi; bi = next)
163 {
164 next = bi->next;
165
166 if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED))
167 {
168 ++holddown_count;
169
170 }
171 else
172 {
173 if (RFAPI_LOCAL_BI (bi))
174 {
175 ++local_count;
176 }
177 else
178 {
179 if (RFAPI_DIRECT_IMPORT_BI (bi))
180 {
181 ++imported_count;
182 }
183 else
184 {
185 ++remote_count;
186 }
187 }
188 }
189 }
190 }
191
192 if (it->holddown_count[afi] != holddown_count)
193 {
194 zlog_debug ("%s: it->holddown_count %d != holddown_count %d",
195 __func__, it->holddown_count[afi], holddown_count);
196 assert (0);
197 }
198 if (it->remote_count[afi] != remote_count)
199 {
200 zlog_debug ("%s: it->remote_count %d != remote_count %d",
201 __func__, it->remote_count[afi], remote_count);
202 assert (0);
203 }
204 if (it->imported_count[afi] != imported_count)
205 {
206 zlog_debug ("%s: it->imported_count %d != imported_count %d",
207 __func__, it->imported_count[afi], imported_count);
208 assert (0);
209 }
210 }
211 }
212}
213
214#if DEBUG_ROUTE_COUNTERS
215#define VNC_ITRCCK do {rfapiCheckRouteCount();} while (0)
216#else
217#define VNC_ITRCCK
218#endif
219
220/*
221 * Validate reference count for a node in an import table
222 *
223 * Normally lockoffset is 0 for nodes in quiescent state. However,
224 * route_unlock_node will delete the node if it is called when
225 * node->lock == 1, and we have to validate the refcount before
226 * the node is deleted. In this case, we specify lockoffset 1.
227 */
228void
229rfapiCheckRefcount (struct route_node *rn, safi_t safi, int lockoffset)
230{
231 unsigned int count_bi = 0;
232 unsigned int count_monitor = 0;
233 struct bgp_info *bi;
234 struct rfapi_monitor_encap *hme;
235 struct rfapi_monitor_vpn *hmv;
236
237 for (bi = rn->info; bi; bi = bi->next)
238 ++count_bi;
239
240
241 if (rn->aggregate)
242 {
243 ++count_monitor; /* rfapi_it_extra */
244
245 switch (safi)
246 {
247 void *cursor;
248 int rc;
249
250 case SAFI_ENCAP:
251 for (hme = RFAPI_MONITOR_ENCAP (rn); hme; hme = hme->next)
252 ++count_monitor;
253 break;
254
255 case SAFI_MPLS_VPN:
256
257 for (hmv = RFAPI_MONITOR_VPN (rn); hmv; hmv = hmv->next)
258 ++count_monitor;
259
260 if (RFAPI_MONITOR_EXTERIOR (rn)->source)
261 {
262 ++count_monitor; /* sl */
263 cursor = NULL;
264 for (rc = skiplist_next (RFAPI_MONITOR_EXTERIOR (rn)->source,
265 NULL, NULL, &cursor);
266 !rc;
267 rc = skiplist_next (RFAPI_MONITOR_EXTERIOR (rn)->source,
268 NULL, NULL, &cursor))
269 {
270
271 ++count_monitor; /* sl entry */
272 }
273 }
274 break;
275
276 default:
277 assert (0);
278 }
279 }
280
281 if (count_bi + count_monitor + lockoffset != rn->lock)
282 {
283 zlog_debug
284 ("%s: count_bi=%d, count_monitor=%d, lockoffset=%d, rn->lock=%d",
285 __func__, count_bi, count_monitor, lockoffset, rn->lock);
286 assert (0);
287 }
288}
289
290/*
291 * Perform deferred rfapi_close operations that were queued
292 * during callbacks.
293 */
294static wq_item_status
295rfapi_deferred_close_workfunc (struct work_queue *q, void *data)
296{
297 struct rfapi_descriptor *rfd = data;
298 struct rfapi *h = q->spec.data;
299
300 assert (!(h->flags & RFAPI_INCALLBACK));
301 rfapi_close (rfd);
302 zlog_debug ("%s: completed deferred close on handle %p", __func__, rfd);
303 return WQ_SUCCESS;
304}
305
306/*
307 * Extract layer 2 option from Encap TLVS in BGP attrs
308 */
309int
310rfapiGetL2o (struct attr *attr, struct rfapi_l2address_option *l2o)
311{
312 if (attr && attr->extra)
313 {
314
315 struct bgp_attr_encap_subtlv *pEncap;
316
317 for (pEncap = attr->extra->vnc_subtlvs; pEncap; pEncap = pEncap->next)
318 {
319
320 if (pEncap->type == BGP_VNC_SUBTLV_TYPE_RFPOPTION)
321 {
322 if (pEncap->value[0] == RFAPI_VN_OPTION_TYPE_L2ADDR)
323 {
324
325 if (pEncap->value[1] == 14)
326 {
327 memcpy (l2o->macaddr.octet, pEncap->value + 2,
328 ETHER_ADDR_LEN);
329 l2o->label =
330 ((pEncap->value[10] >> 4) & 0x0f) +
331 ((pEncap->value[9] << 4) & 0xff0) +
332 ((pEncap->value[8] << 12) & 0xff000);
333
334 l2o->local_nve_id = pEncap->value[12];
335
336 l2o->logical_net_id =
337 (pEncap->value[15] & 0xff) +
338 ((pEncap->value[14] << 8) & 0xff00) +
339 ((pEncap->value[13] << 16) & 0xff0000);
340 }
341
342 return 0;
343 }
344 }
345 }
346 }
347
348 return ENOENT;
349}
350
351/*
352 * Extract the lifetime from the Tunnel Encap attribute of a route in
353 * an import table
354 */
355int
356rfapiGetVncLifetime (struct attr *attr, uint32_t * lifetime)
357{
358 struct bgp_attr_encap_subtlv *pEncap;
359
360 *lifetime = RFAPI_INFINITE_LIFETIME; /* default to infinite */
361
362 if (attr && attr->extra)
363 {
364
365 for (pEncap = attr->extra->vnc_subtlvs; pEncap; pEncap = pEncap->next)
366 {
367
368 if (pEncap->type == BGP_VNC_SUBTLV_TYPE_LIFETIME)
369 { /* lifetime */
370 if (pEncap->length == 4)
371 {
372 memcpy (lifetime, pEncap->value, 4);
373 *lifetime = ntohl (*lifetime);
374 return 0;
375 }
376 }
377 }
378 }
379
380 return ENOENT;
381}
382
383/*
384 * Extract the tunnel type from the extended community
385 */
386int
387rfapiGetTunnelType (struct attr *attr,
388 bgp_encap_types *type)
389{
390 *type = BGP_ENCAP_TYPE_MPLS; /* default to MPLS */
391 if (attr && attr->extra && attr->extra->ecommunity)
392 {
393 struct ecommunity *ecom = attr->extra->ecommunity;
394 int i;
395
396 for (i = 0; i < (ecom->size * ECOMMUNITY_SIZE); i += ECOMMUNITY_SIZE)
397 {
398 uint8_t *ep;
399
400 ep = ecom->val + i;
401 if (ep[0] == ECOMMUNITY_ENCODE_OPAQUE &&
402 ep[1] == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP)
403 {
404 *type = (ep[6]<<8) + ep[7];
405 return 0;
406 }
407 }
408 }
409
410 return ENOENT;
411}
412
413
414/*
415 * Look for UN address in Encap attribute
416 */
417int
418rfapiGetVncTunnelUnAddr (struct attr *attr, struct prefix *p)
419{
420 struct bgp_attr_encap_subtlv *pEncap;
421 bgp_encap_types tun_type;
422
423 rfapiGetTunnelType (attr, &tun_type);
424 if (p && tun_type == BGP_ENCAP_TYPE_MPLS)
425 {
426 /* MPLS carries UN address in next hop */
427 rfapiNexthop2Prefix (attr, p);
428 if (p->family != 0)
429 return 0;
430 }
431 if (attr && attr->extra)
432 {
433 for (pEncap = attr->extra->encap_subtlvs; pEncap; pEncap = pEncap->next)
434 {
435
436 if (pEncap->type == BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT)
437 { /* un addr */
438 switch (pEncap->length)
439 {
440 case 8:
441 if (p)
442 {
443 p->family = AF_INET;
444 p->prefixlen = 32;
445 memcpy (p->u.val, pEncap->value, 4);
446 }
447 return 0;
448
449 case 20:
450 if (p)
451 {
452 p->family = AF_INET6;
453 p->prefixlen = 128;
454 memcpy (p->u.val, pEncap->value, 16);
455 }
456 return 0;
457 }
458 }
459 }
460 }
461
462 return ENOENT;
463}
464
465/*
466 * Get UN address wherever it might be
467 */
468int
469rfapiGetUnAddrOfVpnBi (struct bgp_info *bi, struct prefix *p)
470{
471 /* If it's in this route's VNC attribute, we're done */
472 if (!rfapiGetVncTunnelUnAddr (bi->attr, p))
473 return 0;
474 /*
475 * Otherwise, see if it's cached from a corresponding ENCAP SAFI
476 * advertisement
477 */
478 if (bi->extra)
479 {
480 switch (bi->extra->vnc.import.un_family)
481 {
482 case AF_INET:
483 if (p)
484 {
485 p->family = bi->extra->vnc.import.un_family;
486 p->u.prefix4 = bi->extra->vnc.import.un.addr4;
487 p->prefixlen = 32;
488 }
489 return 0;
490 case AF_INET6:
491 if (p)
492 {
493 p->family = bi->extra->vnc.import.un_family;
494 p->u.prefix6 = bi->extra->vnc.import.un.addr6;
495 p->prefixlen = 128;
496 }
497 return 0;
498 default:
499 if (p)
500 p->family = 0;
501#if DEBUG_ENCAP_MONITOR
502 zlog_debug ("%s: bi->extra->vnc.import.un_family is 0, no UN addr",
503 __func__);
504#endif
505 break;
506 }
507 }
508
509 return ENOENT;
510}
511
512
513/*
514 * Make a new bgp_info from gathered parameters
515 */
516static struct bgp_info *
517rfapiBgpInfoCreate (
518 struct attr *attr,
519 struct peer *peer,
520 void *rfd,
521 struct prefix_rd *prd,
522 u_char type,
523 u_char sub_type,
524 uint32_t *label)
525{
526 struct bgp_info *new;
527
528 new = bgp_info_new ();
529 assert (new);
530
531 if (attr)
532 {
533 if (!new->attr)
534 new->attr = bgp_attr_intern (attr);
535 }
536 bgp_info_extra_get (new);
537 if (prd)
538 {
539 new->extra->vnc.import.rd = *prd;
540 rfapi_time (&new->extra->vnc.import.create_time);
541 }
542 if (label)
543 encode_label (*label, new->extra->tag);
544 new->type = type;
545 new->sub_type = sub_type;
546 new->peer = peer;
547 peer_lock (peer);
548
549 return new;
550}
551
552/*
553 * Frees bgp_info as used in import tables (parts are not
554 * allocated exactly the way they are in the main RIBs)
555 */
556static void
557rfapiBgpInfoFree (struct bgp_info *goner)
558{
559 if (!goner)
560 return;
561
562 if (goner->peer)
563 {
564 zlog_debug ("%s: calling peer_unlock(%p), #%d",
565 __func__, goner->peer, goner->peer->lock);
566 peer_unlock (goner->peer);
567 }
568
569 if (goner->attr)
570 {
571 bgp_attr_unintern (&goner->attr);
572 }
573 if (goner->extra)
574 {
575 assert (!goner->extra->damp_info); /* Not used in import tbls */
576 XFREE (MTYPE_BGP_ROUTE_EXTRA, goner->extra);
577 goner->extra = NULL;
578 }
579 XFREE (MTYPE_BGP_ROUTE, goner);
580}
581
582struct rfapi_import_table *
583rfapiMacImportTableGetNoAlloc (struct bgp *bgp, uint32_t lni)
584{
585 struct rfapi *h;
586 struct rfapi_import_table *it = NULL;
587 uintptr_t lni_as_ptr = lni;
588
589 h = bgp->rfapi;
590 if (!h)
591 return NULL;
592
593 if (!h->import_mac)
594 return NULL;
595
596 if (skiplist_search (h->import_mac, (void *) lni_as_ptr, (void **) &it))
597 return NULL;
598
599 return it;
600}
601
602struct rfapi_import_table *
603rfapiMacImportTableGet (struct bgp *bgp, uint32_t lni)
604{
605 struct rfapi *h;
606 struct rfapi_import_table *it = NULL;
607 uintptr_t lni_as_ptr = lni;
608
609 h = bgp->rfapi;
610 assert (h);
611
612 if (!h->import_mac)
613 {
614 /* default cmp is good enough for LNI */
615 h->import_mac = skiplist_new (0, NULL, NULL);
616 }
617
618 if (skiplist_search (h->import_mac, (void *) lni_as_ptr, (void **) &it))
619 {
620
621 struct ecommunity *enew;
622 struct ecommunity_val eval;
623 afi_t afi;
624
625 it =
626 XCALLOC (MTYPE_RFAPI_IMPORTTABLE, sizeof (struct rfapi_import_table));
627 /* set RT list of new import table based on LNI */
628 memset ((char *) &eval, 0, sizeof (eval));
629 eval.val[0] = 0; /* VNC L2VPN */
630 eval.val[1] = 2; /* VNC L2VPN */
631 eval.val[5] = (lni >> 16) & 0xff;
632 eval.val[6] = (lni >> 8) & 0xff;
633 eval.val[7] = (lni >> 0) & 0xff;
634
635 enew = ecommunity_new ();
636 ecommunity_add_val (enew, &eval);
637 it->rt_import_list = enew;
638
639 for (afi = AFI_IP; afi < AFI_MAX; ++afi)
640 {
641 it->imported_vpn[afi] = route_table_init ();
642 it->imported_encap[afi] = route_table_init ();
643 }
644
645 it->l2_logical_net_id = lni;
646
647 skiplist_insert (h->import_mac, (void *) lni_as_ptr, it);
648 }
649
650 assert (it);
651 return it;
652}
653
654/*
655 * Implement MONITOR_MOVE_SHORTER(original_node) from
656 * RFAPI-Import-Event-Handling.txt
657 *
658 * Returns pointer to the list of moved monitors
659 */
660static struct rfapi_monitor_vpn *
661rfapiMonitorMoveShorter (struct route_node *original_vpn_node, int lockoffset)
662{
663 struct bgp_info *bi;
664 struct route_node *par;
665 struct rfapi_monitor_vpn *m;
666 struct rfapi_monitor_vpn *mlast;
667 struct rfapi_monitor_vpn *moved;
668 int movecount = 0;
669 int parent_already_refcounted = 0;
670
671 RFAPI_CHECK_REFCOUNT (original_vpn_node, SAFI_MPLS_VPN, lockoffset);
672
673#if DEBUG_MONITOR_MOVE_SHORTER
674 {
675 char buf[BUFSIZ];
676
677 prefix2str (&original_vpn_node->p, buf, BUFSIZ);
678 buf[BUFSIZ - 1] = 0;
679 zlog_debug ("%s: called with node pfx=%s", __func__, buf);
680 }
681#endif
682
683 /*
684 * 1. If there is at least one bi (either regular route or
685 * route marked as withdrawn, with a pending timer) at
686 * original_node with a valid UN address, we're done. Return.
687 */
688 for (bi = original_vpn_node->info; bi; bi = bi->next)
689 {
690 struct prefix pfx;
691
692 if (!rfapiGetUnAddrOfVpnBi (bi, &pfx))
693 {
694#if DEBUG_MONITOR_MOVE_SHORTER
695 zlog_debug ("%s: have valid UN at original node, no change",
696 __func__);
697#endif
698 return NULL;
699 }
700 }
701
702 /*
703 * 2. Travel up the tree (toward less-specific prefixes) from
704 * original_node to find the first node that has at least
705 * one route (even if it is only a withdrawn route) with a
706 * valid UN address. Call this node "Node P."
707 */
708 for (par = original_vpn_node->parent; par; par = par->parent)
709 {
710 for (bi = par->info; bi; bi = bi->next)
711 {
712 struct prefix pfx;
713 if (!rfapiGetUnAddrOfVpnBi (bi, &pfx))
714 {
715 break;
716 }
717 }
718 if (bi)
719 break;
720 }
721
722 if (par)
723 {
724 RFAPI_CHECK_REFCOUNT (par, SAFI_MPLS_VPN, 0);
725 }
726
727 /*
728 * If no less-specific routes, try to use the 0/0 node
729 */
730 if (!par)
731 {
732 /* this isn't necessarily 0/0 */
733 par = route_top (original_vpn_node->table);
734
735 /*
736 * If we got the top node but it wasn't 0/0,
737 * ignore it
738 */
739 if (par && par->p.prefixlen)
740 {
741 route_unlock_node (par); /* maybe free */
742 par = NULL;
743 }
744
745 if (par)
746 {
747 ++parent_already_refcounted;
748 }
749 }
750
751 /*
752 * Create 0/0 node if it isn't there
753 */
754 if (!par)
755 {
756 struct prefix pfx_default;
757
758 memset (&pfx_default, 0, sizeof (pfx_default));
759 pfx_default.family = original_vpn_node->p.family;
760
761 /* creates default node if none exists */
762 par = route_node_get (original_vpn_node->table, &pfx_default);
763 ++parent_already_refcounted;
764 }
765
766 /*
767 * 3. Move each of the monitors found at original_node to Node P.
768 * These are "Moved Monitors."
769 *
770 */
771
772 /*
773 * Attach at end so that the list pointer we return points
774 * only to the moved routes
775 */
776 for (m = RFAPI_MONITOR_VPN (par), mlast = NULL; m; mlast = m, m = m->next);
777
778 if (mlast)
779 {
780 moved = mlast->next = RFAPI_MONITOR_VPN (original_vpn_node);
781 }
782 else
783 {
784 moved = RFAPI_MONITOR_VPN_W_ALLOC (par) =
785 RFAPI_MONITOR_VPN (original_vpn_node);
786 }
787 if (RFAPI_MONITOR_VPN (original_vpn_node)) /* check agg, so not allocated */
788 RFAPI_MONITOR_VPN_W_ALLOC (original_vpn_node) = NULL;
789
790 /*
791 * update the node pointers on the monitors
792 */
793 for (m = moved; m; m = m->next)
794 {
795 ++movecount;
796 m->node = par;
797 }
798
799 RFAPI_CHECK_REFCOUNT (par, SAFI_MPLS_VPN,
800 parent_already_refcounted - movecount);
801 while (movecount > parent_already_refcounted)
802 {
803 route_lock_node (par);
804 ++parent_already_refcounted;
805 }
806 while (movecount < parent_already_refcounted)
807 {
808 /* unlikely, but code defensively */
809 route_unlock_node (par);
810 --parent_already_refcounted;
811 }
812 RFAPI_CHECK_REFCOUNT (original_vpn_node, SAFI_MPLS_VPN,
813 movecount + lockoffset);
814 while (movecount--)
815 {
816 route_unlock_node (original_vpn_node);
817 }
818
819#if DEBUG_MONITOR_MOVE_SHORTER
820 {
821 char buf[BUFSIZ];
822
823 prefix2str (&par->p, buf, BUFSIZ);
824 buf[BUFSIZ - 1] = 0;
825 zlog_debug ("%s: moved to node pfx=%s", __func__, buf);
826 }
827#endif
828
829
830 return moved;
831}
832
833/*
834 * Implement MONITOR_MOVE_LONGER(new_node) from
835 * RFAPI-Import-Event-Handling.txt
836 */
837static void
838rfapiMonitorMoveLonger (struct route_node *new_vpn_node)
839{
840 struct rfapi_monitor_vpn *monitor;
841 struct rfapi_monitor_vpn *mlast;
842 struct bgp_info *bi;
843 struct route_node *par;
844
845 RFAPI_CHECK_REFCOUNT (new_vpn_node, SAFI_MPLS_VPN, 0);
846
847 /*
848 * Make sure we have at least one valid route at the new node
849 */
850 for (bi = new_vpn_node->info; bi; bi = bi->next)
851 {
852 struct prefix pfx;
853 if (!rfapiGetUnAddrOfVpnBi (bi, &pfx))
854 break;
855 }
856
857 if (!bi)
858 {
859 zlog_debug ("%s: no valid routes at node %p, so not attempting moves",
860 __func__, new_vpn_node);
861 return;
862 }
863
864 /*
865 * Find first parent node that has monitors
866 */
867 for (par = new_vpn_node->parent; par; par = par->parent)
868 {
869 if (RFAPI_MONITOR_VPN (par))
870 break;
871 }
872
873 if (!par)
874 {
875 zlog_debug ("%s: no parent nodes with monitors, done", __func__);
876 return;
877 }
878
879 /*
880 * Check each of these monitors to see of their longest-match
881 * is now the updated node. Move any such monitors to the more-
882 * specific updated node
883 */
884 for (mlast = NULL, monitor = RFAPI_MONITOR_VPN (par); monitor;)
885 {
886
887 /*
888 * If new longest match for monitor prefix is the new
889 * route's prefix, move monitor to new route's prefix
890 */
891 if (prefix_match (&new_vpn_node->p, &monitor->p))
892 {
893 /* detach */
894 if (mlast)
895 {
896 mlast->next = monitor->next;
897 }
898 else
899 {
900 RFAPI_MONITOR_VPN_W_ALLOC (par) = monitor->next;
901 }
902
903
904 /* attach */
905 monitor->next = RFAPI_MONITOR_VPN (new_vpn_node);
906 RFAPI_MONITOR_VPN_W_ALLOC (new_vpn_node) = monitor;
907 monitor->node = new_vpn_node;
908
909 route_lock_node (new_vpn_node); /* incr refcount */
910
911 monitor = mlast ? mlast->next : RFAPI_MONITOR_VPN (par);
912
913 RFAPI_CHECK_REFCOUNT (par, SAFI_MPLS_VPN, 1);
914 /* decr refcount after we're done with par as this might free it */
915 route_unlock_node (par);
916
917 continue;
918 }
919 mlast = monitor;
920 monitor = monitor->next;
921 }
922
923 RFAPI_CHECK_REFCOUNT (new_vpn_node, SAFI_MPLS_VPN, 0);
924}
925
926
927static void
928rfapiBgpInfoChainFree (struct bgp_info *bi)
929{
930 struct bgp_info *next;
931
932 while (bi)
933 {
934
935 /*
936 * If there is a timer waiting to delete this bi, cancel
937 * the timer and delete immediately
938 */
939 if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED) &&
940 bi->extra->vnc.import.timer)
941 {
942
943 struct thread *t = (struct thread *) bi->extra->vnc.import.timer;
944 struct rfapi_withdraw *wcb = t->arg;
945
946 XFREE (MTYPE_RFAPI_WITHDRAW, wcb);
947 thread_cancel (t);
948 }
949
950 next = bi->next;
951 bi->next = NULL;
952 rfapiBgpInfoFree (bi);
953 bi = next;
954 }
955}
956
957static void
958rfapiImportTableFlush (struct rfapi_import_table *it)
959{
960 afi_t afi;
961
962 /*
963 * Free ecommunity
964 */
965 ecommunity_free (&it->rt_import_list);
966 it->rt_import_list = NULL;
967
968 for (afi = AFI_IP; afi < AFI_MAX; ++afi)
969 {
970
971 struct route_node *rn;
972
973 for (rn = route_top (it->imported_vpn[afi]); rn; rn = route_next (rn))
974 {
975 /*
976 * Each route_node has:
977 * aggregate: points to rfapi_it_extra with monitor chain(s)
978 * info: points to chain of bgp_info
979 */
980 /* free bgp_info and its children */
981 rfapiBgpInfoChainFree (rn->info);
982 rn->info = NULL;
983
984 rfapiMonitorExtraFlush (SAFI_MPLS_VPN, rn);
985 }
986
987 for (rn = route_top (it->imported_encap[afi]); rn; rn = route_next (rn))
988 {
989 /* free bgp_info and its children */
990 rfapiBgpInfoChainFree (rn->info);
991 rn->info = NULL;
992
993 rfapiMonitorExtraFlush (SAFI_ENCAP, rn);
994 }
995
996 route_table_finish (it->imported_vpn[afi]);
997 route_table_finish (it->imported_encap[afi]);
998 }
999 if (it->monitor_exterior_orphans)
1000 {
1001 skiplist_free (it->monitor_exterior_orphans);
1002 }
1003}
1004
1005void
1006rfapiImportTableRefDelByIt (
1007 struct bgp *bgp,
1008 struct rfapi_import_table *it_target)
1009{
1010 struct rfapi *h;
1011 struct rfapi_import_table *it;
1012 struct rfapi_import_table *prev = NULL;
1013
1014 assert (it_target);
1015
1016 h = bgp->rfapi;
1017 assert (h);
1018
1019 for (it = h->imports; it; prev = it, it = it->next)
1020 {
1021 if (it == it_target)
1022 break;
1023 }
1024
1025 assert (it);
1026 assert (it->refcount);
1027
1028 it->refcount -= 1;
1029
1030 if (!it->refcount)
1031 {
1032 if (prev)
1033 {
1034 prev->next = it->next;
1035 }
1036 else
1037 {
1038 h->imports = it->next;
1039 }
1040 rfapiImportTableFlush (it);
1041 XFREE (MTYPE_RFAPI_IMPORTTABLE, it);
1042 }
1043}
1044
1045#if RFAPI_REQUIRE_ENCAP_BEEC
1046/*
1047 * Look for magic BGP Encapsulation Extended Community value
1048 * Format in RFC 5512 Sect. 4.5
1049 */
1050static int
1051rfapiEcommunitiesMatchBeec (struct ecommunity *ecom,
1052 bgp_encap_types type)
1053{
1054 int i;
1055
1056 if (!ecom)
1057 return 0;
1058
1059 for (i = 0; i < (ecom->size * ECOMMUNITY_SIZE); i += ECOMMUNITY_SIZE)
1060 {
1061
1062 uint8_t *ep;
1063
1064 ep = ecom->val + i;
1065
1066 if (ep[0] == ECOMMUNITY_ENCODE_OPAQUE &&
1067 ep[1] == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP &&
1068 ep[6] == ((type && 0xff00)>>8) &&
1069 ep[7] == (type&0xff))
1070 {
1071
1072 return 1;
1073 }
1074 }
1075 return 0;
1076
1077}
1078#endif
1079
1080int
1081rfapiEcommunitiesIntersect (struct ecommunity *e1, struct ecommunity *e2)
1082{
1083 int i, j;
1084
1085 if (!e1 || !e2)
1086 return 0;
1087
1088 {
1089 char *s1, *s2;
1090 s1 = ecommunity_ecom2str (e1, ECOMMUNITY_FORMAT_DISPLAY);
1091 s2 = ecommunity_ecom2str (e2, ECOMMUNITY_FORMAT_DISPLAY);
1092 zlog_debug ("%s: e1[%s], e2[%s]", __func__, s1, s2);
1093 XFREE (MTYPE_ECOMMUNITY_STR, s1);
1094 XFREE (MTYPE_ECOMMUNITY_STR, s2);
1095 }
1096
1097 for (i = 0; i < e1->size; ++i)
1098 {
1099 for (j = 0; j < e2->size; ++j)
1100 {
1101 if (!memcmp (e1->val + (i * ECOMMUNITY_SIZE),
1102 e2->val + (j * ECOMMUNITY_SIZE), ECOMMUNITY_SIZE))
1103 {
1104
1105 return 1;
1106 }
1107 }
1108 }
1109 return 0;
1110}
1111
1112int
1113rfapiEcommunityGetLNI (struct ecommunity *ecom, uint32_t * lni)
1114{
1115 if (ecom)
1116 {
1117 int i;
1118 for (i = 0; i < ecom->size; ++i)
1119 {
1120 uint8_t *p = ecom->val + (i * ECOMMUNITY_SIZE);
1121
1122 if ((*(p + 0) == 0x00) && (*(p + 1) == 0x02))
1123 {
1124
1125 *lni = (*(p + 5) << 16) | (*(p + 6) << 8) | (*(p + 7));
1126 return 0;
1127 }
1128 }
1129 }
1130 return ENOENT;
1131}
1132
1133static int
1134rfapiVpnBiNhEqualsPt (struct bgp_info *bi, struct rfapi_ip_addr *hpt)
1135{
1136 uint8_t family;
1137
1138 if (!hpt || !bi)
1139 return 0;
1140
1141 family = BGP_MP_NEXTHOP_FAMILY (bi->attr->extra->mp_nexthop_len);
1142
1143 if (hpt->addr_family != family)
1144 return 0;
1145
1146 switch (family)
1147 {
1148 case AF_INET:
1149 if (bi->attr->extra->mp_nexthop_global_in.s_addr != hpt->addr.v4.s_addr)
1150 return 0;
1151 break;
1152
1153 case AF_INET6:
1154 if (IPV6_ADDR_CMP (&bi->attr->extra->mp_nexthop_global, &hpt->addr.v6))
1155 return 0;
1156 break;
1157
1158 default:
1159 return 0;
1160 break;
1161 }
1162
1163 return 1;
1164}
1165
1166
1167/*
1168 * Compare 2 VPN BIs. Return true if they have the same VN and UN addresses
1169 */
1170static int
1171rfapiVpnBiSamePtUn (struct bgp_info *bi1, struct bgp_info *bi2)
1172{
1173 struct prefix pfx_un1;
1174 struct prefix pfx_un2;
1175
1176 if (!bi1 || !bi2)
1177 return 0;
1178
1179 if (!bi1->attr || !bi2->attr)
1180 return 0;
1181
1182 if (!bi1->attr->extra || !bi2->attr->extra)
1183 return 0;
1184
1185 /*
1186 * VN address comparisons
1187 */
1188
1189 if (BGP_MP_NEXTHOP_FAMILY (bi1->attr->extra->mp_nexthop_len) !=
1190 BGP_MP_NEXTHOP_FAMILY (bi2->attr->extra->mp_nexthop_len))
1191 {
1192 return 0;
1193 }
1194
1195 switch (BGP_MP_NEXTHOP_FAMILY (bi1->attr->extra->mp_nexthop_len))
1196 {
1197
1198 case AF_INET:
1199 if (bi1->attr->extra->mp_nexthop_global_in.s_addr !=
1200 bi2->attr->extra->mp_nexthop_global_in.s_addr)
1201 return 0;
1202 break;
1203
1204 case AF_INET6:
1205 if (IPV6_ADDR_CMP (&bi1->attr->extra->mp_nexthop_global,
1206 &bi2->attr->extra->mp_nexthop_global))
1207 return 0;
1208 break;
1209
1210 default:
1211 return 0;
1212 break;
1213 }
1214
1215 /*
1216 * UN address comparisons
1217 */
1218 if (rfapiGetVncTunnelUnAddr (bi1->attr, &pfx_un1))
1219 {
1220 if (bi1->extra)
1221 {
1222 pfx_un1.family = bi1->extra->vnc.import.un_family;
1223 switch (bi1->extra->vnc.import.un_family)
1224 {
1225 case AF_INET:
1226 pfx_un1.u.prefix4 = bi1->extra->vnc.import.un.addr4;
1227 break;
1228 case AF_INET6:
1229 pfx_un1.u.prefix6 = bi1->extra->vnc.import.un.addr6;
1230 break;
1231 default:
1232 pfx_un1.family = 0;
1233 break;
1234 }
1235 }
1236 }
1237
1238 if (rfapiGetVncTunnelUnAddr (bi2->attr, &pfx_un2))
1239 {
1240 if (bi2->extra)
1241 {
1242 pfx_un2.family = bi2->extra->vnc.import.un_family;
1243 switch (bi2->extra->vnc.import.un_family)
1244 {
1245 case AF_INET:
1246 pfx_un2.u.prefix4 = bi2->extra->vnc.import.un.addr4;
1247 break;
1248 case AF_INET6:
1249 pfx_un2.u.prefix6 = bi2->extra->vnc.import.un.addr6;
1250 break;
1251 default:
1252 pfx_un2.family = 0;
1253 break;
1254 }
1255 }
1256 }
1257
1258 if (!pfx_un1.family || !pfx_un2.family)
1259 return 0;
1260
1261 if (pfx_un1.family != pfx_un2.family)
1262 return 0;
1263
1264 switch (pfx_un1.family)
1265 {
1266 case AF_INET:
1267 if (!IPV4_ADDR_SAME
1268 (&pfx_un1.u.prefix4.s_addr, &pfx_un2.u.prefix4.s_addr))
1269 return 0;
1270 break;
1271 case AF_INET6:
1272 if (!IPV6_ADDR_SAME (&pfx_un1.u.prefix6, &pfx_un2.u.prefix6))
1273 return 0;
1274 break;
1275 }
1276
1277
1278
1279 return 1;
1280}
1281
1282uint8_t
1283rfapiRfpCost (struct attr * attr)
1284{
1285 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
1286 {
1287 if (attr->local_pref > 255)
1288 {
1289 return 0;
1290 }
1291 return 255 - attr->local_pref;
1292 }
1293
1294 return 255;
1295}
1296
1297/*------------------------------------------
1298 * rfapi_extract_l2o
1299 *
1300 * Find Layer 2 options in an option chain
1301 *
1302 * input:
1303 * pHop option chain
1304 *
1305 * output:
1306 * l2o layer 2 options extracted
1307 *
1308 * return value:
1309 * 0 OK
1310 * 1 no options found
1311 *
1312 --------------------------------------------*/
1313int
1314rfapi_extract_l2o (struct bgp_tea_options *pHop, /* chain of options */
1315 struct rfapi_l2address_option *l2o) /* return extracted value */
1316{
1317 struct bgp_tea_options *p;
1318
1319 for (p = pHop; p; p = p->next)
1320 {
1321 if ((p->type == RFAPI_VN_OPTION_TYPE_L2ADDR) && (p->length >= 8))
1322 {
1323
1324 char *v = p->value;
1325
1326 memcpy (&l2o->macaddr, v, 6);
1327
1328 l2o->label =
1329 ((v[6] << 12) & 0xff000) +
1330 ((v[7] << 4) & 0xff0) + ((v[8] >> 4) & 0xf);
1331
1332 l2o->local_nve_id = (uint8_t) v[10];
1333
1334 l2o->logical_net_id = (v[11] << 16) + (v[12] << 8) + (v[13] << 0);
1335
1336 return 0;
1337 }
1338 }
1339 return 1;
1340}
1341
1342static struct rfapi_next_hop_entry *
1343rfapiRouteInfo2NextHopEntry (
1344 struct rfapi_ip_prefix *rprefix,
1345 struct bgp_info *bi, /* route to encode */
1346 uint32_t lifetime, /* use this in nhe */
1347 struct route_node *rn) /* req for L2 eth addr */
1348{
1349 struct rfapi_next_hop_entry *new;
1350 int have_vnc_tunnel_un = 0;
1351
1352#if DEBUG_ENCAP_MONITOR
1353 zlog_debug ("%s: entry, bi %p, rn %p", __func__, bi, rn);
1354#endif
1355
1356 new = XCALLOC (MTYPE_RFAPI_NEXTHOP, sizeof (struct rfapi_next_hop_entry));
1357 assert (new);
1358
1359 new->prefix = *rprefix;
1360
1361 if (bi->extra &&
1362 decode_rd_type(bi->extra->vnc.import.rd.val) == RD_TYPE_VNC_ETH)
1363 {
1364 /* ethernet */
1365
1366 struct rfapi_vn_option *vo;
1367
1368 vo = XCALLOC (MTYPE_RFAPI_VN_OPTION, sizeof (struct rfapi_vn_option));
1369 assert (vo);
1370
1371 vo->type = RFAPI_VN_OPTION_TYPE_L2ADDR;
1372
1373 memcpy (&vo->v.l2addr.macaddr, &rn->p.u.prefix_eth.octet,
1374 ETHER_ADDR_LEN);
1375 /* only low 3 bytes of this are significant */
1376 if (bi->attr && bi->attr->extra)
1377 {
1378 (void) rfapiEcommunityGetLNI (bi->attr->extra->ecommunity,
1379 &vo->v.l2addr.logical_net_id);
1380 }
1381
1382 /* local_nve_id comes from lower byte of RD type */
1383 vo->v.l2addr.local_nve_id = bi->extra->vnc.import.rd.val[1];
1384
1385 /* label comes from MP_REACH_NLRI label */
1386 vo->v.l2addr.label = decode_label (bi->extra->tag);
1387
1388 new->vn_options = vo;
1389
1390 /*
1391 * If there is an auxiliary prefix (i.e., host IP address),
1392 * use it as the nexthop prefix instead of the query prefix
1393 */
1394 if (bi->extra->vnc.import.aux_prefix.family)
1395 {
1396 rfapiQprefix2Rprefix (&bi->extra->vnc.import.aux_prefix,
1397 &new->prefix);
1398 }
1399 }
1400
1401 if (bi->attr)
1402 {
1403 bgp_encap_types tun_type;
1404 new->prefix.cost = rfapiRfpCost (bi->attr);
1405
1406 if (bi->attr->extra)
1407 {
1408
1409 struct bgp_attr_encap_subtlv *pEncap;
1410
1411 switch (BGP_MP_NEXTHOP_FAMILY (bi->attr->extra->mp_nexthop_len))
1412 {
1413 case AF_INET:
1414 new->vn_address.addr_family = AF_INET;
1415 new->vn_address.addr.v4 = bi->attr->extra->mp_nexthop_global_in;
1416 break;
1417
1418 case AF_INET6:
1419 new->vn_address.addr_family = AF_INET6;
1420 new->vn_address.addr.v6 = bi->attr->extra->mp_nexthop_global;
1421 break;
1422
1423 default:
1424 zlog_warn ("%s: invalid vpn nexthop length: %d",
1425 __func__, bi->attr->extra->mp_nexthop_len);
1426 rfapi_free_next_hop_list (new);
1427 return NULL;
1428 }
1429
1430 for (pEncap = bi->attr->extra->vnc_subtlvs; pEncap;
1431 pEncap = pEncap->next)
1432 {
1433 switch (pEncap->type)
1434 {
1435 case BGP_VNC_SUBTLV_TYPE_LIFETIME:
1436 /* use configured lifetime, not attr lifetime */
1437 break;
1438
1439 default:
1440 zlog_warn ("%s: unknown VNC option type %d",
1441 __func__, pEncap->type);
1442
1443
1444 break;
1445 }
1446 }
1447
1448 rfapiGetTunnelType (bi->attr, &tun_type);
1449 if (tun_type == BGP_ENCAP_TYPE_MPLS)
1450 {
1451 struct prefix p;
1452 /* MPLS carries UN address in next hop */
1453 rfapiNexthop2Prefix (bi->attr, &p);
1454 if (p.family != 0)
1455 {
1456 rfapiQprefix2Raddr(&p, &new->un_address);
1457 have_vnc_tunnel_un = 1;
1458 }
1459 }
1460
1461 for (pEncap = bi->attr->extra->encap_subtlvs; pEncap;
1462 pEncap = pEncap->next)
1463 {
1464 switch (pEncap->type)
1465 {
1466 case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT:
1467 /*
1468 * Overrides ENCAP UN address, if any
1469 */
1470 switch (pEncap->length)
1471 {
1472
1473 case 8:
1474 new->un_address.addr_family = AF_INET;
1475 memcpy (&new->un_address.addr.v4, pEncap->value, 4);
1476 have_vnc_tunnel_un = 1;
1477 break;
1478
1479 case 20:
1480 new->un_address.addr_family = AF_INET6;
1481 memcpy (&new->un_address.addr.v6, pEncap->value, 16);
1482 have_vnc_tunnel_un = 1;
1483 break;
1484
1485 default:
1486 zlog_warn
1487 ("%s: invalid tunnel subtlv UN addr length (%d) for bi %p",
1488 __func__, pEncap->length, bi);
1489 }
1490 break;
1491
1492 default:
1493 zlog_warn ("%s: unknown Encap Attribute option type %d",
1494 __func__, pEncap->type);
1495
1496
1497 break;
1498 }
1499 }
1500
1501 new->un_options = rfapi_encap_tlv_to_un_option (bi->attr);
1502
1503#if DEBUG_ENCAP_MONITOR
1504 zlog_debug ("%s: line %d: have_vnc_tunnel_un=%d",
1505 __func__, __LINE__, have_vnc_tunnel_un);
1506#endif
1507
1508 if (!have_vnc_tunnel_un && bi && bi->extra)
1509 {
1510 /*
1511 * use cached UN address from ENCAP route
1512 */
1513 new->un_address.addr_family = bi->extra->vnc.import.un_family;
1514 switch (new->un_address.addr_family)
1515 {
1516 case AF_INET:
1517 new->un_address.addr.v4 = bi->extra->vnc.import.un.addr4;
1518 break;
1519 case AF_INET6:
1520 new->un_address.addr.v6 = bi->extra->vnc.import.un.addr6;
1521 break;
1522 default:
1523 zlog_warn ("%s: invalid UN addr family (%d) for bi %p",
1524 __func__, new->un_address.addr_family, bi);
1525 rfapi_free_next_hop_list (new);
1526 return NULL;
1527 break;
1528 }
1529 }
1530 }
1531 }
1532 new->lifetime = lifetime;
1533 return new;
1534}
1535
1536int
1537rfapiHasNonRemovedRoutes (struct route_node *rn)
1538{
1539 struct bgp_info *bi;
1540
1541 for (bi = rn->info; bi; bi = bi->next)
1542 {
1543 struct prefix pfx;
1544
1545 if (!CHECK_FLAG (bi->flags, BGP_INFO_REMOVED) &&
1546 (bi->extra && !rfapiGetUnAddrOfVpnBi (bi, &pfx)))
1547 {
1548
1549 return 1;
1550 }
1551 }
1552 return 0;
1553}
1554
1555#if DEBUG_IT_NODES
1556/*
1557 * DEBUG FUNCTION
1558 */
1559void
1560rfapiDumpNode (struct route_node *rn)
1561{
1562 struct bgp_info *bi;
1563
1564 zlog_debug ("%s: rn=%p", __func__, rn);
1565 for (bi = rn->info; bi; bi = bi->next)
1566 {
1567 struct prefix pfx;
1568 int ctrc = rfapiGetUnAddrOfVpnBi (bi, &pfx);
1569 int nr;
1570
1571 if (!CHECK_FLAG (bi->flags, BGP_INFO_REMOVED) && (bi->extra && !ctrc))
1572 {
1573
1574 nr = 1;
1575 }
1576 else
1577 {
1578 nr = 0;
1579 }
1580
1581 zlog_debug (" bi=%p, nr=%d, flags=0x%x, extra=%p, ctrc=%d",
1582 bi, nr, bi->flags, bi->extra, ctrc);
1583 }
1584}
1585#endif
1586
1587static int
1588rfapiNhlAddNodeRoutes (
1589 struct route_node *rn, /* in */
1590 struct rfapi_ip_prefix *rprefix, /* in */
1591 uint32_t lifetime, /* in */
1592 int removed, /* in */
1593 struct rfapi_next_hop_entry **head, /* in/out */
1594 struct rfapi_next_hop_entry **tail, /* in/out */
1595 struct rfapi_ip_addr *exclude_vnaddr, /* omit routes to same NVE */
1596 struct route_node *rfd_rib_node,/* preload this NVE rib node */
1597 struct prefix *pfx_target_original) /* query target */
1598{
1599 struct bgp_info *bi;
1600 struct rfapi_next_hop_entry *new;
1601 struct prefix pfx_un;
1602 struct skiplist *seen_nexthops;
1603 int count = 0;
1604 int is_l2 = (rn->p.family == AF_ETHERNET);
1605
1606 if (rfapiRibFTDFilterRecentPrefix(
1607 (struct rfapi_descriptor *)(rfd_rib_node->table->info), rn,
1608 pfx_target_original))
1609 {
1610 return 0;
1611 }
1612
1613 seen_nexthops =
1614 skiplist_new (0, vnc_prefix_cmp, (void (*)(void *)) prefix_free);
1615
1616 for (bi = rn->info; bi; bi = bi->next)
1617 {
1618
1619 struct prefix pfx_vn;
1620 struct prefix *newpfx;
1621
1622 if (removed && !CHECK_FLAG (bi->flags, BGP_INFO_REMOVED))
1623 {
1624#if DEBUG_RETURNED_NHL
1625 zlog_debug ("%s: want holddown, this route not holddown, skip",
1626 __func__);
1627#endif
1628 continue;
1629 }
1630 if (!removed && CHECK_FLAG (bi->flags, BGP_INFO_REMOVED))
1631 {
1632 continue;
1633 }
1634
1635 if (!bi->extra)
1636 {
1637 continue;
1638 }
1639
1640 /*
1641 * Check for excluded VN address
1642 */
1643 if (rfapiVpnBiNhEqualsPt (bi, exclude_vnaddr))
1644 continue;
1645
1646 /*
1647 * Check for VN address (nexthop) copied already
1648 */
1649 if (is_l2)
1650 {
1651 /* L2 routes: semantic nexthop in aux_prefix; VN addr ain't it */
1652 pfx_vn = bi->extra->vnc.import.aux_prefix;
1653 }
1654 else
1655 {
1656 rfapiNexthop2Prefix (bi->attr, &pfx_vn);
1657 }
1658 if (!skiplist_search (seen_nexthops, &pfx_vn, NULL))
1659 {
1660#if DEBUG_RETURNED_NHL
1661 char buf[BUFSIZ];
1662
1663 prefix2str (&pfx_vn, buf, BUFSIZ);
1664 buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */
1665 zlog_debug ("%s: already put VN/nexthop %s, skip", __func__, buf);
1666#endif
1667 continue;
1668 }
1669
1670 if (rfapiGetUnAddrOfVpnBi (bi, &pfx_un))
1671 {
1672#if DEBUG_ENCAP_MONITOR
1673 zlog_debug ("%s: failed to get UN address of this VPN bi",
1674 __func__);
1675#endif
1676 continue;
1677 }
1678
1679 newpfx = prefix_new ();
1680 *newpfx = pfx_vn;
1681 skiplist_insert (seen_nexthops, newpfx, newpfx);
1682
1683 new = rfapiRouteInfo2NextHopEntry(rprefix, bi, lifetime, rn);
1684 if (new)
1685 {
1686 if (rfapiRibPreloadBi(rfd_rib_node, &pfx_vn, &pfx_un, lifetime, bi))
1687 {
1688 /* duplicate filtered by RIB */
1689 rfapi_free_next_hop_list (new);
1690 new = NULL;
1691 }
1692 }
1693
1694 if (new)
1695 {
1696 if (*tail)
1697 {
1698 (*tail)->next = new;
1699 }
1700 else
1701 {
1702 *head = new;
1703 }
1704 *tail = new;
1705 ++count;
1706 }
1707 }
1708
1709 skiplist_free (seen_nexthops);
1710
1711 return count;
1712}
1713
1714
1715/*
1716 * Breadth-first
1717 *
1718 * omit_node is meant for the situation where we are adding a subtree
1719 * of a parent of some original requested node. The response already
1720 * contains the original requested node, and we don't want to duplicate
1721 * its routes in the list, so we skip it if the right or left node
1722 * matches (of course, we still travel down its child subtrees).
1723 */
1724static int
1725rfapiNhlAddSubtree (
1726 struct route_node *rn, /* in */
1727 uint32_t lifetime, /* in */
1728 struct rfapi_next_hop_entry **head, /* in/out */
1729 struct rfapi_next_hop_entry **tail, /* in/out */
1730 struct route_node *omit_node, /* in */
1731 struct rfapi_ip_addr *exclude_vnaddr,/* omit routes to same NVE */
1732 struct route_table *rfd_rib_table,/* preload here */
1733 struct prefix *pfx_target_original) /* query target */
1734{
1735 struct rfapi_ip_prefix rprefix;
1736 int rcount = 0;
1737
1738 if (rn->l_left && rn->l_left != omit_node)
1739 {
1740 if (rn->l_left->info)
1741 {
1742 int count = 0;
1743 struct route_node *rib_rn = NULL;
1744
1745 rfapiQprefix2Rprefix (&rn->l_left->p, &rprefix);
1746 if (rfd_rib_table)
1747 {
1748 rib_rn = route_node_get(rfd_rib_table, &rn->l_left->p);
1749 }
1750
1751 count = rfapiNhlAddNodeRoutes (rn->l_left, &rprefix, lifetime, 0,
1752 head, tail, exclude_vnaddr, rib_rn, pfx_target_original);
1753 if (!count)
1754 {
1755 count = rfapiNhlAddNodeRoutes (rn->l_left, &rprefix, lifetime, 1,
1756 head, tail, exclude_vnaddr, rib_rn, pfx_target_original);
1757 }
1758 rcount += count;
1759 if (rib_rn)
1760 route_unlock_node(rib_rn);
1761 }
1762 }
1763
1764 if (rn->l_right && rn->l_right != omit_node)
1765 {
1766 if (rn->l_right->info)
1767 {
1768 int count = 0;
1769 struct route_node *rib_rn = NULL;
1770
1771 rfapiQprefix2Rprefix (&rn->l_right->p, &rprefix);
1772 if (rfd_rib_table)
1773 {
1774 rib_rn = route_node_get(rfd_rib_table, &rn->l_right->p);
1775 }
1776 count = rfapiNhlAddNodeRoutes (rn->l_right, &rprefix, lifetime, 0,
1777 head, tail, exclude_vnaddr, rib_rn, pfx_target_original);
1778 if (!count)
1779 {
1780 count = rfapiNhlAddNodeRoutes (rn->l_right, &rprefix, lifetime, 1,
1781 head, tail, exclude_vnaddr, rib_rn, pfx_target_original);
1782 }
1783 rcount += count;
1784 if (rib_rn)
1785 route_unlock_node(rib_rn);
1786 }
1787 }
1788
1789 if (rn->l_left)
1790 {
1791 rcount += rfapiNhlAddSubtree (rn->l_left, lifetime, head, tail, omit_node,
1792 exclude_vnaddr, rfd_rib_table, pfx_target_original);
1793 }
1794 if (rn->l_right)
1795 {
1796 rcount += rfapiNhlAddSubtree (rn->l_right, lifetime, head, tail,
1797 omit_node, exclude_vnaddr, rfd_rib_table, pfx_target_original);
1798 }
1799
1800 return rcount;
1801}
1802
1803/*
1804 * Implementation of ROUTE_LIST(node) from RFAPI-Import-Event-Handling.txt
1805 *
1806 * Construct an rfapi nexthop list based on the routes attached to
1807 * the specified node.
1808 *
1809 * If there are any routes that do NOT have BGP_INFO_REMOVED set,
1810 * return those only. If there are ONLY routes with BGP_INFO_REMOVED,
1811 * then return those, and also include all the non-removed routes from the
1812 * next less-specific node (i.e., this node's parent) at the end.
1813 */
1814struct rfapi_next_hop_entry *
1815rfapiRouteNode2NextHopList (
1816 struct route_node *rn,
1817 uint32_t lifetime, /* put into nexthop entries */
1818 struct rfapi_ip_addr *exclude_vnaddr,/* omit routes to same NVE */
1819 struct route_table *rfd_rib_table,/* preload here */
1820 struct prefix *pfx_target_original) /* query target */
1821{
1822 struct rfapi_ip_prefix rprefix;
1823 struct rfapi_next_hop_entry *answer = NULL;
1824 struct rfapi_next_hop_entry *last = NULL;
1825 struct route_node *parent;
1826 int count = 0;
1827 struct route_node *rib_rn;
1828
1829#if DEBUG_RETURNED_NHL
1830 {
1831 char buf[BUFSIZ];
1832
1833 prefix2str (&rn->p, buf, BUFSIZ);
1834 buf[BUFSIZ - 1] = 0;
1835 zlog_debug ("%s: called with node pfx=%s", __func__, buf);
1836 }
1837 rfapiDebugBacktrace ();
1838#endif
1839
1840 rfapiQprefix2Rprefix (&rn->p, &rprefix);
1841
1842 rib_rn = rfd_rib_table? route_node_get(rfd_rib_table, &rn->p): NULL;
1843
1844 /*
1845 * Add non-withdrawn routes at this node
1846 */
1847 count = rfapiNhlAddNodeRoutes (rn, &rprefix, lifetime, 0, &answer, &last,
1848 exclude_vnaddr, rib_rn, pfx_target_original);
1849
1850 /*
1851 * If the list has at least one entry, it's finished
1852 */
1853 if (count)
1854 {
1855 count += rfapiNhlAddSubtree (rn, lifetime, &answer, &last, NULL,
1856 exclude_vnaddr, rfd_rib_table, pfx_target_original);
1857 zlog_debug ("%s: %d nexthops, answer=%p", __func__, count, answer);
1858#if DEBUG_RETURNED_NHL
1859 rfapiPrintNhl (NULL, answer);
1860#endif
1861 if (rib_rn)
1862 route_unlock_node(rib_rn);
1863 return answer;
1864 }
1865
1866 /*
1867 * Add withdrawn routes at this node
1868 */
1869 count = rfapiNhlAddNodeRoutes (rn, &rprefix, lifetime, 1, &answer, &last,
1870 exclude_vnaddr, rib_rn, pfx_target_original);
1871 if (rib_rn)
1872 route_unlock_node(rib_rn);
1873
1874 // rfapiPrintNhl(NULL, answer);
1875
1876 /*
1877 * walk up the tree until we find a node with non-deleted
1878 * routes, then add them
1879 */
1880 for (parent = rn->parent; parent; parent = parent->parent)
1881 {
1882 if (rfapiHasNonRemovedRoutes (parent))
1883 {
1884 break;
1885 }
1886 }
1887
1888 /*
1889 * Add non-withdrawn routes from less-specific prefix
1890 */
1891 if (parent)
1892 {
1893 rib_rn = rfd_rib_table? route_node_get(rfd_rib_table, &parent->p): NULL;
1894 rfapiQprefix2Rprefix (&parent->p, &rprefix);
1895 count += rfapiNhlAddNodeRoutes (parent, &rprefix, lifetime, 0,
1896 &answer, &last, exclude_vnaddr, rib_rn, pfx_target_original);
1897 count += rfapiNhlAddSubtree (parent, lifetime, &answer, &last, rn,
1898 exclude_vnaddr, rfd_rib_table, pfx_target_original);
1899 if (rib_rn)
1900 route_unlock_node(rib_rn);
1901 }
1902 else
1903 {
1904 /*
1905 * There is no parent with non-removed routes. Still need to
1906 * add subtree of original node if it contributed routes to the
1907 * answer.
1908 */
1909 if (count)
1910 count += rfapiNhlAddSubtree (rn, lifetime, &answer, &last, rn,
1911 exclude_vnaddr, rfd_rib_table, pfx_target_original);
1912 }
1913
1914 zlog_debug ("%s: %d nexthops, answer=%p", __func__, count, answer);
1915#if DEBUG_RETURNED_NHL
1916 rfapiPrintNhl (NULL, answer);
1917#endif
1918 return answer;
1919}
1920
1921/*
1922 * Construct nexthop list of all routes in table
1923 */
1924struct rfapi_next_hop_entry *
1925rfapiRouteTable2NextHopList (
1926 struct route_table *rt,
1927 uint32_t lifetime, /* put into nexthop entries */
1928 struct rfapi_ip_addr *exclude_vnaddr,/* omit routes to same NVE */
1929 struct route_table *rfd_rib_table, /* preload this NVE rib table */
1930 struct prefix *pfx_target_original) /* query target */
1931{
1932 struct route_node *rn;
1933 struct rfapi_next_hop_entry *biglist = NULL;
1934 struct rfapi_next_hop_entry *nhl;
1935 struct rfapi_next_hop_entry *tail = NULL;
1936 int count = 0;
1937
1938 for (rn = route_top (rt); rn; rn = route_next (rn))
1939 {
1940
1941 nhl = rfapiRouteNode2NextHopList (rn, lifetime, exclude_vnaddr,
1942 rfd_rib_table, pfx_target_original);
1943 if (!tail)
1944 {
1945 tail = biglist = nhl;
1946 if (tail)
1947 count = 1;
1948 }
1949 else
1950 {
1951 tail->next = nhl;
1952 }
1953 if (tail)
1954 {
1955 while (tail->next)
1956 {
1957 ++count;
1958 tail = tail->next;
1959 }
1960 }
1961 }
1962
1963 zlog_debug ("%s: returning %d routes", __func__, count);
1964 return biglist;
1965}
1966
1967struct rfapi_next_hop_entry *
1968rfapiEthRouteNode2NextHopList (
1969 struct route_node *rn,
1970 struct rfapi_ip_prefix *rprefix,
1971 uint32_t lifetime, /* put into nexthop entries */
1972 struct rfapi_ip_addr *exclude_vnaddr,/* omit routes to same NVE */
1973 struct route_table *rfd_rib_table,/* preload NVE rib table */
1974 struct prefix *pfx_target_original) /* query target */
1975{
1976 int count = 0;
1977 struct rfapi_next_hop_entry *answer = NULL;
1978 struct rfapi_next_hop_entry *last = NULL;
1979 struct route_node *rib_rn;
1980
1981 rib_rn = rfd_rib_table? route_node_get(rfd_rib_table, &rn->p): NULL;
1982
1983 count = rfapiNhlAddNodeRoutes (rn, rprefix, lifetime, 0, &answer, &last,
1984 NULL, rib_rn, pfx_target_original);
1985
1986#if DEBUG_ENCAP_MONITOR
1987 zlog_debug ("%s: node %p: %d non-holddown routes", __func__, rn, count);
1988#endif
1989
1990 if (!count)
1991 {
1992 count = rfapiNhlAddNodeRoutes (rn, rprefix, lifetime, 1, &answer, &last,
1993 exclude_vnaddr, rib_rn, pfx_target_original);
1994 zlog_debug ("%s: node %p: %d holddown routes", __func__, rn, count);
1995 }
1996
1997 if (rib_rn)
1998 route_unlock_node(rib_rn);
1999
2000#if DEBUG_RETURNED_NHL
2001 rfapiPrintNhl (NULL, answer);
2002#endif
2003
2004 return answer;
2005}
2006
2007
2008/*
2009 * Construct nexthop list of all routes in table
2010 */
2011struct rfapi_next_hop_entry *
2012rfapiEthRouteTable2NextHopList (
2013 uint32_t logical_net_id,
2014 struct rfapi_ip_prefix *rprefix,
2015 uint32_t lifetime, /* put into nexthop entries */
2016 struct rfapi_ip_addr *exclude_vnaddr,/* omit routes to same NVE */
2017 struct route_table *rfd_rib_table, /* preload NVE rib node */
2018 struct prefix *pfx_target_original) /* query target */
2019{
2020 struct rfapi_import_table *it;
2021 struct bgp *bgp = bgp_get_default ();
2022 struct route_table *rt;
2023 struct route_node *rn;
2024 struct rfapi_next_hop_entry *biglist = NULL;
2025 struct rfapi_next_hop_entry *nhl;
2026 struct rfapi_next_hop_entry *tail = NULL;
2027 int count = 0;
2028
2029
2030 it = rfapiMacImportTableGet (bgp, logical_net_id);
2031 rt = it->imported_vpn[AFI_ETHER];
2032
2033 for (rn = route_top (rt); rn; rn = route_next (rn))
2034 {
2035
2036 nhl = rfapiEthRouteNode2NextHopList(rn, rprefix, lifetime,
2037 exclude_vnaddr, rfd_rib_table, pfx_target_original);
2038 if (!tail)
2039 {
2040 tail = biglist = nhl;
2041 if (tail)
2042 count = 1;
2043 }
2044 else
2045 {
2046 tail->next = nhl;
2047 }
2048 if (tail)
2049 {
2050 while (tail->next)
2051 {
2052 ++count;
2053 tail = tail->next;
2054 }
2055 }
2056 }
2057
2058 zlog_debug ("%s: returning %d routes", __func__, count);
2059 return biglist;
2060}
2061
2062/*
2063 * Insert a new bi to the imported route table node,
2064 * keeping the list of BIs sorted best route first
2065 */
2066static void
2067rfapiBgpInfoAttachSorted (
2068 struct route_node *rn,
2069 struct bgp_info *info_new,
2070 afi_t afi,
2071 safi_t safi)
2072{
2073 struct bgp *bgp;
2074 struct bgp_info *prev;
2075 struct bgp_info *next;
2076
2077 bgp = bgp_get_default (); /* assume 1 instance for now */
2078
2079 if (VNC_DEBUG(IMPORT_BI_ATTACH))
2080 {
2081 zlog_debug ("%s: info_new->peer=%p", __func__, info_new->peer);
2082 zlog_debug ("%s: info_new->peer->su_remote=%p", __func__,
2083 info_new->peer->su_remote);
2084 }
2085
2086 for (prev = NULL, next = rn->info; next; prev = next, next = next->next)
2087 {
2088 if (!bgp ||
2089 (!CHECK_FLAG (info_new->flags, BGP_INFO_REMOVED) &&
2090 CHECK_FLAG (next->flags, BGP_INFO_REMOVED)) ||
2091 bgp_info_cmp_compatible (bgp, info_new, next, afi, safi) == -1)
2092 { /* -1 if 1st is better */
2093 break;
2094 }
2095 }
2096 zlog_debug ("%s: prev=%p, next=%p", __func__, prev, next);
2097 if (prev)
2098 {
2099 prev->next = info_new;
2100 }
2101 else
2102 {
2103 rn->info = info_new;
2104 }
2105 info_new->prev = prev;
2106 info_new->next = next;
2107 if (next)
2108 next->prev = info_new;
2109}
2110
2111static void
2112rfapiBgpInfoDetach (struct route_node *rn, struct bgp_info *bi)
2113{
2114 /*
2115 * Remove the route (doubly-linked)
2116 */
2117 if (bi->next)
2118 bi->next->prev = bi->prev;
2119 if (bi->prev)
2120 bi->prev->next = bi->next;
2121 else
2122 rn->info = bi->next;
2123}
2124
2125/*
2126 * For L3-indexed import tables
2127 */
2128static int
2129rfapi_bi_peer_rd_cmp (void *b1, void *b2)
2130{
2131 struct bgp_info *bi1 = b1;
2132 struct bgp_info *bi2 = b2;
2133
2134 /*
2135 * Compare peers
2136 */
2137 if (bi1->peer < bi2->peer)
2138 return -1;
2139 if (bi1->peer > bi2->peer)
2140 return 1;
2141
2142 /*
2143 * compare RDs
2144 */
2145 return vnc_prefix_cmp ((struct prefix *) &bi1->extra->vnc.import.rd,
2146 (struct prefix *) &bi2->extra->vnc.import.rd);
2147}
2148
2149/*
2150 * For L2-indexed import tables
2151 * The BIs in these tables should ALWAYS have an aux_prefix set because
2152 * they arrive via IPv4 or IPv6 advertisements.
2153 */
2154static int
2155rfapi_bi_peer_rd_aux_cmp (void *b1, void *b2)
2156{
2157 struct bgp_info *bi1 = b1;
2158 struct bgp_info *bi2 = b2;
2159 int rc;
2160
2161 /*
2162 * Compare peers
2163 */
2164 if (bi1->peer < bi2->peer)
2165 return -1;
2166 if (bi1->peer > bi2->peer)
2167 return 1;
2168
2169 /*
2170 * compare RDs
2171 */
2172 rc = vnc_prefix_cmp ((struct prefix *) &bi1->extra->vnc.import.rd,
2173 (struct prefix *) &bi2->extra->vnc.import.rd);
2174 if (rc)
2175 {
2176 return rc;
2177 }
2178
2179 /*
2180 * L2 import tables can have multiple entries with the
2181 * same MAC address, same RD, but different L3 addresses.
2182 *
2183 * Use presence of aux_prefix with AF=ethernet and prefixlen=1
2184 * as magic value to signify explicit wildcarding of the aux_prefix.
2185 * This magic value will not appear in bona fide bi entries in
2186 * the import table, but is allowed in the "fake" bi used to
2187 * probe the table when searching. (We have to test both b1 and b2
2188 * because there is no guarantee of the order the test key and
2189 * the real key will be passed)
2190 */
2191 if ((bi1->extra->vnc.import.aux_prefix.family == AF_ETHERNET &&
2192 (bi1->extra->vnc.import.aux_prefix.prefixlen == 1)) ||
2193 (bi2->extra->vnc.import.aux_prefix.family == AF_ETHERNET &&
2194 (bi2->extra->vnc.import.aux_prefix.prefixlen == 1)))
2195 {
2196
2197 /*
2198 * wildcard aux address specified
2199 */
2200 return 0;
2201 }
2202
2203 return vnc_prefix_cmp (&bi1->extra->vnc.import.aux_prefix,
2204 &bi2->extra->vnc.import.aux_prefix);
2205}
2206
2207
2208/*
2209 * Index on RD and Peer
2210 */
2211static void
2212rfapiItBiIndexAdd (
2213 struct route_node *rn, /* Import table VPN node */
2214 struct bgp_info *bi) /* new BI */
2215{
2216 struct skiplist *sl;
2217
2218 assert (rn);
2219 assert (bi);
2220 assert (bi->extra);
2221
2222 {
2223 char buf[BUFSIZ];
2224 prefix_rd2str (&bi->extra->vnc.import.rd, buf, BUFSIZ);
2225 zlog_debug ("%s: bi %p, peer %p, rd %s", __func__, bi, bi->peer, buf);
2226 }
2227
2228 sl = RFAPI_RDINDEX_W_ALLOC (rn);
2229 if (!sl)
2230 {
2231 if (AF_ETHERNET == rn->p.family)
2232 {
2233 sl = skiplist_new (0, rfapi_bi_peer_rd_aux_cmp, NULL);
2234 }
2235 else
2236 {
2237 sl = skiplist_new (0, rfapi_bi_peer_rd_cmp, NULL);
2238 }
2239 RFAPI_IT_EXTRA_GET (rn)->u.vpn.idx_rd = sl;
2240 route_lock_node (rn); /* for skiplist */
2241 }
2242 assert (!skiplist_insert (sl, (void *) bi, (void *) bi));
2243 route_lock_node (rn); /* for skiplist entry */
2244
2245 /* NB: BIs in import tables are not refcounted */
2246}
2247
2248static void
2249rfapiItBiIndexDump (struct route_node *rn)
2250{
2251 struct skiplist *sl;
2252 void *cursor = NULL;
2253 struct bgp_info *k;
2254 struct bgp_info *v;
2255 int rc;
2256
2257 sl = RFAPI_RDINDEX (rn);
2258 if (!sl)
2259 return;
2260
2261 for (rc = skiplist_next (sl, (void **) &k, (void **) &v, &cursor);
2262 !rc; rc = skiplist_next (sl, (void **) &k, (void **) &v, &cursor))
2263 {
2264
2265 char buf[BUFSIZ];
2266 char buf_aux_pfx[BUFSIZ];
2267
2268 prefix_rd2str (&k->extra->vnc.import.rd, buf, BUFSIZ);
2269 buf_aux_pfx[0] = 0;
2270 if (k->extra->vnc.import.aux_prefix.family)
2271 {
2272 prefix2str (&k->extra->vnc.import.aux_prefix, buf_aux_pfx, BUFSIZ);
2273 }
2274 else
2275 {
2276 strncpy (buf_aux_pfx, "(none)", BUFSIZ);
2277 buf_aux_pfx[BUFSIZ - 1] = 0;
2278 }
2279
2280 zlog_debug ("bi %p, peer %p, rd %s, aux_prefix %s", k, k->peer, buf,
2281 buf_aux_pfx);
2282 }
2283}
2284
2285static struct bgp_info *
2286rfapiItBiIndexSearch (
2287 struct route_node *rn, /* Import table VPN node */
2288 struct prefix_rd *prd,
2289 struct peer *peer,
2290 struct prefix *aux_prefix) /* optional L3 addr for L2 ITs */
2291{
2292 struct skiplist *sl;
2293 int rc;
2294 struct bgp_info bi_fake;
2295 struct bgp_info_extra bi_extra;
2296 struct bgp_info *bi_result;
2297
2298 sl = RFAPI_RDINDEX (rn);
2299 if (!sl)
2300 return NULL;
2301
2302#if DEBUG_BI_SEARCH
2303 {
2304 char buf[BUFSIZ];
2305 char buf_aux_pfx[BUFSIZ];
2306
2307 prefix_rd2str (prd, buf, BUFSIZ);
2308 if (aux_prefix)
2309 {
2310 prefix2str (aux_prefix, buf_aux_pfx, BUFSIZ);
2311 }
2312 else
2313 {
2314 strncpy (buf_aux_pfx, "(nil)", BUFSIZ - 1);
2315 buf_aux_pfx[BUFSIZ - 1] = 0;
2316 }
2317
2318 zlog_debug ("%s want prd=%s, peer=%p, aux_prefix=%s",
2319 __func__, buf, peer, buf_aux_pfx);
2320 rfapiItBiIndexDump (rn);
2321 }
2322#endif
2323
2324 /* threshold is a WAG */
2325 if (sl->count < 3)
2326 {
2327#if DEBUG_BI_SEARCH
2328 zlog_debug ("%s: short list algorithm", __func__);
2329#endif
2330 /* if short list, linear search might be faster */
2331 for (bi_result = rn->info; bi_result; bi_result = bi_result->next)
2332 {
2333#if DEBUG_BI_SEARCH
2334 {
2335 char buf[BUFSIZ];
2336 prefix_rd2str (&bi_result->extra->vnc.import.rd, buf, BUFSIZ);
2337 zlog_debug ("%s: bi has prd=%s, peer=%p", __func__,
2338 buf, bi_result->peer);
2339 }
2340#endif
2341 if (peer == bi_result->peer &&
2342 !prefix_cmp ((struct prefix *) &bi_result->extra->vnc.import.rd,
2343 (struct prefix *) prd))
2344 {
2345
2346#if DEBUG_BI_SEARCH
2347 zlog_debug ("%s: peer and RD same, doing aux_prefix check",
2348 __func__);
2349#endif
2350 if (!aux_prefix ||
2351 !prefix_cmp (aux_prefix,
2352 &bi_result->extra->vnc.import.aux_prefix))
2353 {
2354
2355#if DEBUG_BI_SEARCH
2356 zlog_debug ("%s: match", __func__);
2357#endif
2358 break;
2359 }
2360
2361 }
2362 }
2363 return bi_result;
2364 }
2365
2366 bi_fake.peer = peer;
2367 bi_fake.extra = &bi_extra;
2368 bi_fake.extra->vnc.import.rd = *(struct prefix_rd *) prd;
2369 if (aux_prefix)
2370 {
2371 bi_fake.extra->vnc.import.aux_prefix = *aux_prefix;
2372 }
2373 else
2374 {
2375 /* wildcard */
2376 bi_fake.extra->vnc.import.aux_prefix.family = AF_ETHERNET;
2377 bi_fake.extra->vnc.import.aux_prefix.prefixlen = 1;
2378 }
2379
2380 rc = skiplist_search (sl, (void *) &bi_fake, (void *) &bi_result);
2381
2382 if (rc)
2383 {
2384#if DEBUG_BI_SEARCH
2385 zlog_debug ("%s: no match", __func__);
2386#endif
2387 return NULL;
2388 }
2389
2390#if DEBUG_BI_SEARCH
2391 zlog_debug ("%s: matched bi=%p", __func__, bi_result);
2392#endif
2393
2394 return bi_result;
2395}
2396
2397static void
2398rfapiItBiIndexDel (
2399 struct route_node *rn, /* Import table VPN node */
2400 struct bgp_info *bi) /* old BI */
2401{
2402 struct skiplist *sl;
2403 int rc;
2404
2405 {
2406 char buf[BUFSIZ];
2407 prefix_rd2str (&bi->extra->vnc.import.rd, buf, BUFSIZ);
2408 zlog_debug ("%s: bi %p, peer %p, rd %s", __func__, bi, bi->peer, buf);
2409 }
2410
2411 sl = RFAPI_RDINDEX (rn);
2412 assert (sl);
2413
2414 rc = skiplist_delete (sl, (void *) (bi), (void *) bi);
2415 if (rc)
2416 {
2417 rfapiItBiIndexDump (rn);
2418 }
2419 assert (!rc);
2420
2421 route_unlock_node (rn); /* for skiplist entry */
2422
2423 /* NB: BIs in import tables are not refcounted */
2424}
2425
2426/*
2427 * Add a backreference at the ENCAP node to the VPN route that
2428 * refers to it
2429 */
2430static void
2431rfapiMonitorEncapAdd (
2432 struct rfapi_import_table *import_table,
2433 struct prefix *p, /* VN address */
2434 struct route_node *vpn_rn, /* VPN node */
2435 struct bgp_info *vpn_bi) /* VPN bi/route */
2436{
2437 afi_t afi = family2afi (p->family);
2438 struct route_node *rn;
2439 struct rfapi_monitor_encap *m;
2440
2441 assert (afi);
2442 rn = route_node_get (import_table->imported_encap[afi], p); /* locks rn */
2443 assert (rn);
2444
2445 m =
2446 XCALLOC (MTYPE_RFAPI_MONITOR_ENCAP, sizeof (struct rfapi_monitor_encap));
2447 assert (m);
2448
2449 m->node = vpn_rn;
2450 m->bi = vpn_bi;
2451 m->rn = rn;
2452
2453 /* insert to encap node's list */
2454 m->next = RFAPI_MONITOR_ENCAP (rn);
2455 if (m->next)
2456 m->next->prev = m;
2457 RFAPI_MONITOR_ENCAP_W_ALLOC (rn) = m;
2458
2459 /* for easy lookup when deleting vpn route */
2460 vpn_bi->extra->vnc.import.hme = m;
2461
2462 zlog_debug
2463 ("%s: it=%p, vpn_bi=%p, afi=%d, encap rn=%p, setting vpn_bi->extra->vnc.import.hme=%p",
2464 __func__, import_table, vpn_bi, afi, rn, m);
2465
2466 RFAPI_CHECK_REFCOUNT (rn, SAFI_ENCAP, 0);
2467}
2468
2469static void
2470rfapiMonitorEncapDelete (struct bgp_info *vpn_bi)
2471{
2472 /*
2473 * Remove encap monitor
2474 */
2475 zlog_debug ("%s: vpn_bi=%p", __func__, vpn_bi);
2476 if (vpn_bi->extra)
2477 {
2478 struct rfapi_monitor_encap *hme = vpn_bi->extra->vnc.import.hme;
2479
2480 if (hme)
2481 {
2482
2483 zlog_debug ("%s: hme=%p", __func__, hme);
2484
2485 /* Refcount checking takes too long here */
2486 //RFAPI_CHECK_REFCOUNT(hme->rn, SAFI_ENCAP, 0);
2487 if (hme->next)
2488 hme->next->prev = hme->prev;
2489 if (hme->prev)
2490 hme->prev->next = hme->next;
2491 else
2492 RFAPI_MONITOR_ENCAP_W_ALLOC (hme->rn) = hme->next;
2493 /* Refcount checking takes too long here */
2494 //RFAPI_CHECK_REFCOUNT(hme->rn, SAFI_ENCAP, 1);
2495
2496 /* see if the struct rfapi_it_extra is empty and can be freed */
2497 rfapiMonitorExtraPrune (SAFI_ENCAP, hme->rn);
2498
2499 route_unlock_node (hme->rn); /* decr ref count */
2500 XFREE (MTYPE_RFAPI_MONITOR_ENCAP, hme);
2501 vpn_bi->extra->vnc.import.hme = NULL;
2502 }
2503 }
2504}
2505
2506/*
2507 * quagga lib/thread.h says this must return int even though
2508 * it doesn't do anything with the return value
2509 */
2510static int
2511rfapiWithdrawTimerVPN (struct thread *t)
2512{
2513 struct rfapi_withdraw *wcb = t->arg;
2514 struct bgp_info *bi = wcb->info;
2515 struct bgp *bgp = bgp_get_default ();
2516
2517 struct rfapi_monitor_vpn *moved;
2518 afi_t afi;
2519
2520 assert (wcb->node);
2521 assert (bi);
2522 assert (wcb->import_table);
2523 assert (bi->extra);
2524
2525 RFAPI_CHECK_REFCOUNT (wcb->node, SAFI_MPLS_VPN, wcb->lockoffset);
2526
2527 {
2528 char buf[BUFSIZ];
2529
2530 zlog_debug ("%s: removing bi %p at prefix %s/%d",
2531 __func__,
2532 bi,
2533 rfapi_ntop (wcb->node->p.family, &wcb->node->p.u.prefix, buf,
2534 BUFSIZ), wcb->node->p.prefixlen);
2535 }
2536
2537 /*
2538 * Remove the route (doubly-linked)
2539 */
2540 if (CHECK_FLAG (bi->flags, BGP_INFO_VALID)
2541 && VALID_INTERIOR_TYPE (bi->type))
2542 RFAPI_MONITOR_EXTERIOR (wcb->node)->valid_interior_count--;
2543
2544 afi = family2afi (wcb->node->p.family);
2545 wcb->import_table->holddown_count[afi] -= 1; /* keep count consistent */
2546 rfapiItBiIndexDel (wcb->node, bi);
2547 rfapiBgpInfoDetach (wcb->node, bi); /* with removed bi */
2548
2549 vnc_import_bgp_exterior_del_route_interior (bgp, wcb->import_table,
2550 wcb->node, bi);
2551
2552
2553 /*
2554 * If VNC is configured to send response remove messages, AND
2555 * if the removed route had a UN address, do response removal
2556 * processing.
2557 */
2558 if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE))
2559 {
2560
2561 int has_valid_duplicate = 0;
2562 struct bgp_info *bii;
2563
2564 /*
2565 * First check if there are any OTHER routes at this node
2566 * that have the same nexthop and a valid UN address. If
2567 * there are (e.g., from other peers), then the route isn't
2568 * really gone, so skip sending a response removal message.
2569 */
2570 for (bii = wcb->node->info; bii; bii = bii->next)
2571 {
2572 if (rfapiVpnBiSamePtUn (bi, bii))
2573 {
2574 has_valid_duplicate = 1;
2575 break;
2576 }
2577 }
2578
2579 zlog_debug ("%s: has_valid_duplicate=%d", __func__,
2580 has_valid_duplicate);
2581
2582 if (!has_valid_duplicate)
2583 {
2584 rfapiRibPendingDeleteRoute (bgp, wcb->import_table, afi, wcb->node);
2585 }
2586 }
2587
2588 rfapiMonitorEncapDelete (bi);
2589
2590 /*
2591 * If there are no VPN monitors at this VPN Node A,
2592 * we are done
2593 */
2594 if (!RFAPI_MONITOR_VPN (wcb->node))
2595 {
2596 zlog_debug ("%s: no VPN monitors at this node", __func__);
2597 goto done;
2598 }
2599
2600 /*
2601 * rfapiMonitorMoveShorter only moves monitors if there are
2602 * no remaining valid routes at the current node
2603 */
2604 moved = rfapiMonitorMoveShorter (wcb->node, 1);
2605
2606 if (moved)
2607 {
2608 rfapiMonitorMovedUp (wcb->import_table, wcb->node, moved->node, moved);
2609 }
2610
2611done:
2612 /*
2613 * Free VPN bi
2614 */
2615 rfapiBgpInfoFree (bi);
2616 wcb->info = NULL;
2617
2618 /*
2619 * If route count at this node has gone to 0, withdraw exported prefix
2620 */
2621 if (!wcb->node->info)
2622 {
2623 /* see if the struct rfapi_it_extra is empty and can be freed */
2624 rfapiMonitorExtraPrune (SAFI_MPLS_VPN, wcb->node);
2625 vnc_direct_bgp_del_prefix (bgp, wcb->import_table, wcb->node);
2626 vnc_zebra_del_prefix (bgp, wcb->import_table, wcb->node);
2627 }
2628 else
2629 {
2630 /*
2631 * nexthop change event
2632 * vnc_direct_bgp_add_prefix() will recompute the VN addr ecommunity
2633 */
2634 vnc_direct_bgp_add_prefix (bgp, wcb->import_table, wcb->node);
2635 }
2636
2637 RFAPI_CHECK_REFCOUNT (wcb->node, SAFI_MPLS_VPN, 1 + wcb->lockoffset);
2638 route_unlock_node (wcb->node); /* decr ref count */
2639 XFREE (MTYPE_RFAPI_WITHDRAW, wcb);
2640 return 0;
2641}
2642
2643/*
2644 * This works for multiprotocol extension, but not for plain ol'
2645 * unicast IPv4 because that nexthop is stored in attr->nexthop
2646 */
2647void
2648rfapiNexthop2Prefix (struct attr *attr, struct prefix *p)
2649{
2650 assert (p);
2651 assert (attr);
2652 assert (attr->extra);
2653
2654 memset (p, 0, sizeof (struct prefix));
2655
2656 switch (p->family = BGP_MP_NEXTHOP_FAMILY (attr->extra->mp_nexthop_len))
2657 {
2658 case AF_INET:
2659 p->u.prefix4 = attr->extra->mp_nexthop_global_in;
2660 p->prefixlen = 32;
2661 break;
2662
2663 case AF_INET6:
2664 p->u.prefix6 = attr->extra->mp_nexthop_global;
2665 p->prefixlen = 128;
2666 break;
2667
2668 default:
2669 zlog_debug ("%s: Family is unknown = %d",
2670 __func__, p->family);
2671 }
2672}
2673
2674void
2675rfapiUnicastNexthop2Prefix (afi_t afi, struct attr *attr, struct prefix *p)
2676{
2677 if (afi == AFI_IP)
2678 {
2679 p->family = AF_INET;
2680 p->prefixlen = 32;
2681 p->u.prefix4 = attr->nexthop;
2682 }
2683 else
2684 {
2685 rfapiNexthop2Prefix (attr, p);
2686 }
2687}
2688
2689static int
2690rfapiAttrNexthopAddrDifferent (struct prefix *p1, struct prefix *p2)
2691{
2692 if (!p1 || !p2)
2693 {
2694 zlog_debug ("%s: p1 or p2 is NULL", __func__);
2695 return 1;
2696 }
2697
2698 /*
2699 * Are address families the same?
2700 */
2701 if (p1->family != p2->family)
2702 {
2703 return 1;
2704 }
2705
2706 switch (p1->family)
2707 {
2708 case AF_INET:
2709 if (IPV4_ADDR_SAME (&p1->u.prefix4, &p2->u.prefix4))
2710 return 0;
2711 break;
2712
2713 case AF_INET6:
2714 if (IPV6_ADDR_SAME (&p1->u.prefix6, &p2->u.prefix6))
2715 return 0;
2716 break;
2717
2718 default:
2719 assert (1);
2720
2721 }
2722
2723 return 1;
2724}
2725
2726static void
2727rfapiCopyUnEncap2VPN (struct bgp_info *encap_bi, struct bgp_info *vpn_bi)
2728{
2729 struct attr_extra *attre;
2730
2731 if (!encap_bi->attr || !encap_bi->attr->extra)
2732 {
2733 zlog_warn ("%s: no encap bi attr/extra, can't copy UN address",
2734 __func__);
2735 return;
2736 }
2737
2738 if (!vpn_bi || !vpn_bi->extra)
2739 {
2740 zlog_warn ("%s: no vpn bi attr/extra, can't copy UN address",
2741 __func__);
2742 return;
2743 }
2744
2745 attre = encap_bi->attr->extra;
2746
2747 switch (BGP_MP_NEXTHOP_FAMILY (attre->mp_nexthop_len))
2748 {
2749 case AF_INET:
2750
2751 /*
2752 * instrumentation to debug segfault of 091127
2753 */
2754 zlog_debug ("%s: vpn_bi=%p", __func__, vpn_bi);
2755 if (vpn_bi)
2756 {
2757 zlog_debug ("%s: vpn_bi->extra=%p", __func__, vpn_bi->extra);
2758 }
2759
2760 vpn_bi->extra->vnc.import.un_family = AF_INET;
2761 vpn_bi->extra->vnc.import.un.addr4 = attre->mp_nexthop_global_in;
2762 break;
2763
2764 case AF_INET6:
2765 vpn_bi->extra->vnc.import.un_family = AF_INET6;
2766 vpn_bi->extra->vnc.import.un.addr6 = attre->mp_nexthop_global;
2767 break;
2768
2769 default:
2770 zlog_warn ("%s: invalid encap nexthop length: %d",
2771 __func__, attre->mp_nexthop_len);
2772 vpn_bi->extra->vnc.import.un_family = 0;
2773 break;
2774 }
2775}
2776
2777/*
2778 * returns 0 on success, nonzero on error
2779 */
2780static int
2781rfapiWithdrawEncapUpdateCachedUn (
2782 struct rfapi_import_table *import_table,
2783 struct bgp_info *encap_bi,
2784 struct route_node *vpn_rn,
2785 struct bgp_info *vpn_bi)
2786{
2787 if (!encap_bi)
2788 {
2789
2790 /*
2791 * clear cached UN address
2792 */
2793 if (!vpn_bi || !vpn_bi->extra)
2794 {
2795 zlog_warn ("%s: missing VPN bi/extra, can't clear UN addr",
2796 __func__);
2797 return 1;
2798 }
2799 vpn_bi->extra->vnc.import.un_family = 0;
2800 memset (&vpn_bi->extra->vnc.import.un, 0,
2801 sizeof (vpn_bi->extra->vnc.import.un));
2802 if (CHECK_FLAG (vpn_bi->flags, BGP_INFO_VALID))
2803 {
2804 if (rfapiGetVncTunnelUnAddr (vpn_bi->attr, NULL))
2805 {
2806 UNSET_FLAG (vpn_bi->flags, BGP_INFO_VALID);
2807 if (VALID_INTERIOR_TYPE (vpn_bi->type))
2808 RFAPI_MONITOR_EXTERIOR (vpn_rn)->valid_interior_count--;
2809 /* signal interior route withdrawal to import-exterior */
2810 vnc_import_bgp_exterior_del_route_interior (bgp_get_default (),
2811 import_table,
2812 vpn_rn, vpn_bi);
2813 }
2814 }
2815
2816 }
2817 else
2818 {
2819 if (!vpn_bi)
2820 {
2821 zlog_warn ("%s: missing VPN bi, can't clear UN addr", __func__);
2822 return 1;
2823 }
2824 rfapiCopyUnEncap2VPN (encap_bi, vpn_bi);
2825 if (!CHECK_FLAG (vpn_bi->flags, BGP_INFO_VALID))
2826 {
2827 SET_FLAG (vpn_bi->flags, BGP_INFO_VALID);
2828 if (VALID_INTERIOR_TYPE (vpn_bi->type))
2829 RFAPI_MONITOR_EXTERIOR (vpn_rn)->valid_interior_count++;
2830 /* signal interior route withdrawal to import-exterior */
2831 vnc_import_bgp_exterior_add_route_interior (bgp_get_default (),
2832 import_table,
2833 vpn_rn, vpn_bi);
2834 }
2835 }
2836 return 0;
2837}
2838
2839static int
2840rfapiWithdrawTimerEncap (struct thread *t)
2841{
2842 struct rfapi_withdraw *wcb = t->arg;
2843 struct bgp_info *bi = wcb->info;
2844 int was_first_route = 0;
2845 struct rfapi_monitor_encap *em;
2846 struct skiplist *vpn_node_sl = skiplist_new (0, NULL, NULL);
2847
2848 assert (wcb->node);
2849 assert (bi);
2850 assert (wcb->import_table);
2851
2852 RFAPI_CHECK_REFCOUNT (wcb->node, SAFI_ENCAP, 0);
2853
2854 if (wcb->node->info == bi)
2855 was_first_route = 1;
2856
2857 /*
2858 * Remove the route/bi and free it
2859 */
2860 rfapiBgpInfoDetach (wcb->node, bi);
2861 rfapiBgpInfoFree (bi);
2862
2863 if (!was_first_route)
2864 goto done;
2865
2866 for (em = RFAPI_MONITOR_ENCAP (wcb->node); em; em = em->next)
2867 {
2868
2869 /*
2870 * Update monitoring VPN BIs with new encap info at the
2871 * head of the encap bi chain (which could be NULL after
2872 * removing the expiring bi above)
2873 */
2874 if (rfapiWithdrawEncapUpdateCachedUn
2875 (wcb->import_table, wcb->node->info, em->node, em->bi))
2876 continue;
2877
2878 /*
2879 * Build a list of unique VPN nodes referenced by these monitors.
2880 * Use a skiplist for speed.
2881 */
2882 skiplist_insert (vpn_node_sl, em->node, em->node);
2883 }
2884
2885
2886 /*
2887 * for each VPN node referenced in the ENCAP monitors:
2888 */
2889 struct route_node *rn;
2890 while (!skiplist_first (vpn_node_sl, (void **) &rn, NULL))
2891 {
2892 if (!wcb->node->info)
2893 {
2894 struct rfapi_monitor_vpn *moved;
2895
2896 moved = rfapiMonitorMoveShorter (rn, 0);
2897 if (moved)
2898 {
2899 //rfapiDoRouteCallback(wcb->import_table, moved->node, moved);
2900 rfapiMonitorMovedUp (wcb->import_table, rn, moved->node, moved);
2901 }
2902 }
2903 else
2904 {
2905 //rfapiDoRouteCallback(wcb->import_table, rn, NULL);
2906 rfapiMonitorItNodeChanged (wcb->import_table, rn, NULL);
2907 }
2908 skiplist_delete_first (vpn_node_sl);
2909 }
2910
2911done:
2912 RFAPI_CHECK_REFCOUNT (wcb->node, SAFI_ENCAP, 1);
2913 route_unlock_node (wcb->node); /* decr ref count */
2914 XFREE (MTYPE_RFAPI_WITHDRAW, wcb);
2915 skiplist_free (vpn_node_sl);
2916 return 0;
2917}
2918
2919
2920/*
2921 * Works for both VPN and ENCAP routes; timer_service_func is different
2922 * in each case
2923 */
2924static void
2925rfapiBiStartWithdrawTimer (
2926 struct rfapi_import_table *import_table,
2927 struct route_node *rn,
2928 struct bgp_info *bi,
2929 afi_t afi,
2930 safi_t safi,
2931 int (*timer_service_func) (struct thread *))
2932{
2933 uint32_t lifetime;
2934 struct rfapi_withdraw *wcb;
2935
2936 if CHECK_FLAG
2937 (bi->flags, BGP_INFO_REMOVED)
2938 {
2939 /*
2940 * Already on the path to being withdrawn,
2941 * should already have a timer set up to
2942 * delete it.
2943 */
2944 zlog_debug ("%s: already being withdrawn, do nothing", __func__);
2945 return;
2946 }
2947
2948 rfapiGetVncLifetime (bi->attr, &lifetime);
2949 zlog_debug ("%s: VNC lifetime is %u", __func__, lifetime);
2950
2951 /*
2952 * withdrawn routes get to hang around for a while
2953 */
2954 SET_FLAG (bi->flags, BGP_INFO_REMOVED);
2955
2956 /* set timer to remove the route later */
2957 lifetime = rfapiGetHolddownFromLifetime (lifetime);
2958 zlog_debug ("%s: using timeout %u", __func__, lifetime);
2959
2960 /*
2961 * Stash import_table, node, and info for use by timer
2962 * service routine, which is supposed to free the wcb.
2963 */
2964 wcb = XCALLOC (MTYPE_RFAPI_WITHDRAW, sizeof (struct rfapi_withdraw));
2965 assert (wcb);
2966 wcb->node = rn;
2967 wcb->info = bi;
2968 wcb->import_table = import_table;
2969
2970 zlog_debug
2971 ("%s: wcb values: node=%p, info=%p, import_table=%p (bi follows)",
2972 __func__, wcb->node, wcb->info, wcb->import_table);
2973 rfapiPrintBi (NULL, bi);
2974
2975
2976 assert (bi->extra);
2977 if (lifetime > UINT32_MAX / 1001)
2978 {
2979 /* sub-optimal case, but will probably never happen */
2980 bi->extra->vnc.import.timer = thread_add_timer (bm->master,
2981 timer_service_func,
2982 wcb, lifetime);
2983 }
2984 else
2985 {
2986 static uint32_t jitter;
2987 uint32_t lifetime_msec;
2988
2989 /*
2990 * the goal here is to spread out the timers so they are
2991 * sortable in the skip list
2992 */
2993 if (++jitter >= 1000)
2994 jitter = 0;
2995
2996 lifetime_msec = (lifetime * 1000) + jitter;
2997
2998 bi->extra->vnc.import.timer = thread_add_background (bm->master,
2999 timer_service_func,
3000 wcb,
3001 lifetime_msec);
3002 }
3003
3004 /* re-sort route list (BGP_INFO_REMOVED routes are last) */
3005 if (((struct bgp_info *) rn->info)->next)
3006 {
3007 rfapiBgpInfoDetach (rn, bi);
3008 rfapiBgpInfoAttachSorted (rn, bi, afi, safi);
3009 }
3010}
3011
3012
3013typedef void (rfapi_bi_filtered_import_f) (struct rfapi_import_table *,
3014 int,
3015 struct peer *,
3016 void *,
3017 struct prefix *,
3018 struct prefix *,
3019 afi_t,
3020 struct prefix_rd *,
3021 struct attr *,
3022 u_char, u_char, uint32_t *);
3023
3024
3025static void
3026rfapiExpireEncapNow (
3027 struct rfapi_import_table *it,
3028 struct route_node *rn,
3029 struct bgp_info *bi)
3030{
3031 struct rfapi_withdraw *wcb;
3032 struct thread t;
3033
3034 /*
3035 * pretend we're an expiring timer
3036 */
3037 wcb = XCALLOC (MTYPE_RFAPI_WITHDRAW, sizeof (struct rfapi_withdraw));
3038 wcb->info = bi;
3039 wcb->node = rn;
3040 wcb->import_table = it;
3041 memset (&t, 0, sizeof (t));
3042 t.arg = wcb;
3043 rfapiWithdrawTimerEncap (&t); /* frees wcb */
3044}
3045
3046static int
3047rfapiGetNexthop (struct attr *attr, struct prefix *prefix)
3048{
3049 switch (BGP_MP_NEXTHOP_FAMILY (attr->extra->mp_nexthop_len))
3050 {
3051 case AF_INET:
3052 prefix->family = AF_INET;
3053 prefix->prefixlen = 32;
3054 prefix->u.prefix4 = attr->extra->mp_nexthop_global_in;
3055 break;
3056 case AF_INET6:
3057 prefix->family = AF_INET6;
3058 prefix->prefixlen = 128;
3059 prefix->u.prefix6 = attr->extra->mp_nexthop_global;
3060 break;
3061 default:
3062 zlog_debug ("%s: unknown attr->extra->mp_nexthop_len %d", __func__,
3063 attr->extra->mp_nexthop_len);
3064 return EINVAL;
3065 }
3066 return 0;
3067}
3068
3069/*
3070 * import a bgp_info if its route target list intersects with the
3071 * import table's route target list
3072 */
3073static void
3074rfapiBgpInfoFilteredImportEncap (
3075 struct rfapi_import_table *import_table,
3076 int action,
3077 struct peer *peer,
3078 void *rfd, /* set for looped back routes */
3079 struct prefix *p,
3080 struct prefix *aux_prefix, /* Unused for encap routes */
3081 afi_t afi,
3082 struct prefix_rd *prd,
3083 struct attr *attr, /* part of bgp_info */
3084 u_char type, /* part of bgp_info */
3085 u_char sub_type, /* part of bgp_info */
3086 uint32_t *label) /* part of bgp_info */
3087{
3088 struct route_table *rt = NULL;
3089 struct route_node *rn;
3090 struct bgp_info *info_new;
3091 struct bgp_info *bi;
3092 struct bgp_info *next;
3093 char buf[BUFSIZ];
3094
3095 struct prefix p_firstbi_old;
3096 struct prefix p_firstbi_new;
3097 int replacing = 0;
3098 const char *action_str = NULL;
3099 struct prefix un_prefix;
3100
3101 struct bgp *bgp;
3102 bgp = bgp_get_default (); /* assume 1 instance for now */
3103
3104 switch (action)
3105 {
3106 case FIF_ACTION_UPDATE:
3107 action_str = "update";
3108 break;
3109 case FIF_ACTION_WITHDRAW:
3110 action_str = "withdraw";
3111 break;
3112 case FIF_ACTION_KILL:
3113 action_str = "kill";
3114 break;
3115 default:
3116 assert (0);
3117 break;
3118 }
3119
3120 zlog_debug ("%s: entry: %s: prefix %s/%d", __func__,
3121 action_str,
3122 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), p->prefixlen);
3123
3124 memset (&p_firstbi_old, 0, sizeof (p_firstbi_old));
3125 memset (&p_firstbi_new, 0, sizeof (p_firstbi_new));
3126
3127 if (action == FIF_ACTION_UPDATE)
3128 {
3129 /*
3130 * Compare rt lists. If no intersection, don't import this route
3131 * On a withdraw, peer and RD are sufficient to determine if
3132 * we should act.
3133 */
3134 if (!attr || !attr->extra || !attr->extra->ecommunity)
3135 {
3136
3137 zlog_debug ("%s: attr, extra, or ecommunity missing, not importing",
3138 __func__);
3139 return;
3140 }
3141#if RFAPI_REQUIRE_ENCAP_BEEC
3142 if (!rfapiEcommunitiesMatchBeec (attr->extra->ecommunity))
3143 {
3144 zlog_debug ("%s: it=%p: no match for BGP Encapsulation ecommunity",
3145 __func__, import_table);
3146 return;
3147 }
3148#endif
3149 if (!rfapiEcommunitiesIntersect (import_table->rt_import_list,
3150 attr->extra->ecommunity))
3151 {
3152
3153 zlog_debug ("%s: it=%p: no ecommunity intersection",
3154 __func__, import_table);
3155 return;
3156 }
3157
3158 /*
3159 * Updates must also have a nexthop address
3160 */
3161 memset (&un_prefix, 0, sizeof (un_prefix)); /* keep valgrind happy */
3162 if (rfapiGetNexthop (attr, &un_prefix))
3163 {
3164 zlog_debug ("%s: missing nexthop address", __func__);
3165 return;
3166 }
3167 }
3168
3169 /*
3170 * Figure out which radix tree the route would go into
3171 */
3172 switch (afi)
3173 {
3174 case AFI_IP:
3175 case AFI_IP6:
3176 rt = import_table->imported_encap[afi];
3177 break;
3178
3179 default:
3180 zlog_err ("%s: bad afi %d", __func__, afi);
3181 return;
3182 }
3183
3184 /*
3185 * route_node_lookup returns a node only if there is at least
3186 * one route attached.
3187 */
3188 rn = route_node_lookup (rt, p);
3189
3190#if DEBUG_ENCAP_MONITOR
3191 zlog_debug ("%s: initial encap lookup (it=%p) rn=%p",
3192 __func__, import_table, rn);
3193#endif
3194
3195 if (rn)
3196 {
3197
3198 RFAPI_CHECK_REFCOUNT (rn, SAFI_ENCAP, 1);
3199 route_unlock_node (rn); /* undo lock in route_node_lookup */
3200
3201
3202 /*
3203 * capture nexthop of first bi
3204 */
3205 if (rn->info)
3206 {
3207 rfapiNexthop2Prefix (((struct bgp_info *) (rn->info))->attr,
3208 &p_firstbi_old);
3209 }
3210
3211 for (bi = rn->info; bi; bi = bi->next)
3212 {
3213
3214 /*
3215 * Does this bgp_info refer to the same route
3216 * as we are trying to add?
3217 */
3218 zlog_debug ("%s: comparing BI %p", __func__, bi);
3219
3220
3221 /*
3222 * Compare RDs
3223 *
3224 * RD of import table bi is in bi->extra->vnc.import.rd
3225 * RD of info_orig is in prd
3226 */
3227 if (!bi->extra)
3228 {
3229 zlog_debug ("%s: no bi->extra", __func__);
3230 continue;
3231 }
3232 if (prefix_cmp ((struct prefix *) &bi->extra->vnc.import.rd,
3233 (struct prefix *) prd))
3234 {
3235
3236 zlog_debug ("%s: prd does not match", __func__);
3237 continue;
3238 }
3239
3240 /*
3241 * Compare peers
3242 */
3243 if (bi->peer != peer)
3244 {
3245 zlog_debug ("%s: peer does not match", __func__);
3246 continue;
3247 }
3248
3249 zlog_debug ("%s: found matching bi", __func__);
3250
3251 /* Same route. Delete this bi, replace with new one */
3252
3253 if (action == FIF_ACTION_WITHDRAW)
3254 {
3255
3256 zlog_debug ("%s: withdrawing at prefix %s/%d",
3257 __func__,
3258 inet_ntop (rn->p.family, &rn->p.u.prefix, buf,
3259 BUFSIZ), rn->p.prefixlen);
3260
3261 rfapiBiStartWithdrawTimer (import_table, rn, bi,
3262 afi, SAFI_ENCAP,
3263 rfapiWithdrawTimerEncap);
3264
3265 }
3266 else
3267 {
3268 zlog_debug ("%s: %s at prefix %s/%d",
3269 __func__,
3270 ((action ==
3271 FIF_ACTION_KILL) ? "killing" : "replacing"),
3272 inet_ntop (rn->p.family, &rn->p.u.prefix, buf,
3273 BUFSIZ), rn->p.prefixlen);
3274
3275 /*
3276 * If this route is waiting to be deleted because of
3277 * a previous withdraw, we must cancel its timer.
3278 */
3279 if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED)
3280 && bi->extra->vnc.import.timer)
3281 {
3282
3283 struct thread *t =
3284 (struct thread *) bi->extra->vnc.import.timer;
3285 struct rfapi_withdraw *wcb = t->arg;
3286
3287 XFREE (MTYPE_RFAPI_WITHDRAW, wcb);
3288 thread_cancel (t);
3289 }
3290
3291 if (action == FIF_ACTION_UPDATE)
3292 {
3293 rfapiBgpInfoDetach (rn, bi);
3294 rfapiBgpInfoFree (bi);
3295 replacing = 1;
3296 }
3297 else
3298 {
3299 /*
3300 * Kill: do export stuff when removing bi
3301 */
3302 struct rfapi_withdraw *wcb;
3303 struct thread t;
3304
3305 /*
3306 * pretend we're an expiring timer
3307 */
3308 wcb =
3309 XCALLOC (MTYPE_RFAPI_WITHDRAW,
3310 sizeof (struct rfapi_withdraw));
3311 wcb->info = bi;
3312 wcb->node = rn;
3313 wcb->import_table = import_table;
3314 memset (&t, 0, sizeof (t));
3315 t.arg = wcb;
3316 rfapiWithdrawTimerEncap (&t); /* frees wcb */
3317 }
3318 }
3319
3320 break;
3321 }
3322 }
3323
3324 if (rn)
3325 RFAPI_CHECK_REFCOUNT (rn, SAFI_ENCAP, replacing ? 1 : 0);
3326
3327 if (action == FIF_ACTION_WITHDRAW || action == FIF_ACTION_KILL)
3328 return;
3329
3330 info_new = rfapiBgpInfoCreate (attr, peer, rfd, prd, type, sub_type, NULL);
3331
3332 if (rn)
3333 {
3334 if (!replacing)
3335 route_lock_node (rn); /* incr ref count for new BI */
3336 }
3337 else
3338 {
3339 rn = route_node_get (rt, p);
3340 }
3341
3342 zlog_debug ("%s: (afi=%d, rn=%p) inserting at prefix %s/%d",
3343 __func__,
3344 afi,
3345 rn,
3346 inet_ntop (rn->p.family, &rn->p.u.prefix, buf, BUFSIZ),
3347 rn->p.prefixlen);
3348
3349 rfapiBgpInfoAttachSorted (rn, info_new, afi, SAFI_ENCAP);
3350
3351 /*
3352 * Delete holddown routes from same NVE. See details in
3353 * rfapiBgpInfoFilteredImportVPN()
3354 */
3355 for (bi = info_new->next; bi; bi = next)
3356 {
3357
3358 struct prefix pfx_un;
3359 int un_match = 0;
3360
3361 next = bi->next;
3362 if (!CHECK_FLAG (bi->flags, BGP_INFO_REMOVED))
3363 continue;
3364
3365 /*
3366 * We already match the VN address (it is the prefix
3367 * of the route node)
3368 */
3369
3370 if (!rfapiGetNexthop (bi->attr, &pfx_un) &&
3371 prefix_same (&pfx_un, &un_prefix))
3372 {
3373
3374 un_match = 1;
3375 }
3376
3377 if (!un_match)
3378 continue;
3379
3380 zlog_debug ("%s: removing holddown bi matching NVE of new route",
3381 __func__);
3382 if (bi->extra->vnc.import.timer)
3383 {
3384 struct thread *t = (struct thread *) bi->extra->vnc.import.timer;
3385 struct rfapi_withdraw *wcb = t->arg;
3386
3387 XFREE (MTYPE_RFAPI_WITHDRAW, wcb);
3388 thread_cancel (t);
3389 }
3390 rfapiExpireEncapNow (import_table, rn, bi);
3391 }
3392
3393 rfapiNexthop2Prefix (((struct bgp_info *) (rn->info))->attr,
3394 &p_firstbi_new);
3395
3396 /*
3397 * If the nexthop address of the selected Encap route (i.e.,
3398 * the UN address) has changed, then we must update the VPN
3399 * routes that refer to this Encap route and possibly force
3400 * rfapi callbacks.
3401 */
3402 if (rfapiAttrNexthopAddrDifferent (&p_firstbi_old, &p_firstbi_new))
3403 {
3404
3405 struct rfapi_monitor_encap *m;
3406 struct rfapi_monitor_encap *mnext;
3407
3408 struct route_node *referenced_vpn_prefix;
3409
3410 /*
3411 * Optimized approach: build radix tree on the fly to
3412 * hold list of VPN nodes referenced by the ENCAP monitors
3413 *
3414 * The nodes in this table correspond to prefixes of VPN routes.
3415 * The "info" pointer of the node points to a chain of
3416 * struct rfapi_monitor_encap, each of which refers to a
3417 * specific VPN node.
3418 */
3419 struct route_table *referenced_vpn_table;
3420
3421 referenced_vpn_table = route_table_init ();
3422 assert (referenced_vpn_table);
3423
3424 /*
3425 * iterate over the set of monitors at this ENCAP node.
3426 */
3427#if DEBUG_ENCAP_MONITOR
3428 zlog_debug ("%s: examining monitors at rn=%p", __func__, rn);
3429#endif
3430 for (m = RFAPI_MONITOR_ENCAP (rn); m; m = m->next)
3431 {
3432
3433 /*
3434 * For each referenced bi/route, copy the ENCAP route's
3435 * nexthop to the VPN route's cached UN address field and set
3436 * the address family of the cached UN address field.
3437 */
3438 rfapiCopyUnEncap2VPN (info_new, m->bi);
3439 if (!CHECK_FLAG (m->bi->flags, BGP_INFO_VALID))
3440 {
3441 SET_FLAG (m->bi->flags, BGP_INFO_VALID);
3442 if (VALID_INTERIOR_TYPE (m->bi->type))
3443 RFAPI_MONITOR_EXTERIOR (m->node)->valid_interior_count++;
3444 vnc_import_bgp_exterior_add_route_interior (bgp,
3445 import_table,
3446 m->node, m->bi);
3447 }
3448
3449 /*
3450 * Build a list of unique VPN nodes referenced by these monitors
3451 *
3452 * There could be more than one VPN node here with a given
3453 * prefix. Those are currently in an unsorted linear list
3454 * per prefix.
3455 */
3456
3457 referenced_vpn_prefix =
3458 route_node_get (referenced_vpn_table, &m->node->p);
3459 assert (referenced_vpn_prefix);
3460 for (mnext = referenced_vpn_prefix->info; mnext;
3461 mnext = mnext->next)
3462 {
3463
3464 if (mnext->node == m->node)
3465 break;
3466 }
3467
3468 if (mnext)
3469 {
3470 /*
3471 * already have an entry for this VPN node
3472 */
3473 route_unlock_node (referenced_vpn_prefix);
3474 }
3475 else
3476 {
3477 mnext = XCALLOC (MTYPE_RFAPI_MONITOR_ENCAP,
3478 sizeof (struct rfapi_monitor_encap));
3479 assert (mnext);
3480 mnext->node = m->node;
3481 mnext->next = referenced_vpn_prefix->info;
3482 referenced_vpn_prefix->info = mnext;
3483 }
3484
3485 }
3486
3487 /*
3488 * for each VPN node referenced in the ENCAP monitors:
3489 */
3490 for (referenced_vpn_prefix = route_top (referenced_vpn_table);
3491 referenced_vpn_prefix;
3492 referenced_vpn_prefix = route_next (referenced_vpn_prefix))
3493 {
3494
3495 while ((m = referenced_vpn_prefix->info))
3496 {
3497
3498 struct route_node *n;
3499
3500 rfapiMonitorMoveLonger (m->node);
3501 for (n = m->node; n; n = n->parent)
3502 {
3503 //rfapiDoRouteCallback(import_table, n, NULL);
3504 }
3505 rfapiMonitorItNodeChanged (import_table, m->node, NULL);
3506
3507 referenced_vpn_prefix->info = m->next;
3508 route_unlock_node (referenced_vpn_prefix);
3509 XFREE (MTYPE_RFAPI_MONITOR_ENCAP, m);
3510 }
3511
3512 }
3513 route_table_finish (referenced_vpn_table);
3514 }
3515
3516 RFAPI_CHECK_REFCOUNT (rn, SAFI_ENCAP, 0);
3517}
3518
3519static void
3520rfapiExpireVpnNow (
3521 struct rfapi_import_table *it,
3522 struct route_node *rn,
3523 struct bgp_info *bi,
3524 int lockoffset)
3525{
3526 struct rfapi_withdraw *wcb;
3527 struct thread t;
3528
3529 /*
3530 * pretend we're an expiring timer
3531 */
3532 wcb = XCALLOC (MTYPE_RFAPI_WITHDRAW, sizeof (struct rfapi_withdraw));
3533 wcb->info = bi;
3534 wcb->node = rn;
3535 wcb->import_table = it;
3536 wcb->lockoffset = lockoffset;
3537 memset (&t, 0, sizeof (t));
3538 t.arg = wcb;
3539 rfapiWithdrawTimerVPN (&t); /* frees wcb */
3540}
3541
3542
3543/*
3544 * import a bgp_info if its route target list intersects with the
3545 * import table's route target list
3546 */
3547void
3548rfapiBgpInfoFilteredImportVPN (
3549 struct rfapi_import_table *import_table,
3550 int action,
3551 struct peer *peer,
3552 void *rfd, /* set for looped back routes */
3553 struct prefix *p,
3554 struct prefix *aux_prefix, /* AFI_ETHER: optional IP */
3555 afi_t afi,
3556 struct prefix_rd *prd,
3557 struct attr *attr, /* part of bgp_info */
3558 u_char type, /* part of bgp_info */
3559 u_char sub_type, /* part of bgp_info */
3560 uint32_t *label) /* part of bgp_info */
3561{
3562 struct route_table *rt = NULL;
3563 struct route_node *rn;
3564 struct route_node *n;
3565 struct bgp_info *info_new;
3566 struct bgp_info *bi;
3567 struct bgp_info *next;
3568 char buf[BUFSIZ];
3569 struct prefix vn_prefix;
3570 struct prefix un_prefix;
3571 int un_prefix_valid = 0;
3572 struct route_node *ern;
3573 int replacing = 0;
3574 int original_had_routes = 0;
3575 struct prefix original_nexthop;
3576 const char *action_str = NULL;
3577 int is_it_ce = 0;
3578
3579 struct bgp *bgp;
3580 bgp = bgp_get_default (); /* assume 1 instance for now */
3581
3582 switch (action)
3583 {
3584 case FIF_ACTION_UPDATE:
3585 action_str = "update";
3586 break;
3587 case FIF_ACTION_WITHDRAW:
3588 action_str = "withdraw";
3589 break;
3590 case FIF_ACTION_KILL:
3591 action_str = "kill";
3592 break;
3593 default:
3594 assert (0);
3595 break;
3596 }
3597
3598 if (import_table == bgp->rfapi->it_ce)
3599 is_it_ce = 1;
3600
3601 zlog_debug ("%s: entry: %s%s: prefix %s/%d: it %p, afi %s", __func__,
3602 (is_it_ce ? "CE-IT " : ""),
3603 action_str,
3604 rfapi_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
3605 p->prefixlen, import_table, afi2str (afi));
3606
3607 VNC_ITRCCK;
3608
3609 /*
3610 * Compare rt lists. If no intersection, don't import this route
3611 * On a withdraw, peer and RD are sufficient to determine if
3612 * we should act.
3613 */
3614 if (action == FIF_ACTION_UPDATE)
3615 {
3616 if (!attr || !attr->extra || !attr->extra->ecommunity)
3617 {
3618
3619 zlog_debug ("%s: attr, extra, or ecommunity missing, not importing",
3620 __func__);
3621 return;
3622 }
3623 if ((import_table != bgp->rfapi->it_ce) &&
3624 !rfapiEcommunitiesIntersect (import_table->rt_import_list,
3625 attr->extra->ecommunity))
3626 {
3627
3628 zlog_debug ("%s: it=%p: no ecommunity intersection",
3629 __func__, import_table);
3630 return;
3631 }
3632
3633 memset (&vn_prefix, 0, sizeof (vn_prefix)); /* keep valgrind happy */
3634 if (rfapiGetNexthop (attr, &vn_prefix))
3635 {
3636 /* missing nexthop address would be a bad, bad thing */
3637 zlog_debug ("%s: missing nexthop", __func__);
3638 return;
3639 }
3640 }
3641
3642 /*
3643 * Figure out which radix tree the route would go into
3644 */
3645 switch (afi)
3646 {
3647 case AFI_IP:
3648 case AFI_IP6:
3649 case AFI_ETHER:
3650 rt = import_table->imported_vpn[afi];
3651 break;
3652
3653 default:
3654 zlog_err ("%s: bad afi %d", __func__, afi);
3655 return;
3656 }
3657
3658 /* clear it */
3659 memset (&original_nexthop, 0, sizeof (original_nexthop));
3660
3661 /*
3662 * route_node_lookup returns a node only if there is at least
3663 * one route attached.
3664 */
3665 rn = route_node_lookup (rt, p);
3666
3667 zlog_debug ("%s: rn=%p", __func__, rn);
3668
3669 if (rn)
3670 {
3671
3672 RFAPI_CHECK_REFCOUNT (rn, SAFI_MPLS_VPN, 1);
3673 route_unlock_node (rn); /* undo lock in route_node_lookup */
3674
3675 if (rn->info)
3676 original_had_routes = 1;
3677
3678 /*
3679 * Look for same route (will have same RD and peer)
3680 */
3681 bi = rfapiItBiIndexSearch (rn, prd, peer, aux_prefix);
3682
3683 if (bi)
3684 {
3685
3686 /*
3687 * This was an old test when we iterated over the
3688 * BIs linearly. Since we're now looking up with
3689 * RD and peer, comparing types should not be
3690 * needed. Changed to assertion.
3691 *
3692 * Compare types. Doing so prevents a RFP-originated
3693 * route from matching an imported route, for example.
3694 */
3695 assert (bi->type == type);
3696
3697 zlog_debug ("%s: found matching bi", __func__);
3698
3699 /*
3700 * In the special CE table, withdrawals occur without holddown
3701 */
3702 if (import_table == bgp->rfapi->it_ce)
3703 {
3704 vnc_direct_bgp_del_route_ce (bgp, rn, bi);
3705 if (action == FIF_ACTION_WITHDRAW)
3706 action = FIF_ACTION_KILL;
3707 }
3708
3709 if (action == FIF_ACTION_WITHDRAW)
3710 {
3711
3712 int washolddown = CHECK_FLAG (bi->flags, BGP_INFO_REMOVED);
3713
3714 zlog_debug ("%s: withdrawing at prefix %s/%d%s",
3715 __func__,
3716 rfapi_ntop (rn->p.family, &rn->p.u.prefix, buf,
3717 BUFSIZ), rn->p.prefixlen,
3718 (washolddown ? " (already being withdrawn)" : ""));
3719
3720 VNC_ITRCCK;
3721 if (!washolddown)
3722 {
3723 rfapiBiStartWithdrawTimer (import_table, rn, bi,
3724 afi, SAFI_MPLS_VPN,
3725 rfapiWithdrawTimerVPN);
3726
3727 RFAPI_UPDATE_ITABLE_COUNT (bi, import_table, afi, -1);
3728 import_table->holddown_count[afi] += 1;
3729 }
3730 VNC_ITRCCK;
3731 }
3732 else
3733 {
3734 int washolddown = 0;
3735
3736 zlog_debug ("%s: %s at prefix %s/%d",
3737 __func__,
3738 ((action ==
3739 FIF_ACTION_KILL) ? "killing" : "replacing"),
3740 rfapi_ntop (rn->p.family, &rn->p.u.prefix, buf,
3741 BUFSIZ), rn->p.prefixlen);
3742
3743 /*
3744 * If this route is waiting to be deleted because of
3745 * a previous withdraw, we must cancel its timer.
3746 */
3747 if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED) &&
3748 bi->extra->vnc.import.timer)
3749 {
3750
3751 struct thread *t =
3752 (struct thread *) bi->extra->vnc.import.timer;
3753 struct rfapi_withdraw *wcb = t->arg;
3754
3755 XFREE (MTYPE_RFAPI_WITHDRAW, wcb);
3756 thread_cancel (t);
3757
3758 import_table->holddown_count[afi] -= 1;
3759 RFAPI_UPDATE_ITABLE_COUNT (bi, import_table, afi, 1);
3760
3761 washolddown = 1;
3762 }
3763 /*
3764 * decrement remote count (if route is remote) because
3765 * we are going to remove it below
3766 */
3767 RFAPI_UPDATE_ITABLE_COUNT (bi, import_table, afi, -1);
3768 if (action == FIF_ACTION_UPDATE)
3769 {
3770 replacing = 1;
3771
3772 /*
3773 * make copy of original nexthop so we can see if it changed
3774 */
3775 rfapiGetNexthop (bi->attr, &original_nexthop);
3776
3777 /*
3778 * remove bi without doing any export processing
3779 */
3780 if (CHECK_FLAG (bi->flags, BGP_INFO_VALID)
3781 && VALID_INTERIOR_TYPE (bi->type))
3782 RFAPI_MONITOR_EXTERIOR (rn)->valid_interior_count--;
3783 rfapiItBiIndexDel (rn, bi);
3784 rfapiBgpInfoDetach (rn, bi);
3785 rfapiMonitorEncapDelete (bi);
3786 vnc_import_bgp_exterior_del_route_interior (bgp,
3787 import_table,
3788 rn, bi);
3789 rfapiBgpInfoFree (bi);
3790 }
3791 else
3792 {
3793 /* Kill */
3794 /*
3795 * remove bi and do export processing
3796 */
3797 import_table->holddown_count[afi] += 1;
3798 rfapiExpireVpnNow (import_table, rn, bi, 0);
3799 }
3800
3801 }
3802 }
3803
3804 }
3805
3806 if (rn)
3807 RFAPI_CHECK_REFCOUNT (rn, SAFI_MPLS_VPN, replacing ? 1 : 0);
3808
3809 if (action == FIF_ACTION_WITHDRAW || action == FIF_ACTION_KILL)
3810 {
3811 VNC_ITRCCK;
3812 return;
3813 }
3814
3815 info_new = rfapiBgpInfoCreate (attr, peer, rfd, prd, type, sub_type, label);
3816
3817 /*
3818 * lookup un address in encap table
3819 */
3820 ern = route_node_match (import_table->imported_encap[afi], &vn_prefix);
3821 if (ern)
3822 {
3823 rfapiCopyUnEncap2VPN (ern->info, info_new);
3824 route_unlock_node (ern); /* undo lock in route_note_match */
3825 }
3826 else
3827 {
3828 char buf[BUFSIZ];
3829 prefix2str (&vn_prefix, buf, sizeof (buf));
3830 buf[BUFSIZ - 1] = 0;
3831 /* Not a big deal, just means VPN route got here first */
3832 zlog_debug ("%s: no encap route for vn addr %s", __func__, buf);
3833 info_new->extra->vnc.import.un_family = 0;
3834 }
3835
3836 if (rn)
3837 {
3838 if (!replacing)
3839 route_lock_node (rn);
3840 }
3841 else
3842 {
3843 /*
3844 * No need to increment reference count, so only "get"
3845 * if the node is not there already
3846 */
3847 rn = route_node_get (rt, p);
3848 }
3849
3850 /*
3851 * For ethernet routes, if there is an accompanying IP address,
3852 * save it in the bi
3853 */
3854 if ((AFI_ETHER == afi) && aux_prefix)
3855 {
3856
3857 zlog_debug ("%s: setting BI's aux_prefix", __func__);
3858 info_new->extra->vnc.import.aux_prefix = *aux_prefix;
3859 }
3860
3861 zlog_debug ("%s: inserting bi %p at prefix %s/%d #%d",
3862 __func__,
3863 info_new,
3864 rfapi_ntop (rn->p.family, &rn->p.u.prefix, buf, BUFSIZ),
3865 rn->p.prefixlen, rn->lock);
3866
3867 rfapiBgpInfoAttachSorted (rn, info_new, afi, SAFI_MPLS_VPN);
3868 rfapiItBiIndexAdd (rn, info_new);
3869 if (!rfapiGetUnAddrOfVpnBi (info_new, NULL))
3870 {
3871 if (VALID_INTERIOR_TYPE (info_new->type))
3872 RFAPI_MONITOR_EXTERIOR (rn)->valid_interior_count++;
3873 SET_FLAG (info_new->flags, BGP_INFO_VALID);
3874 }
3875 RFAPI_UPDATE_ITABLE_COUNT (info_new, import_table, afi, 1);
3876 vnc_import_bgp_exterior_add_route_interior (bgp, import_table, rn,
3877 info_new);
3878
3879 if (import_table == bgp->rfapi->it_ce)
3880 vnc_direct_bgp_add_route_ce (bgp, rn, info_new);
3881
3882 zlog_debug ("%s: showing IT node", __func__);
3883 rfapiShowItNode (NULL, rn); /* debug */
3884
3885 rfapiMonitorEncapAdd (import_table, &vn_prefix, rn, info_new);
3886
3887 if (!rfapiGetUnAddrOfVpnBi (info_new, &un_prefix))
3888 {
3889
3890 /*
3891 * if we have a valid UN address (either via Encap route
3892 * or via tunnel attribute), then we should attempt
3893 * to move any monitors at less-specific nodes to this node
3894 */
3895 rfapiMonitorMoveLonger (rn);
3896
3897 un_prefix_valid = 1;
3898
3899 }
3900
3901 /*
3902 * 101129 Enhancement: if we add a route (implication: it is not
3903 * in holddown), delete all other routes from this nve at this
3904 * node that are in holddown, regardless of peer.
3905 *
3906 * Reasons it's OK to do that:
3907 *
3908 * - if the holddown route being deleted originally came from BGP VPN,
3909 * it is already gone from BGP (implication of holddown), so there
3910 * won't be any added inconsistency with the BGP RIB.
3911 *
3912 * - once a fresh route is added at a prefix, any routes in holddown
3913 * at that prefix will not show up in RFP responses, so deleting
3914 * the holddown routes won't affect the contents of responses.
3915 *
3916 * - lifetimes are supposed to be consistent, so there should not
3917 * be a case where the fresh route has a shorter lifetime than
3918 * the holddown route, so we don't expect the fresh route to
3919 * disappear and complete its holddown time before the existing
3920 * holddown routes time out. Therefore, we won't have a situation
3921 * where we expect the existing holddown routes to be hidden and
3922 * then to reappear sometime later (as holddown routes) in a
3923 * RFP response.
3924 *
3925 * Among other things, this would enable us to skirt the problem
3926 * of local holddown routes that refer to NVE descriptors that
3927 * have already been closed (if the same NVE triggers a subsequent
3928 * rfapi_open(), the new peer is different and doesn't match the
3929 * peer of the holddown route, so the stale holddown route still
3930 * hangs around until it times out instead of just being replaced
3931 * by the fresh route).
3932 */
3933 /*
3934 * We know that the new bi will have been inserted before any routes
3935 * in holddown, so we can skip any that came before it
3936 */
3937 for (bi = info_new->next; bi; bi = next)
3938 {
3939
3940 struct prefix pfx_vn;
3941 struct prefix pfx_un;
3942 int un_match = 0;
3943 int remote_peer_match = 0;
3944
3945 next = bi->next;
3946
3947 /*
3948 * Must be holddown
3949 */
3950 if (!CHECK_FLAG (bi->flags, BGP_INFO_REMOVED))
3951 continue;
3952
3953 /*
3954 * Must match VN address (nexthop of VPN route)
3955 */
3956 if (rfapiGetNexthop (bi->attr, &pfx_vn))
3957 continue;
3958 if (!prefix_same (&pfx_vn, &vn_prefix))
3959 continue;
3960
3961 if (un_prefix_valid && /* new route UN addr */
3962 !rfapiGetUnAddrOfVpnBi (bi, &pfx_un) && /* old route UN addr */
3963 prefix_same (&pfx_un, &un_prefix))
3964 { /* compare */
3965 un_match = 1;
3966 }
3967 if (!RFAPI_LOCAL_BI (bi) && !RFAPI_LOCAL_BI (info_new) &&
3968 sockunion_same (&bi->peer->su, &info_new->peer->su))
3969 {
3970 /* old & new are both remote, same peer */
3971 remote_peer_match = 1;
3972 }
3973
3974 if (!un_match & !remote_peer_match)
3975 continue;
3976
3977 zlog_debug ("%s: removing holddown bi matching NVE of new route",
3978 __func__);
3979 if (bi->extra->vnc.import.timer)
3980 {
3981 struct thread *t = (struct thread *) bi->extra->vnc.import.timer;
3982 struct rfapi_withdraw *wcb = t->arg;
3983
3984 XFREE (MTYPE_RFAPI_WITHDRAW, wcb);
3985 thread_cancel (t);
3986 }
3987 rfapiExpireVpnNow (import_table, rn, bi, 0);
3988 }
3989
3990 if (!original_had_routes)
3991 {
3992 /*
3993 * We went from 0 usable routes to 1 usable route. Perform the
3994 * "Adding a Route" export process.
3995 */
3996 vnc_direct_bgp_add_prefix (bgp, import_table, rn);
3997 vnc_zebra_add_prefix (bgp, import_table, rn);
3998 }
3999 else
4000 {
4001 /*
4002 * Check for nexthop change event
4003 * Note: the prefix_same() test below detects two situations:
4004 * 1. route is replaced, new route has different nexthop
4005 * 2. new route is added (original_nexthop is 0)
4006 */
4007 struct prefix new_nexthop;
4008
4009 rfapiGetNexthop (attr, &new_nexthop);
4010 if (!prefix_same (&original_nexthop, &new_nexthop))
4011 {
4012 /*
4013 * nexthop change event
4014 * vnc_direct_bgp_add_prefix() will recompute VN addr ecommunity
4015 */
4016 vnc_direct_bgp_add_prefix (bgp, import_table, rn);
4017 }
4018 }
4019
4020 if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE))
4021 {
4022 for (n = rn; n; n = n->parent)
4023 {
4024 //rfapiDoRouteCallback(import_table, n, NULL);
4025 }
4026 rfapiMonitorItNodeChanged (import_table, rn, NULL);
4027 }
4028 RFAPI_CHECK_REFCOUNT (rn, SAFI_MPLS_VPN, 0);
4029 VNC_ITRCCK;
4030}
4031
4032static rfapi_bi_filtered_import_f *
4033rfapiBgpInfoFilteredImportFunction (safi_t safi)
4034{
4035 switch (safi)
4036 {
4037 case SAFI_MPLS_VPN:
4038 case BGP_SAFI_VPN:
4039 return rfapiBgpInfoFilteredImportVPN;
4040
4041 case SAFI_ENCAP:
4042 return rfapiBgpInfoFilteredImportEncap;
4043 }
4044 zlog_err ("%s: bad safi %d", __func__, safi);
4045 return NULL;
4046}
4047
4048void
4049rfapiProcessUpdate (
4050 struct peer *peer,
4051 void *rfd, /* set when looped from RFP/RFAPI */
4052 struct prefix *p,
4053 struct prefix_rd *prd,
4054 struct attr *attr,
4055 afi_t afi,
4056 safi_t safi,
4057 u_char type,
4058 u_char sub_type,
4059 uint32_t *label)
4060{
4061 struct bgp *bgp;
4062 struct rfapi *h;
4063 struct rfapi_import_table *it;
4064 int has_ip_route = 1;
4065 uint32_t lni = 0;
4066
4067 bgp = bgp_get_default (); /* assume 1 instance for now */
4068 assert (bgp);
4069
4070 h = bgp->rfapi;
4071 assert (h);
4072
4073 /*
4074 * look at high-order byte of RD. FF means MAC
4075 * address is present (VNC L2VPN)
4076 */
4077 if ((safi == SAFI_MPLS_VPN) &&
4078 (decode_rd_type(prd->val) == RD_TYPE_VNC_ETH))
4079 {
4080 struct prefix pfx_mac_buf;
4081 struct prefix pfx_nexthop_buf;
4082 int rc;
4083
4084 /*
4085 * Set flag if prefix and nexthop are the same - don't
4086 * add the route to normal IP-based import tables
4087 */
4088 if (!rfapiGetNexthop (attr, &pfx_nexthop_buf))
4089 {
4090 if (!prefix_cmp (&pfx_nexthop_buf, p))
4091 {
4092 has_ip_route = 0;
4093 }
4094 }
4095
4096 memset (&pfx_mac_buf, 0, sizeof (pfx_mac_buf));
4097 pfx_mac_buf.family = AF_ETHERNET;
4098 pfx_mac_buf.prefixlen = 48;
4099 memcpy (&pfx_mac_buf.u.prefix_eth.octet, prd->val + 2, 6);
4100
4101 /*
4102 * Find rt containing LNI (Logical Network ID), which
4103 * _should_ always be present when mac address is present
4104 */
4105 rc = rfapiEcommunityGetLNI (attr->extra->ecommunity, &lni);
4106
4107 zlog_debug
4108 ("%s: rfapiEcommunityGetLNI returned %d, lni=%d, attr=%p, attr->extra=%p",
4109 __func__, rc, lni, attr, attr->extra);
4110 if (attr && attr->extra && !rc)
4111 {
4112 it = rfapiMacImportTableGet (bgp, lni);
4113
4114 rfapiBgpInfoFilteredImportVPN (
4115 it,
4116 FIF_ACTION_UPDATE,
4117 peer,
4118 rfd,
4119 &pfx_mac_buf, /* prefix */
4120 p, /* aux prefix: IP addr */
4121 AFI_ETHER,
4122 prd,
4123 attr,
4124 type,
4125 sub_type,
4126 label);
4127 }
4128
4129 }
4130
4131 if (!has_ip_route)
4132 return;
4133
4134 /*
4135 * Iterate over all import tables; do a filtered import
4136 * for the afi/safi combination
4137 */
4138 for (it = h->imports; it; it = it->next)
4139 {
4140 (*rfapiBgpInfoFilteredImportFunction (safi)) (
4141 it,
4142 FIF_ACTION_UPDATE,
4143 peer,
4144 rfd,
4145 p, /* prefix */
4146 NULL,
4147 afi,
4148 prd,
4149 attr,
4150 type,
4151 sub_type,
4152 label);
4153 }
4154
4155 if (safi == SAFI_MPLS_VPN || safi == BGP_SAFI_VPN)
4156 {
4157 vnc_direct_bgp_rh_add_route (bgp, afi, p, peer, attr);
4158 }
4159
4160 if (safi == SAFI_MPLS_VPN)
4161 {
4162 rfapiBgpInfoFilteredImportVPN (
4163 bgp->rfapi->it_ce,
4164 FIF_ACTION_UPDATE,
4165 peer,
4166 rfd,
4167 p, /* prefix */
4168 NULL,
4169 afi,
4170 prd,
4171 attr,
4172 type,
4173 sub_type,
4174 label);
4175 }
4176}
4177
4178
4179void
4180rfapiProcessWithdraw (
4181 struct peer *peer,
4182 void *rfd,
4183 struct prefix *p,
4184 struct prefix_rd *prd,
4185 struct attr *attr,
4186 afi_t afi,
4187 safi_t safi,
4188 u_char type,
4189 int kill)
4190{
4191 struct bgp *bgp;
4192 struct rfapi *h;
4193 struct rfapi_import_table *it;
4194
4195 bgp = bgp_get_default (); /* assume 1 instance for now */
4196 assert (bgp);
4197
4198 h = bgp->rfapi;
4199 assert (h);
4200
4201 /*
4202 * look at high-order byte of RD. FF means MAC
4203 * address is present (VNC L2VPN)
4204 */
4205 if (h->import_mac != NULL && safi == SAFI_MPLS_VPN &&
4206 decode_rd_type(prd->val) == RD_TYPE_VNC_ETH)
4207 {
4208 struct prefix pfx_mac_buf;
4209 void *cursor = NULL;
4210 int rc;
4211
4212 memset (&pfx_mac_buf, 0, sizeof (pfx_mac_buf));
4213 pfx_mac_buf.family = AF_ETHERNET;
4214 pfx_mac_buf.prefixlen = 48;
4215 memcpy (&pfx_mac_buf.u.prefix_eth, prd->val + 2, 6);
4216
4217 /*
4218 * withdraw does not contain attrs, so we don't have
4219 * access to the route's LNI, which would ordinarily
4220 * select the specific mac-based import table. Instead,
4221 * we must iterate over all mac-based tables and rely
4222 * on the RD to match.
4223 *
4224 * If this approach is too slow, add an index where
4225 * key is {RD, peer} and value is the import table
4226 */
4227 for (rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor);
4228 rc == 0;
4229 rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor))
4230 {
4231
4232#if DEBUG_L2_EXTRA
4233 zlog_debug
4234 ("%s: calling rfapiBgpInfoFilteredImportVPN(it=%p, afi=AFI_ETHER)",
4235 __func__, it);
4236#endif
4237
4238 rfapiBgpInfoFilteredImportVPN (
4239 it,
4240 (kill ? FIF_ACTION_KILL : FIF_ACTION_WITHDRAW),
4241 peer,
4242 rfd,
4243 &pfx_mac_buf, /* prefix */
4244 p, /* aux_prefix: IP */
4245 AFI_ETHER,
4246 prd,
4247 attr,
4248 type,
4249 0,
4250 NULL); /* sub_type & label unused for withdraw */
4251 }
4252 }
4253
4254 /*
4255 * XXX For the case where the withdraw involves an L2
4256 * route with no IP information, we rely on the lack
4257 * of RT-list intersection to filter out the withdraw
4258 * from the IP-based import tables below
4259 */
4260
4261 /*
4262 * Iterate over all import tables; do a filtered import
4263 * for the afi/safi combination
4264 */
4265
4266 for (it = h->imports; it; it = it->next)
4267 {
4268 (*rfapiBgpInfoFilteredImportFunction (safi)) (
4269 it,
4270 (kill ? FIF_ACTION_KILL : FIF_ACTION_WITHDRAW),
4271 peer,
4272 rfd,
4273 p, /* prefix */
4274 NULL,
4275 afi,
4276 prd,
4277 attr,
4278 type,
4279 0,
4280 NULL); /* sub_type & label unused for withdraw */
4281 }
4282
4283 /* TBD the deletion should happen after the lifetime expires */
4284 if (safi == SAFI_MPLS_VPN || safi == BGP_SAFI_VPN)
4285 vnc_direct_bgp_rh_del_route (bgp, afi, p, peer);
4286
4287 if (safi == SAFI_MPLS_VPN)
4288 {
4289 rfapiBgpInfoFilteredImportVPN (
4290 bgp->rfapi->it_ce,
4291 (kill ? FIF_ACTION_KILL : FIF_ACTION_WITHDRAW),
4292 peer,
4293 rfd,
4294 p, /* prefix */
4295 NULL,
4296 afi,
4297 prd,
4298 attr,
4299 type,
4300 0,
4301 NULL); /* sub_type & label unused for withdraw */
4302 }
4303}
4304
4305/*
4306 * TBD optimized withdraw timer algorithm for case of many
4307 * routes expiring at the same time due to peer drop.
4308 */
4309/*
4310 * 1. Visit all BIs in all ENCAP import tables.
4311 *
4312 * a. If a bi's peer is the failed peer, remove the bi.
4313 * b. If the removed ENCAP bi was first in the list of
4314 * BIs at this ENCAP node, loop over all monitors
4315 * at this node:
4316 *
4317 * (1) for each ENCAP monitor, loop over all its
4318 * VPN node monitors and set their RFAPI_MON_FLAG_NEEDCALLBACK
4319 * flags.
4320 *
4321 * 2. Visit all BIs in all VPN import tables.
4322 * a. If a bi's peer is the failed peer, remove the bi.
4323 * b. loop over all the VPN node monitors and set their
4324 * RFAPI_MON_FLAG_NEEDCALLBACK flags
4325 * c. If there are no BIs left at this VPN node,
4326 *
4327 */
4328
4329
4330/* surprise, this gets called from peer_delete(), from rfapi_close() */
4331static void
4332rfapiProcessPeerDownRt (
4333 struct peer *peer,
4334 struct rfapi_import_table *import_table,
4335 afi_t afi,
4336 safi_t safi)
4337{
4338 struct route_node *rn;
4339 struct bgp_info *bi;
4340 struct route_table *rt;
4341 int (*timer_service_func) (struct thread *);
4342
4343 assert (afi == AFI_IP || afi == AFI_IP6);
4344
4345 VNC_ITRCCK;
4346
4347 switch (safi)
4348 {
4349 case SAFI_MPLS_VPN:
4350 rt = import_table->imported_vpn[afi];
4351 timer_service_func = rfapiWithdrawTimerVPN;
4352 break;
4353 case SAFI_ENCAP:
4354 rt = import_table->imported_encap[afi];
4355 timer_service_func = rfapiWithdrawTimerEncap;
4356 break;
4357 default:
4358 assert (0);
4359 }
4360
4361
4362 for (rn = route_top (rt); rn; rn = route_next (rn))
4363 {
4364 for (bi = rn->info; bi; bi = bi->next)
4365 {
4366 if (bi->peer == peer)
4367 {
4368
4369 if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED))
4370 {
4371 /* already in holddown, skip */
4372 continue;
4373 }
4374
4375 if (safi == SAFI_MPLS_VPN)
4376 {
4377 RFAPI_UPDATE_ITABLE_COUNT (bi, import_table, afi, -1);
4378 import_table->holddown_count[afi] += 1;
4379 }
4380 rfapiBiStartWithdrawTimer (import_table, rn, bi,
4381 afi, safi,
4382 timer_service_func);
4383 }
4384 }
4385 }
4386 VNC_ITRCCK;
4387}
4388
4389/*
4390 * This gets called when a peer connection drops. We have to remove
4391 * all the routes from this peer.
4392 *
4393 * Current approach is crude. TBD Optimize by setting fewer timers and
4394 * grouping withdrawn routes so we can generate callbacks more
4395 * efficiently.
4396 */
4397void
4398rfapiProcessPeerDown (struct peer *peer)
4399{
4400 struct bgp *bgp;
4401 struct rfapi *h;
4402 struct rfapi_import_table *it;
4403
4404 /*
4405 * If this peer is a "dummy" peer structure atached to a RFAPI
4406 * nve_descriptor, we don't need to walk the import tables
4407 * because the routes are already withdrawn by rfapi_close()
4408 */
4409 if (CHECK_FLAG (peer->flags, PEER_FLAG_IS_RFAPI_HD))
4410 return;
4411
4412 /*
4413 * 1. Visit all BIs in all ENCAP import tables.
4414 * Start withdraw timer on the BIs that match peer.
4415 *
4416 * 2. Visit All BIs in all VPN import tables.
4417 * Start withdraw timer on the BIs that match peer.
4418 */
4419
4420 bgp = bgp_get_default (); /* assume 1 instance for now */
4421 assert (bgp);
4422
4423 h = bgp->rfapi;
4424 assert (h);
4425
4426 for (it = h->imports; it; it = it->next)
4427 {
4428 rfapiProcessPeerDownRt (peer, it, AFI_IP, SAFI_ENCAP);
4429 rfapiProcessPeerDownRt (peer, it, AFI_IP6, SAFI_ENCAP);
4430 rfapiProcessPeerDownRt (peer, it, AFI_IP, SAFI_MPLS_VPN);
4431 rfapiProcessPeerDownRt (peer, it, AFI_IP6, SAFI_MPLS_VPN);
4432 }
4433
4434 if (h->it_ce)
4435 {
4436 rfapiProcessPeerDownRt (peer, h->it_ce, AFI_IP, SAFI_MPLS_VPN);
4437 rfapiProcessPeerDownRt (peer, h->it_ce, AFI_IP6, SAFI_MPLS_VPN);
4438 }
4439}
4440
4441/*
4442 * Import an entire RIB (for an afi/safi) to an import table RIB,
4443 * filtered according to the import table's RT list
4444 *
4445 * TBD: does this function need additions to match rfapiProcessUpdate()
4446 * for, e.g., L2 handling?
4447 */
4448static void
4449rfapiBgpTableFilteredImport (
4450 struct bgp *bgp,
4451 struct rfapi_import_table *it,
4452 afi_t afi,
4453 safi_t safi)
4454{
4455 struct bgp_node *rn1;
4456 struct bgp_node *rn2;
4457
4458 /* Only these SAFIs have 2-level RIBS */
4459 assert (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP);
4460
4461 /*
4462 * Now visit all the rd nodes and the nodes of all the
4463 * route tables attached to them, and import the routes
4464 * if they have matching route targets
4465 */
4466 for (rn1 = bgp_table_top (bgp->rib[afi][safi]);
4467 rn1; rn1 = bgp_route_next (rn1))
4468 {
4469
4470 if (rn1->info)
4471 {
4472 for (rn2 = bgp_table_top (rn1->info);
4473 rn2; rn2 = bgp_route_next (rn2))
4474 {
4475
4476 struct bgp_info *bi;
4477
4478 for (bi = rn2->info; bi; bi = bi->next)
4479 {
4480 u_int32_t label = 0;
4481
4482 if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED))
4483 continue;
4484
4485 if (bi->extra)
4486 label = decode_label (bi->extra->tag);
4487 (*rfapiBgpInfoFilteredImportFunction (safi)) (
4488 it, /* which import table */
4489 FIF_ACTION_UPDATE,
4490 bi->peer,
4491 NULL,
4492 &rn2->p, /* prefix */
4493 NULL,
4494 afi,
4495 (struct prefix_rd *) &rn1->p,
4496 bi->attr,
4497 bi->type,
4498 bi->sub_type,
4499 &label);
4500 }
4501 }
4502 }
4503 }
4504}
4505
4506
4507/* per-bgp-instance rfapi data */
4508struct rfapi *
4509bgp_rfapi_new (struct bgp *bgp)
4510{
4511 struct rfapi *h;
4512 int afi;
4513 struct rfapi_rfp_cfg *cfg = NULL;
4514 struct rfapi_rfp_cb_methods *cbm = NULL;
4515
4516 assert (bgp->rfapi_cfg == NULL);
4517
4518 h = (struct rfapi *) XCALLOC (MTYPE_RFAPI, sizeof (struct rfapi));
4519
4520 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4521 {
4522 /* ugly, to deal with addition of delegates, part of 0.99.24.1 merge */
4523 h->un[afi].delegate = route_table_get_default_delegate ();
4524 }
4525
4526 /*
4527 * initialize the ce import table
4528 */
4529 h->it_ce =
4530 XCALLOC (MTYPE_RFAPI_IMPORTTABLE, sizeof (struct rfapi_import_table));
4531 h->it_ce->imported_vpn[AFI_IP] = route_table_init ();
4532 h->it_ce->imported_vpn[AFI_IP6] = route_table_init ();
4533 h->it_ce->imported_encap[AFI_IP] = route_table_init ();
4534 h->it_ce->imported_encap[AFI_IP6] = route_table_init ();
4535 rfapiBgpTableFilteredImport (bgp, h->it_ce, AFI_IP, SAFI_MPLS_VPN);
4536 rfapiBgpTableFilteredImport (bgp, h->it_ce, AFI_IP6, SAFI_MPLS_VPN);
4537
4538 /*
4539 * Set up work queue for deferred rfapi_close operations
4540 */
4541 h->deferred_close_q = work_queue_new (bm->master, "rfapi deferred close");
4542 h->deferred_close_q->spec.workfunc = rfapi_deferred_close_workfunc;
4543 h->deferred_close_q->spec.data = h;
4544
4545 h->rfp = rfp_start (bm->master, &cfg, &cbm);
4546 bgp->rfapi_cfg = bgp_rfapi_cfg_new (cfg);
4547 if (cbm != NULL)
4548 {
4549 h->rfp_methods = *cbm;
4550 }
4551 return h;
4552}
4553
4554void
4555bgp_rfapi_destroy (struct bgp *bgp, struct rfapi *h)
4556{
4557 if (bgp == NULL || h == NULL)
4558 return;
4559
4560 if (h->resolve_nve_nexthop)
4561 {
4562 skiplist_free (h->resolve_nve_nexthop);
4563 h->resolve_nve_nexthop = NULL;
4564 }
4565
4566 route_table_finish (h->it_ce->imported_vpn[AFI_IP]);
4567 route_table_finish (h->it_ce->imported_vpn[AFI_IP6]);
4568 route_table_finish (h->it_ce->imported_encap[AFI_IP]);
4569 route_table_finish (h->it_ce->imported_encap[AFI_IP6]);
4570
4571 if (h->import_mac)
4572 {
4573 struct rfapi_import_table *it;
4574 void *cursor;
4575 int rc;
4576
4577 for (cursor = NULL,
4578 rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor);
4579 !rc;
4580 rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor))
4581 {
4582
4583 rfapiImportTableFlush (it);
4584 XFREE (MTYPE_RFAPI_IMPORTTABLE, it);
4585 }
4586 skiplist_free (h->import_mac);
4587 h->import_mac = NULL;
4588 }
4589
4590 work_queue_free (h->deferred_close_q);
4591
4592 if (h->rfp != NULL)
4593 rfp_stop (h->rfp);
4594 XFREE (MTYPE_RFAPI_IMPORTTABLE, h->it_ce);
4595 XFREE (MTYPE_RFAPI, h);
4596}
4597
4598struct rfapi_import_table *
4599rfapiImportTableRefAdd (struct bgp *bgp, struct ecommunity *rt_import_list)
4600{
4601 struct rfapi *h;
4602 struct rfapi_import_table *it;
4603 afi_t afi;
4604
4605 h = bgp->rfapi;
4606 assert (h);
4607
4608 for (it = h->imports; it; it = it->next)
4609 {
4610 if (ecommunity_cmp (it->rt_import_list, rt_import_list))
4611 break;
4612 }
4613
4614 zlog_debug ("%s: matched it=%p", __func__, it);
4615
4616 if (!it)
4617 {
4618 it =
4619 XCALLOC (MTYPE_RFAPI_IMPORTTABLE, sizeof (struct rfapi_import_table));
4620 assert (it);
4621 it->next = h->imports;
4622 h->imports = it;
4623
4624 it->rt_import_list = ecommunity_dup (rt_import_list);
4625 it->monitor_exterior_orphans =
4626 skiplist_new (0, NULL, (void (*)(void *)) prefix_free);
4627
4628 /*
4629 * fill import route tables from RIBs
4630 *
4631 * Potential area for optimization. If this occurs when
4632 * tables are large (e.g., the operator adds a nve group
4633 * with a new RT list to a running system), it could take
4634 * a while.
4635 *
4636 */
4637 for (afi = AFI_IP; afi < AFI_MAX; ++afi)
4638 {
4639
4640 it->imported_vpn[afi] = route_table_init ();
4641 it->imported_encap[afi] = route_table_init ();
4642
4643 rfapiBgpTableFilteredImport (bgp, it, afi, SAFI_MPLS_VPN);
4644 rfapiBgpTableFilteredImport (bgp, it, afi, SAFI_ENCAP);
4645
4646 vnc_import_bgp_exterior_redist_enable_it (bgp, afi, it);
4647 }
4648 }
4649
4650 it->refcount += 1;
4651
4652 return it;
4653}
4654
4655/*
4656 * skiplist element free function
4657 */
4658static void
4659delete_rem_pfx_na_free (void *na)
4660{
4661 uint32_t *pCounter = ((struct rfapi_nve_addr *) na)->info;
4662
4663 *pCounter += 1;
4664 XFREE (MTYPE_RFAPI_NVE_ADDR, na);
4665}
4666
4667/*
4668 * Common deleter for IP and MAC import tables
4669 */
4670static void
4671rfapiDeleteRemotePrefixesIt (
4672 struct bgp *bgp,
4673 struct rfapi_import_table *it,
4674 struct prefix *un,
4675 struct prefix *vn,
4676 struct prefix *p,
4677 int delete_active,
4678 int delete_holddown,
4679 uint32_t *pARcount,
4680 uint32_t *pAHcount,
4681 uint32_t *pHRcount,
4682 uint32_t *pHHcount,
4683 struct skiplist *uniq_active_nves,
4684 struct skiplist *uniq_holddown_nves)
4685{
4686 afi_t afi;
4687
4688#if DEBUG_L2_EXTRA
4689 {
4690 char buf_pfx[BUFSIZ];
4691
4692 if (p)
4693 {
4694 prefix2str (p, buf_pfx, BUFSIZ);
4695 }
4696 else
4697 {
4698 buf_pfx[0] = '*';
4699 buf_pfx[1] = 0;
4700 }
4701
4702 zlog_debug ("%s: entry, p=%s, delete_active=%d, delete_holddown=%d",
4703 __func__, buf_pfx, delete_active, delete_holddown);
4704 }
4705#endif
4706
4707 for (afi = AFI_IP; afi < AFI_MAX; ++afi)
4708 {
4709
4710 struct route_table *rt;
4711 struct route_node *rn;
4712
4713 if (p && (family2afi (p->family) != afi))
4714 {
4715 continue;
4716 }
4717
4718 rt = it->imported_vpn[afi];
4719 if (!rt)
4720 continue;
4721
4722 zlog_debug ("%s: scanning rt for afi=%d", __func__, afi);
4723
4724 for (rn = route_top (rt); rn; rn = route_next (rn))
4725 {
4726 struct bgp_info *bi;
4727 struct bgp_info *next;
4728
4729 if (VNC_DEBUG(IMPORT_DEL_REMOTE))
4730 {
4731 char p1line[BUFSIZ];
4732 char p2line[BUFSIZ];
4733
4734 prefix2str (p, p1line, BUFSIZ);
4735 prefix2str (&rn->p, p2line, BUFSIZ);
4736 zlog_debug ("%s: want %s, have %s", __func__, p1line, p2line);
4737 }
4738
4739 if (p && prefix_cmp (p, &rn->p))
4740 continue;
4741
4742 {
4743 char buf_pfx[BUFSIZ];
4744 prefix2str (&rn->p, buf_pfx, BUFSIZ);
4745 zlog_debug ("%s: rn pfx=%s", __func__, buf_pfx);
4746 }
4747
4748 /* TBD is this valid for afi == AFI_ETHER? */
4749 RFAPI_CHECK_REFCOUNT (rn, SAFI_MPLS_VPN, 1);
4750
4751 for (bi = rn->info; bi; bi = next)
4752 {
4753 next = bi->next;
4754
4755 struct prefix qpt;
4756 struct prefix qct;
4757 int qpt_valid = 0;
4758 int qct_valid = 0;
4759 int is_active = 0;
4760
4761 zlog_debug ("%s: examining bi %p", __func__, bi);
4762
4763 if (bi->attr)
4764 {
4765 if (!rfapiGetNexthop (bi->attr, &qpt))
4766 qpt_valid = 1;
4767 }
4768 if (vn)
4769 {
4770 if (!qpt_valid || !prefix_match (vn, &qpt))
4771 {
4772#if DEBUG_L2_EXTRA
4773 zlog_debug
4774 ("%s: continue at vn && !qpt_valid || !prefix_match(vn, &qpt)",
4775 __func__);
4776#endif
4777 continue;
4778 }
4779 }
4780
4781 if (!rfapiGetUnAddrOfVpnBi (bi, &qct))
4782 qct_valid = 1;
4783
4784 if (un)
4785 {
4786 if (!qct_valid || !prefix_match (un, &qct))
4787 {
4788#if DEBUG_L2_EXTRA
4789 zlog_debug
4790 ("%s: continue at un && !qct_valid || !prefix_match(un, &qct)",
4791 __func__);
4792#endif
4793 continue;
4794 }
4795 }
4796
4797
4798 /*
4799 * Blow bi away
4800 */
4801 /*
4802 * If this route is waiting to be deleted because of
4803 * a previous withdraw, we must cancel its timer.
4804 */
4805 if (CHECK_FLAG (bi->flags, BGP_INFO_REMOVED))
4806 {
4807 if (!delete_holddown)
4808 continue;
4809 if (bi->extra->vnc.import.timer)
4810 {
4811
4812 struct thread *t =
4813 (struct thread *) bi->extra->vnc.import.timer;
4814 struct rfapi_withdraw *wcb = t->arg;
4815
4816 wcb->import_table->holddown_count[afi] -= 1;
4817 RFAPI_UPDATE_ITABLE_COUNT (bi, wcb->import_table, afi,
4818 1);
4819 XFREE (MTYPE_RFAPI_WITHDRAW, wcb);
4820 thread_cancel (t);
4821 }
4822 }
4823 else
4824 {
4825 if (!delete_active)
4826 continue;
4827 is_active = 1;
4828 }
4829
4830 zlog_debug
4831 ("%s: deleting bi %p (qct_valid=%d, qpt_valid=%d, delete_holddown=%d, delete_active=%d)",
4832 __func__, bi, qct_valid, qpt_valid, delete_holddown,
4833 delete_active);
4834
4835
4836 /*
4837 * add nve to list
4838 */
4839 if (qct_valid && qpt_valid)
4840 {
4841
4842 struct rfapi_nve_addr na;
4843 struct rfapi_nve_addr *nap;
4844
4845 memset (&na, 0, sizeof (na));
4846 assert (!rfapiQprefix2Raddr (&qct, &na.un));
4847 assert (!rfapiQprefix2Raddr (&qpt, &na.vn));
4848
4849 if (skiplist_search ((is_active ? uniq_active_nves :
4850 uniq_holddown_nves), &na,
4851 (void **) &nap))
4852 {
4853 char line[BUFSIZ];
4854
4855 nap = XCALLOC (MTYPE_RFAPI_NVE_ADDR,
4856 sizeof (struct rfapi_nve_addr));
4857 assert (nap);
4858 *nap = na;
4859 nap->info = is_active ? pAHcount : pHHcount;
4860 skiplist_insert ((is_active ? uniq_active_nves :
4861 uniq_holddown_nves), nap, nap);
4862
4863 rfapiNveAddr2Str (nap, line, BUFSIZ);
4864 }
4865 }
4866
4867 vnc_direct_bgp_rh_del_route (bgp, afi, &rn->p, bi->peer);
4868
4869 RFAPI_UPDATE_ITABLE_COUNT (bi, it, afi, -1);
4870 it->holddown_count[afi] += 1;
4871 rfapiExpireVpnNow (it, rn, bi, 1);
4872
4873 zlog_debug ("%s: incrementing count (is_active=%d)",
4874 __func__, is_active);
4875
4876 if (is_active)
4877 ++ * pARcount;
4878 else
4879 ++ * pHRcount;
4880 }
4881 }
4882 }
4883}
4884
4885
4886/*
4887 * For use by the "clear vnc prefixes" command
4888 */
4889/*------------------------------------------
4890 * rfapiDeleteRemotePrefixes
4891 *
4892 * UI helper: For use by the "clear vnc prefixes" command
4893 *
4894 * input:
4895 * un if set, tunnel must match this prefix
4896 * vn if set, nexthop prefix must match this prefix
4897 * p if set, prefix must match this prefix
4898 *
4899 * output
4900 * pARcount number of active routes deleted
4901 * pAHcount number of active nves deleted
4902 * pHRcount number of holddown routes deleted
4903 * pHHcount number of holddown nves deleted
4904 *
4905 * return value:
4906 * void
4907 --------------------------------------------*/
4908void
4909rfapiDeleteRemotePrefixes (
4910 struct prefix *un,
4911 struct prefix *vn,
4912 struct prefix *p,
4913 int delete_active,
4914 int delete_holddown,
4915 uint32_t *pARcount,
4916 uint32_t *pAHcount,
4917 uint32_t *pHRcount,
4918 uint32_t *pHHcount)
4919{
4920 struct bgp *bgp;
4921 struct rfapi *h;
4922 struct rfapi_import_table *it;
4923 uint32_t deleted_holddown_route_count = 0;
4924 uint32_t deleted_active_route_count = 0;
4925 uint32_t deleted_holddown_nve_count = 0;
4926 uint32_t deleted_active_nve_count = 0;
4927 struct skiplist *uniq_holddown_nves;
4928 struct skiplist *uniq_active_nves;
4929
4930 VNC_ITRCCK;
4931
4932 bgp = bgp_get_default (); /* assume 1 instance for now */
4933 /* If no bgp instantiated yet, no vnc prefixes exist */
4934 if (!bgp)
4935 return;
4936
4937 h = bgp->rfapi;
4938 assert (h);
4939
4940 uniq_holddown_nves =
4941 skiplist_new (0, rfapi_nve_addr_cmp, delete_rem_pfx_na_free);
4942 uniq_active_nves =
4943 skiplist_new (0, rfapi_nve_addr_cmp, delete_rem_pfx_na_free);
4944
4945 /*
4946 * Iterate over all import tables; do a filtered import
4947 * for the afi/safi combination
4948 */
4949
4950 for (it = h->imports; it; it = it->next)
4951 {
4952
4953 zlog_debug
4954 ("%s: calling rfapiDeleteRemotePrefixesIt() on (IP) import %p",
4955 __func__, it);
4956
4957 rfapiDeleteRemotePrefixesIt (
4958 bgp,
4959 it,
4960 un,
4961 vn,
4962 p,
4963 delete_active,
4964 delete_holddown,
4965 &deleted_active_route_count,
4966 &deleted_active_nve_count,
4967 &deleted_holddown_route_count,
4968 &deleted_holddown_nve_count,
4969 uniq_active_nves,
4970 uniq_holddown_nves);
4971 }
4972
4973 /*
4974 * Now iterate over L2 import tables
4975 */
4976 if (h->import_mac && !(p && (p->family != AF_ETHERNET)))
4977 {
4978
4979 void *cursor = NULL;
4980 int rc;
4981
4982 for (cursor = NULL,
4983 rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor);
4984 !rc;
4985 rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor))
4986 {
4987
4988 zlog_debug
4989 ("%s: calling rfapiDeleteRemotePrefixesIt() on import_mac %p",
4990 __func__, it);
4991
4992 rfapiDeleteRemotePrefixesIt (
4993 bgp,
4994 it,
4995 un,
4996 vn,
4997 p,
4998 delete_active,
4999 delete_holddown,
5000 &deleted_active_route_count,
5001 &deleted_active_nve_count,
5002 &deleted_holddown_route_count,
5003 &deleted_holddown_nve_count,
5004 uniq_active_nves,
5005 uniq_holddown_nves);
5006 }
5007 }
5008
5009 /*
5010 * our custom element freeing function above counts as it deletes
5011 */
5012 skiplist_free (uniq_holddown_nves);
5013 skiplist_free (uniq_active_nves);
5014
5015 if (pARcount)
5016 *pARcount = deleted_active_route_count;
5017 if (pAHcount)
5018 *pAHcount = deleted_active_nve_count;
5019 if (pHRcount)
5020 *pHRcount = deleted_holddown_route_count;
5021 if (pHHcount)
5022 *pHHcount = deleted_holddown_nve_count;
5023
5024 VNC_ITRCCK;
5025}
5026
5027/*------------------------------------------
5028 * rfapiCountRemoteRoutes
5029 *
5030 * UI helper: count VRF routes from BGP side
5031 *
5032 * input:
5033 *
5034 * output
5035 * pALRcount count of active local routes
5036 * pARRcount count of active remote routes
5037 * pHRcount count of holddown routes
5038 * pIRcount count of direct imported routes
5039 *
5040 * return value:
5041 * void
5042 --------------------------------------------*/
5043void
5044rfapiCountAllItRoutes (int *pALRcount, /* active local routes */
5045 int *pARRcount, /* active remote routes */
5046 int *pHRcount, /* holddown routes */
5047 int *pIRcount) /* imported routes */
5048{
5049 struct bgp *bgp;
5050 struct rfapi *h;
5051 struct rfapi_import_table *it;
5052 afi_t afi;
5053
5054 int total_active_local = 0;
5055 int total_active_remote = 0;
5056 int total_holddown = 0;
5057 int total_imported = 0;
5058
5059 bgp = bgp_get_default (); /* assume 1 instance for now */
5060 assert (bgp);
5061
5062 h = bgp->rfapi;
5063 assert (h);
5064
5065 /*
5066 * Iterate over all import tables; do a filtered import
5067 * for the afi/safi combination
5068 */
5069
5070 for (it = h->imports; it; it = it->next)
5071 {
5072
5073 for (afi = AFI_IP; afi < AFI_MAX; ++afi)
5074 {
5075
5076 total_active_local += it->local_count[afi];
5077 total_active_remote += it->remote_count[afi];
5078 total_holddown += it->holddown_count[afi];
5079 total_imported += it->imported_count[afi];
5080
5081 }
5082 }
5083
5084 void *cursor;
5085 int rc;
5086
5087 if (h->import_mac)
5088 {
5089 for (cursor = NULL,
5090 rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor);
5091 !rc;
5092 rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor))
5093 {
5094
5095 total_active_local += it->local_count[AFI_ETHER];
5096 total_active_remote += it->remote_count[AFI_ETHER];
5097 total_holddown += it->holddown_count[AFI_ETHER];
5098 total_imported += it->imported_count[AFI_ETHER];
5099
5100 }
5101 }
5102
5103
5104 if (pALRcount)
5105 {
5106 *pALRcount = total_active_local;
5107 }
5108 if (pARRcount)
5109 {
5110 *pARRcount = total_active_remote;
5111 }
5112 if (pHRcount)
5113 {
5114 *pHRcount = total_holddown;
5115 }
5116 if (pIRcount)
5117 {
5118 *pIRcount = total_imported;
5119 }
5120}
5121
5122/*------------------------------------------
5123 * rfapiGetHolddownFromLifetime
5124 *
5125 * calculate holddown value based on lifetime
5126 *
5127 * input:
5128 * lifetime lifetime
5129 *
5130 * return value:
5131 * Holddown value based on lifetime, holddown_factor,
5132 * and RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY
5133 *
5134 --------------------------------------------*/
5135/* hold down time maxes out at RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY */
5136uint32_t
5137rfapiGetHolddownFromLifetime (uint32_t lifetime)
5138{
5139 uint32_t factor;
5140 struct bgp *bgp;
5141
5142 bgp = bgp_get_default ();
5143 if (bgp && bgp->rfapi_cfg)
5144 factor = bgp->rfapi_cfg->rfp_cfg.holddown_factor;
5145 else
5146 factor = RFAPI_RFP_CFG_DEFAULT_HOLDDOWN_FACTOR;
5147
5148 if (factor < 100 || lifetime < RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY)
5149 lifetime = lifetime * factor / 100;
5150 if (lifetime < RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY)
5151 return lifetime;
5152 else
5153 return RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY;
5154}