]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/rfapi/rfapi_monitor.c
*: always set SO_SNDBUF and SO_RCVBUF using a best effort approach
[mirror_frr.git] / bgpd / rfapi / rfapi_monitor.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_monitor.c
24 */
25
26/* TBD remove unneeded includes */
27
28#include <errno.h>
29
f8b6f499
LB
30#include "lib/zebra.h"
31#include "lib/prefix.h"
32#include "lib/table.h"
33#include "lib/vty.h"
34#include "lib/memory.h"
35#include "lib/log.h"
36#include "lib/table.h"
37#include "lib/skiplist.h"
38
39#include "bgpd/bgpd.h"
40
41#include "bgpd/rfapi/bgp_rfapi_cfg.h"
42#include "bgpd/rfapi/rfapi.h"
43#include "bgpd/rfapi/rfapi_backend.h"
44
45#include "bgpd/rfapi/rfapi.h"
46#include "bgpd/rfapi/rfapi_import.h"
47#include "bgpd/rfapi/vnc_import_bgp.h"
48#include "bgpd/rfapi/rfapi_private.h"
49#include "bgpd/rfapi/rfapi_monitor.h"
50#include "bgpd/rfapi/rfapi_vty.h"
51#include "bgpd/rfapi/rfapi_rib.h"
65efcfce
LB
52
53#define DEBUG_L2_EXTRA 0
54#define DEBUG_DUP_CHECK 0
55#define DEBUG_ETH_SL 0
56
57static void
58rfapiMonitorTimerRestart (struct rfapi_monitor_vpn *m);
59
60static void
61rfapiMonitorEthTimerRestart (struct rfapi_monitor_eth *m);
62
63/*
64 * Forward declarations
65 */
66static void
67rfapiMonitorEthDetachImport (struct bgp *bgp, struct rfapi_monitor_eth *mon);
68
69#if DEBUG_ETH_SL
70/*
71 * Debug function, special case
72 */
73void
74rfapiMonitorEthSlCheck(
75 struct route_node *rn,
76 const char *tag1,
77 const char *tag2)
78{
79 struct route_node *rn_saved = NULL;
80 static struct skiplist *sl_saved = NULL;
81 struct skiplist *sl;
82
83 if (!rn)
84 return;
85
86 if (rn_saved && (rn != rn_saved))
87 return;
88
89 if (!rn_saved)
90 rn_saved = rn;
91
92 sl = RFAPI_MONITOR_ETH(rn);
93 if (sl || sl_saved)
94 {
95 zlog_debug("%s[%s%s]: rn=%p, rn->lock=%d, old sl=%p, new sl=%p",
96 __func__, (tag1? tag1: ""), (tag2? tag2: ""), rn, rn->lock,
97 sl_saved, sl);
98 sl_saved = sl;
99 }
100}
101#endif
102
103/*
104 * Debugging function that aborts when it finds monitors whose
105 * "next" pointer * references themselves
106 */
107void
108rfapiMonitorLoopCheck (struct rfapi_monitor_vpn *mchain)
109{
110 struct rfapi_monitor_vpn *m;
111
112 for (m = mchain; m; m = m->next)
113 assert (m != m->next);
114}
115
116#if DEBUG_DUP_CHECK
117/*
118 * Debugging code: see if a monitor is mentioned more than once
119 * in a HD's monitor list
120 */
121void
122rfapiMonitorDupCheck (struct bgp *bgp)
123{
124 struct listnode *hnode;
125 struct rfapi_descriptor *rfd;
126
127 for (ALL_LIST_ELEMENTS_RO (&bgp->rfapi->descriptors, hnode, rfd))
128 {
129 struct route_node *mrn;
130
131 if (!rfd->mon)
132 continue;
133
134 for (mrn = route_top (rfd->mon); mrn; mrn = route_next (mrn))
135 {
136 struct rfapi_monitor_vpn *m;
137 for (m = (struct rfapi_monitor_vpn *) (mrn->info); m; m = m->next)
138 m->dcount = 0;
139 }
140 }
141
142 for (ALL_LIST_ELEMENTS_RO (&bgp->rfapi->descriptors, hnode, rfd))
143 {
144 struct route_node *mrn;
145
146 if (!rfd->mon)
147 continue;
148
149 for (mrn = route_top (rfd->mon); mrn; mrn = route_next (mrn))
150 {
151 struct rfapi_monitor_vpn *m;
152
153 for (m = (struct rfapi_monitor_vpn *) (mrn->info); m; m = m->next)
154 assert (++m->dcount == 1);
155 }
156 }
157}
158#endif
159
160/* debug */
161void
162rfapiMonitorCleanCheck (struct bgp *bgp)
163{
164 struct listnode *hnode;
165 struct rfapi_descriptor *rfd;
166
167 for (ALL_LIST_ELEMENTS_RO (&bgp->rfapi->descriptors, hnode, rfd))
168 {
169 assert (!rfd->import_table->vpn0_queries[AFI_IP]);
170 assert (!rfd->import_table->vpn0_queries[AFI_IP6]);
171
172 struct route_node *rn;
173
174 for (rn = route_top (rfd->import_table->imported_vpn[AFI_IP]); rn;
175 rn = route_next (rn))
176 {
177
178 assert (!RFAPI_MONITOR_VPN (rn));
179 }
180 for (rn = route_top (rfd->import_table->imported_vpn[AFI_IP6]); rn;
181 rn = route_next (rn))
182 {
183
184 assert (!RFAPI_MONITOR_VPN (rn));
185 }
186 }
187}
188
189/* debug */
190void
191rfapiMonitorCheckAttachAllowed (void)
192{
193 struct bgp *bgp = bgp_get_default ();
194 assert (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE));
195}
196
197void
198rfapiMonitorExtraFlush (safi_t safi, struct route_node *rn)
199{
200 struct rfapi_it_extra *hie;
201 struct rfapi_monitor_vpn *v;
202 struct rfapi_monitor_vpn *v_next;
203 struct rfapi_monitor_encap *e = NULL;
204 struct rfapi_monitor_encap *e_next = NULL;
205
206 if (!rn)
207 return;
208
209 if (!rn->aggregate)
210 return;
211
212 hie = (struct rfapi_it_extra *) (rn->aggregate);
213
214 switch (safi)
215 {
216 case SAFI_ENCAP:
217 for (e = hie->u.encap.e; e; e = e_next)
218 {
219 e_next = e->next;
220 e->next = NULL;
221 XFREE (MTYPE_RFAPI_MONITOR_ENCAP, e);
222 route_unlock_node (rn);
223 }
224 hie->u.encap.e = NULL;
225 break;
226
227 case SAFI_MPLS_VPN:
228 for (v = hie->u.vpn.v; v; v = v_next)
229 {
230 v_next = v->next;
231 v->next = NULL;
232 XFREE (MTYPE_RFAPI_MONITOR, e);
233 route_unlock_node (rn);
234 }
235 hie->u.vpn.v = NULL;
236 if (hie->u.vpn.e.source)
237 {
238 while (!skiplist_delete_first (hie->u.vpn.e.source))
239 {
240 route_unlock_node (rn);
241 }
242 skiplist_free (hie->u.vpn.e.source);
243 hie->u.vpn.e.source = NULL;
244 route_unlock_node (rn);
245 }
246 if (hie->u.vpn.idx_rd)
247 {
248 /* looping through bi->extra->vnc.import.rd is tbd */
249 while (!skiplist_delete_first (hie->u.vpn.idx_rd))
250 {
251 route_unlock_node (rn);
252 }
253 skiplist_free (hie->u.vpn.idx_rd);
254 hie->u.vpn.idx_rd = NULL;
255 route_unlock_node (rn);
256 }
257 if (hie->u.vpn.mon_eth)
258 {
259 while (!skiplist_delete_first (hie->u.vpn.mon_eth))
260 {
261 route_unlock_node (rn);
262 }
263 skiplist_free (hie->u.vpn.mon_eth);
264 hie->u.vpn.mon_eth = NULL;
265 route_unlock_node (rn);
266 }
267 break;
268
269 default:
270 assert (0);
271 }
272 XFREE (MTYPE_RFAPI_IT_EXTRA, hie);
273 rn->aggregate = NULL;
274 route_unlock_node (rn);
275}
276
277/*
278 * If the child lists are empty, release the rfapi_it_extra struct
279 */
280void
281rfapiMonitorExtraPrune (safi_t safi, struct route_node *rn)
282{
283 struct rfapi_it_extra *hie;
284
285 if (!rn)
286 return;
287
288 if (!rn->aggregate)
289 return;
290
291 hie = (struct rfapi_it_extra *) (rn->aggregate);
292
293 switch (safi)
294 {
295 case SAFI_ENCAP:
296 if (hie->u.encap.e)
297 return;
298 break;
299
300 case SAFI_MPLS_VPN:
301 if (hie->u.vpn.v)
302 return;
303 if (hie->u.vpn.mon_eth)
304 {
305 if (skiplist_count (hie->u.vpn.mon_eth))
306 return;
307 skiplist_free (hie->u.vpn.mon_eth);
308 hie->u.vpn.mon_eth = NULL;
309 route_unlock_node (rn); /* uncount skiplist */
310 }
311 if (hie->u.vpn.e.source)
312 {
313 if (skiplist_count (hie->u.vpn.e.source))
314 return;
315 skiplist_free (hie->u.vpn.e.source);
316 hie->u.vpn.e.source = NULL;
317 route_unlock_node (rn);
318 }
319 if (hie->u.vpn.idx_rd)
320 {
321 if (skiplist_count (hie->u.vpn.idx_rd))
322 return;
323 skiplist_free (hie->u.vpn.idx_rd);
324 hie->u.vpn.idx_rd = NULL;
325 route_unlock_node (rn);
326 }
327 if (hie->u.vpn.mon_eth)
328 {
329 if (skiplist_count (hie->u.vpn.mon_eth))
330 return;
331 skiplist_free (hie->u.vpn.mon_eth);
332 hie->u.vpn.mon_eth = NULL;
333 route_unlock_node (rn);
334 }
335 break;
336
337 default:
338 assert (0);
339 }
340 XFREE (MTYPE_RFAPI_IT_EXTRA, hie);
341 rn->aggregate = NULL;
342 route_unlock_node (rn);
343}
344
345/*
346 * returns locked node
347 */
348struct route_node *
349rfapiMonitorGetAttachNode (struct rfapi_descriptor *rfd, struct prefix *p)
350{
351 afi_t afi;
352 struct route_node *rn;
353
354 if (RFAPI_0_PREFIX (p))
355 {
356 assert (1);
357 }
358
359 afi = family2afi (p->family);
360 assert (afi);
361
362 /*
363 * It's possible that even though there is a route at this node,
364 * there are no routes with valid UN addresses (i.e,. with no
365 * valid tunnel routes). Check for that and walk back up the
366 * tree if necessary.
367 *
368 * When the outer loop completes, the matched node, if any, is
369 * locked (i.e., its reference count has been incremented) to
370 * account for the VPN monitor we are about to attach.
371 *
372 * if a monitor is moved to another node, there must be
373 * corresponding unlock/locks
374 */
375 for (rn = route_node_match (rfd->import_table->imported_vpn[afi], p); rn;)
376 {
377
378 struct bgp_info *bi;
379 struct prefix pfx_dummy;
380
381 /* TBD update this code to use new valid_interior_count */
382 for (bi = rn->info; bi; bi = bi->next)
383 {
384 /*
385 * If there is a cached ENCAP UN address, it's a usable
386 * VPN route
387 */
388 if (bi->extra && bi->extra->vnc.import.un_family)
389 {
390 break;
391 }
392
393 /*
394 * Or if there is a valid Encap Attribute tunnel subtlv address,
395 * it's a usable VPN route.
396 */
397 if (!rfapiGetVncTunnelUnAddr (bi->attr, &pfx_dummy))
398 {
399 break;
400 }
401 }
402 if (bi)
403 break;
404
405 route_unlock_node (rn);
406 if ((rn = rn->parent))
407 {
408 route_lock_node (rn);
409 }
410 }
411
412 if (!rn)
413 {
414 struct prefix pfx_default;
415
416 memset (&pfx_default, 0, sizeof (pfx_default));
417 pfx_default.family = p->family;
418
419 /* creates default node if none exists, and increments ref count */
420 rn =
421 route_node_get (rfd->import_table->imported_vpn[afi], &pfx_default);
422 }
423
424 return rn;
425}
426
427/*
428 * If this function happens to attach the monitor to a radix tree
429 * node (as opposed to the 0-prefix list), the node pointer is
430 * returned (for the benefit of caller which might like to use it
431 * to generate an immediate query response).
432 */
433static struct route_node *
434rfapiMonitorAttachImport (struct rfapi_descriptor *rfd,
435 struct rfapi_monitor_vpn *m)
436{
437 struct route_node *rn;
438
439 rfapiMonitorCheckAttachAllowed ();
440
441 if (RFAPI_0_PREFIX (&m->p))
442 {
443 /*
444 * Add new monitor entry to vpn0 list
445 */
446 afi_t afi;
447
448 afi = family2afi (m->p.family);
449 assert (afi);
450
451 m->next = rfd->import_table->vpn0_queries[afi];
452 rfd->import_table->vpn0_queries[afi] = m;
453 zlog_debug ("%s: attached monitor %p to vpn0 list", __func__, m);
454 return NULL;
455 }
456
457 /*
458 * Attach new monitor entry to import table node
459 */
460 rn = rfapiMonitorGetAttachNode (rfd, &m->p); /* returns locked rn */
461 m->node = rn;
462 m->next = RFAPI_MONITOR_VPN (rn);
463 RFAPI_MONITOR_VPN_W_ALLOC (rn) = m;
464 RFAPI_CHECK_REFCOUNT (rn, SAFI_MPLS_VPN, 0);
465 zlog_debug ("%s: attached monitor %p to rn %p", __func__, m, rn);
466 return rn;
467}
468
469
470/*
471 * reattach monitors for this HD to import table
472 */
473void
474rfapiMonitorAttachImportHd (struct rfapi_descriptor *rfd)
475{
476 struct route_node *mrn;
477
478 if (!rfd->mon)
479 {
480 /*
481 * No monitors for this HD
482 */
483 return;
484 }
485
486 for (mrn = route_top (rfd->mon); mrn; mrn = route_next (mrn))
487 {
488
489 if (!mrn->info)
490 continue;
491
492 (void) rfapiMonitorAttachImport (rfd,
493 (struct rfapi_monitor_vpn
494 *) (mrn->info));
495 }
496}
497
498/*
499 * Adds a monitor for a query to the NVE descriptor's list
500 * and, if callbacks are enabled, attaches it to the import table.
501 *
502 * If we happened to locate the import table radix tree attachment
503 * point, return it so the caller can use it to generate a query
504 * response without repeating the lookup. Note that when callbacks
505 * are disabled, this function will not perform a lookup, and the
506 * caller will have to do its own lookup.
507 */
508struct route_node *
509rfapiMonitorAdd (
510 struct bgp *bgp,
511 struct rfapi_descriptor *rfd,
512 struct prefix *p)
513{
514 struct rfapi_monitor_vpn *m;
515 struct route_node *rn;
516
517 /*
518 * Initialize nve's monitor list if needed
519 * NB use the same radix tree for IPv4 and IPv6 targets.
520 * The prefix will always have full-length mask (/32, /128)
521 * or be 0/0 so they won't get mixed up.
522 */
523 if (!rfd->mon)
524 {
525 rfd->mon = route_table_init ();
526 }
527 rn = route_node_get (rfd->mon, p);
528 if (rn->info)
529 {
530 /*
531 * received this query before, no further action needed
532 */
533 rfapiMonitorTimerRestart ((struct rfapi_monitor_vpn *) rn->info);
534 route_unlock_node (rn);
535 return NULL;
536 }
537
538 /*
539 * New query for this nve, record it in the HD
540 */
541 rn->info = XCALLOC (MTYPE_RFAPI_MONITOR, sizeof (struct rfapi_monitor_vpn));
542 m = (struct rfapi_monitor_vpn *) (rn->info);
543 m->rfd = rfd;
544 prefix_copy (&m->p, p);
545
546 ++rfd->monitor_count;
547 ++bgp->rfapi->monitor_count;
548
549 rfapiMonitorTimerRestart (m);
550
551 if (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)
552 {
553 /*
554 * callbacks turned off, so don't attach monitor to import table
555 */
556 return NULL;
557 }
558
559
560 /*
561 * attach to import table
562 */
563 return rfapiMonitorAttachImport (rfd, m);
564}
565
566/*
567 * returns monitor pointer if found, NULL if not
568 */
569static struct rfapi_monitor_vpn *
570rfapiMonitorDetachImport (struct rfapi_monitor_vpn *m)
571{
572 struct rfapi_monitor_vpn *prev;
573 struct rfapi_monitor_vpn *this = NULL;
574
575 if (RFAPI_0_PREFIX (&m->p))
576 {
577 afi_t afi;
578
579 /*
580 * 0-prefix monitors are stored in a special list and not
581 * in the import VPN tree
582 */
583
584 afi = family2afi (m->p.family);
585 assert (afi);
586
587 if (m->rfd->import_table)
588 {
589 for (prev = NULL, this = m->rfd->import_table->vpn0_queries[afi];
590 this; prev = this, this = this->next)
591 {
592
593 if (this == m)
594 break;
595 }
596 if (this)
597 {
598 if (!prev)
599 {
600 m->rfd->import_table->vpn0_queries[afi] = this->next;
601 }
602 else
603 {
604 prev->next = this->next;
605 }
606 }
607 }
608 }
609 else
610 {
611
612 if (m->node)
613 {
614 for (prev = NULL,
615 this = RFAPI_MONITOR_VPN (m->node);
616 this; prev = this, this = this->next)
617 {
618
619 if (this == m)
620 break;
621 }
622 if (this)
623 {
624 if (prev)
625 {
626 prev->next = this->next;
627 }
628 else
629 {
630 RFAPI_MONITOR_VPN_W_ALLOC (m->node) = this->next;
631 }
632 RFAPI_CHECK_REFCOUNT (m->node, SAFI_MPLS_VPN, 1);
633 route_unlock_node (m->node);
634 }
635 m->node = NULL;
636 }
637 }
638 return this;
639}
640
641
642void
643rfapiMonitorDetachImportHd (struct rfapi_descriptor *rfd)
644{
645 struct route_node *rn;
646
647 if (!rfd->mon)
648 return;
649
650 for (rn = route_top (rfd->mon); rn; rn = route_next (rn))
651 {
652 if (rn->info)
653 {
654 rfapiMonitorDetachImport ((struct rfapi_monitor_vpn *) (rn->info));
655 }
656 }
657}
658
659void
660rfapiMonitorDel (
661 struct bgp *bgp,
662 struct rfapi_descriptor *rfd,
663 struct prefix *p)
664{
665 struct route_node *rn;
666 struct rfapi_monitor_vpn *m;
667
668 assert (rfd->mon);
669 rn = route_node_get (rfd->mon, p); /* locks node */
670 m = rn->info;
671
672 assert (m);
673
674 /*
675 * remove from import table
676 */
677 if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE))
678 {
679 rfapiMonitorDetachImport (m);
680 }
681
682 if (m->timer)
683 {
684 thread_cancel (m->timer);
685 m->timer = NULL;
686 }
687
688 /*
689 * remove from rfd list
690 */
691 XFREE (MTYPE_RFAPI_MONITOR, m);
692 rn->info = NULL;
693 route_unlock_node (rn); /* undo original lock when created */
694 route_unlock_node (rn); /* undo lock in route_node_get */
695
696 --rfd->monitor_count;
697 --bgp->rfapi->monitor_count;
698}
699
700/*
701 * returns count of monitors deleted
702 */
703int
704rfapiMonitorDelHd (struct rfapi_descriptor *rfd)
705{
706 struct route_node *rn;
707 struct bgp *bgp;
708 int count = 0;
709
710 zlog_debug ("%s: entry rfd=%p", __func__, rfd);
711
712 bgp = bgp_get_default ();
713
714 if (rfd->mon)
715 {
716 for (rn = route_top (rfd->mon); rn; rn = route_next (rn))
717 {
718 struct rfapi_monitor_vpn *m;
719 if ((m = rn->info))
720 {
721 if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE))
722 {
723 rfapiMonitorDetachImport (m);
724 }
725
726 if (m->timer)
727 {
728 thread_cancel (m->timer);
729 m->timer = NULL;
730 }
731
732 XFREE (MTYPE_RFAPI_MONITOR, m);
733 rn->info = NULL;
734 route_unlock_node (rn); /* undo original lock when created */
735 ++count;
736 --rfd->monitor_count;
737 --bgp->rfapi->monitor_count;
738 }
739 }
740 route_table_finish (rfd->mon);
741 rfd->mon = NULL;
742 }
743
744 if (rfd->mon_eth)
745 {
746
747 struct rfapi_monitor_eth *mon_eth;
748
749 while (!skiplist_first (rfd->mon_eth, NULL, (void **) &mon_eth))
750 {
751
752 int rc;
753
754 if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE))
755 {
756 rfapiMonitorEthDetachImport (bgp, mon_eth);
757 }
758 else
759 {
760#if DEBUG_L2_EXTRA
761 zlog_debug
762 ("%s: callbacks disabled, not attempting to detach mon_eth %p",
763 __func__, mon_eth);
764#endif
765 }
766
767 if (mon_eth->timer)
768 {
769 thread_cancel (mon_eth->timer);
770 mon_eth->timer = NULL;
771 }
772
773 /*
774 * remove from rfd list
775 */
776 rc = skiplist_delete (rfd->mon_eth, mon_eth, mon_eth);
777 assert (!rc);
778
779 zlog_debug ("%s: freeing mon_eth %p", __func__, mon_eth);
780 XFREE (MTYPE_RFAPI_MONITOR_ETH, mon_eth);
781
782 ++count;
783 --rfd->monitor_count;
784 --bgp->rfapi->monitor_count;
785 }
786 skiplist_free (rfd->mon_eth);
787 rfd->mon_eth = NULL;
788
789 }
790
791 return count;
792}
793
794void
795rfapiMonitorResponseRemovalOff (struct bgp *bgp)
796{
797 if (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE)
798 {
799 return;
800 }
801 bgp->rfapi_cfg->flags |= BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE;
802}
803
804void
805rfapiMonitorResponseRemovalOn (struct bgp *bgp)
806{
807 if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE))
808 {
809 return;
810 }
811 bgp->rfapi_cfg->flags &= ~BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE;
812}
813
814static int
815rfapiMonitorTimerExpire (struct thread *t)
816{
817 struct rfapi_monitor_vpn *m = t->arg;
818
819 /* forget reference to thread, it's gone */
820 m->timer = NULL;
821
822 /* delete the monitor */
823 rfapiMonitorDel (bgp_get_default (), m->rfd, &m->p);
824
825 return 0;
826}
827
828static void
829rfapiMonitorTimerRestart (struct rfapi_monitor_vpn *m)
830{
831 if (m->timer)
832 {
833 unsigned long remain = thread_timer_remain_second (m->timer);
834
835 /* unexpected case, but avoid wraparound problems below */
836 if (remain > m->rfd->response_lifetime)
837 return;
838
839 /* don't restart if we just restarted recently */
840 if (m->rfd->response_lifetime - remain < 2)
841 return;
842
843 thread_cancel (m->timer);
844 m->timer = NULL;
845 }
846
847 {
848 char buf[BUFSIZ];
849
850 zlog_debug ("%s: target %s life %u", __func__,
851 rfapi_ntop (m->p.family, m->p.u.val, buf, BUFSIZ),
852 m->rfd->response_lifetime);
853 }
854 m->timer = thread_add_timer (bm->master, rfapiMonitorTimerExpire, m,
855 m->rfd->response_lifetime);
856}
857
858/*
859 * called when an updated response is sent to the NVE. Per
860 * ticket 255, restart timers for any monitors that could have
861 * been responsible for the response, i.e., any monitors for
862 * the exact prefix or a parent of it.
863 */
864void
865rfapiMonitorTimersRestart (struct rfapi_descriptor *rfd, struct prefix *p)
866{
867 struct route_node *rn;
868
869 if (AF_ETHERNET == p->family)
870 {
871 struct rfapi_monitor_eth *mon_eth;
872 int rc;
873 void *cursor;
874
875 /*
876 * XXX match any LNI
877 */
878 for (cursor = NULL,
879 rc =
880 skiplist_next (rfd->mon_eth, NULL, (void **) &mon_eth, &cursor);
881 rc == 0;
882 rc =
883 skiplist_next (rfd->mon_eth, NULL, (void **) &mon_eth, &cursor))
884 {
885
886 if (!memcmp (mon_eth->macaddr.octet, p->u.prefix_eth.octet,
887 ETHER_ADDR_LEN))
888 {
889
890 rfapiMonitorEthTimerRestart (mon_eth);
891
892 }
893 }
894
895 }
896 else
897 {
898 for (rn = route_top (rfd->mon); rn; rn = route_next (rn))
899 {
900 struct rfapi_monitor_vpn *m;
901
902 if (!((m = rn->info)))
903 continue;
904
905 /* NB order of test is significant ! */
906 if (!m->node || prefix_match (&m->node->p, p))
907 {
908 rfapiMonitorTimerRestart (m);
909 }
910 }
911 }
912}
913
914/*
915 * Find monitors at this node and all its parents. Call
916 * rfapiRibUpdatePendingNode with this node and all corresponding NVEs.
917 */
918void
919rfapiMonitorItNodeChanged (
920 struct rfapi_import_table *import_table,
921 struct route_node *it_node,
922 struct rfapi_monitor_vpn *monitor_list) /* for base it node, NULL=all */
923{
924 struct skiplist *nves_seen;
925 struct route_node *rn = it_node;
926 struct bgp *bgp = bgp_get_default ();
927 afi_t afi = family2afi (rn->p.family);
928#if DEBUG_L2_EXTRA
929 char buf_prefix[BUFSIZ];
930#endif
931
932 assert (bgp);
933 assert (import_table);
934
935 nves_seen = skiplist_new (0, NULL, NULL);
936
937#if DEBUG_L2_EXTRA
938 prefix2str (&it_node->p, buf_prefix, BUFSIZ);
939 zlog_debug ("%s: it=%p, it_node=%p, it_node->prefix=%s",
940 __func__, import_table, it_node, buf_prefix);
941#endif
942
943 if (AFI_ETHER == afi)
944 {
945 struct rfapi_monitor_eth *m;
946 struct skiplist *sl;
947 void *cursor;
948 int rc;
949
950 if ((sl = RFAPI_MONITOR_ETH (rn)))
951 {
952
953 for (cursor = NULL,
954 rc = skiplist_next (sl, NULL, (void **) &m, (void **) &cursor);
955 !rc;
956 rc = skiplist_next (sl, NULL, (void **) &m, (void **) &cursor))
957 {
958
959 if (skiplist_search (nves_seen, m->rfd, NULL))
960 {
961 /*
962 * Haven't done this NVE yet. Add to "seen" list.
963 */
964 assert (!skiplist_insert (nves_seen, m->rfd, NULL));
965
966 /*
967 * update its RIB
968 */
969 rfapiRibUpdatePendingNode(bgp, m->rfd, import_table,
970 it_node, m->rfd->response_lifetime);
971 }
972 }
973 }
974
975 }
976 else
977 {
978
979 struct rfapi_monitor_vpn *m;
980
981 if (monitor_list)
982 {
983 m = monitor_list;
984 }
985 else
986 {
987 m = RFAPI_MONITOR_VPN (rn);
988 }
989
990 do
991 {
992 /*
993 * If we have reached the root node (parent==NULL) and there
994 * are no routes here (info==NULL), and the IT node that
995 * changed was not the root node (it_node->parent != NULL),
996 * then any monitors at this node are here because they had
997 * no match at all. Therefore, do not send route updates to them
998 * because we haven't sent them an initial route.
999 */
1000 if (!rn->parent && !rn->info && it_node->parent)
1001 break;
1002
1003 for (; m; m = m->next)
1004 {
1005
1006 if (RFAPI_0_PREFIX (&m->p))
1007 {
1008 /* shouldn't happen, but be safe */
1009 continue;
1010 }
1011 if (skiplist_search (nves_seen, m->rfd, NULL))
1012 {
1013 /*
1014 * Haven't done this NVE yet. Add to "seen" list.
1015 */
1016 assert (!skiplist_insert (nves_seen, m->rfd, NULL));
1017
1018 {
1019 char buf_attach_pfx[BUFSIZ];
1020 char buf_target_pfx[BUFSIZ];
1021
1022 prefix2str (&m->node->p, buf_attach_pfx, BUFSIZ);
1023 prefix2str (&m->p, buf_target_pfx, BUFSIZ);
1024 zlog_debug
1025 ("%s: update rfd %p attached to pfx %s (targ=%s)",
1026 __func__, m->rfd, buf_attach_pfx, buf_target_pfx);
1027 }
1028
1029 /*
1030 * update its RIB
1031 */
1032 rfapiRibUpdatePendingNode(bgp, m->rfd, import_table,
1033 it_node, m->rfd->response_lifetime);
1034 }
1035 }
1036 rn = rn->parent;
1037 if (rn)
1038 m = RFAPI_MONITOR_VPN (rn);
1039 }
1040 while (rn);
1041 }
1042
1043 /*
1044 * All-routes L2 monitors
1045 */
1046 if (AFI_ETHER == afi)
1047 {
1048 struct rfapi_monitor_eth *e;
1049
1050#if DEBUG_L2_EXTRA
1051 zlog_debug ("%s: checking L2 all-routes monitors", __func__);
1052#endif
1053
1054 for (e = import_table->eth0_queries; e; e = e->next)
1055 {
1056#if DEBUG_L2_EXTRA
1057 zlog_debug ("%s: checking eth0 mon=%p", __func__, e);
1058#endif
1059 if (skiplist_search (nves_seen, e->rfd, NULL))
1060 {
1061 /*
1062 * Haven't done this NVE yet. Add to "seen" list.
1063 */
1064 assert (!skiplist_insert (nves_seen, e->rfd, NULL));
1065
1066 /*
1067 * update its RIB
1068 */
1069#if DEBUG_L2_EXTRA
1070 zlog_debug ("%s: found L2 all-routes monitor %p", __func__, e);
1071#endif
1072 rfapiRibUpdatePendingNode (bgp, e->rfd, import_table, it_node,
1073 e->rfd->response_lifetime);
1074 }
1075 }
1076 }
1077 else
1078 {
1079 struct rfapi_monitor_vpn *m;
1080
1081 /*
1082 * All-routes IPv4. IPv6 monitors
1083 */
1084 for (m = import_table->vpn0_queries[afi]; m; m = m->next)
1085 {
1086 if (skiplist_search (nves_seen, m->rfd, NULL))
1087 {
1088 /*
1089 * Haven't done this NVE yet. Add to "seen" list.
1090 */
1091 assert (!skiplist_insert (nves_seen, m->rfd, NULL));
1092
1093 /*
1094 * update its RIB
1095 */
1096 rfapiRibUpdatePendingNode (bgp, m->rfd, import_table, it_node,
1097 m->rfd->response_lifetime);
1098 }
1099 }
1100 }
1101
1102 skiplist_free (nves_seen);
1103}
1104
1105/*
1106 * For the listed monitors, update new node and its subtree, but
1107 * omit old node and its subtree
1108 */
1109void
1110rfapiMonitorMovedUp (
1111 struct rfapi_import_table *import_table,
1112 struct route_node *old_node,
1113 struct route_node *new_node,
1114 struct rfapi_monitor_vpn *monitor_list)
1115{
1116 struct bgp *bgp = bgp_get_default ();
1117 struct rfapi_monitor_vpn *m;
1118
1119 assert (new_node);
1120 assert (old_node);
1121 assert (new_node != old_node);
1122
1123 /*
1124 * If new node is 0/0 and there is no route there, don't
1125 * generate an update because it will not contain any
1126 * routes including the target.
1127 */
1128 if (!new_node->parent && !new_node->info)
1129 {
1130 zlog_debug ("%s: new monitor at 0/0 and no routes, no updates",
1131 __func__);
1132 return;
1133 }
1134
1135 for (m = monitor_list; m; m = m->next)
1136 {
1137 rfapiRibUpdatePendingNode (bgp, m->rfd, import_table, new_node,
1138 m->rfd->response_lifetime);
1139 rfapiRibUpdatePendingNodeSubtree (bgp, m->rfd, import_table, new_node,
1140 old_node, m->rfd->response_lifetime);
1141 }
1142}
1143
1144static int
1145rfapiMonitorEthTimerExpire (struct thread *t)
1146{
1147 struct rfapi_monitor_eth *m = t->arg;
1148
1149 /* forget reference to thread, it's gone */
1150 m->timer = NULL;
1151
1152 /* delete the monitor */
1153 rfapiMonitorEthDel (bgp_get_default (), m->rfd, &m->macaddr,
1154 m->logical_net_id);
1155
1156 return 0;
1157}
1158
1159static void
1160rfapiMonitorEthTimerRestart (struct rfapi_monitor_eth *m)
1161{
1162 if (m->timer)
1163 {
1164 unsigned long remain = thread_timer_remain_second (m->timer);
1165
1166 /* unexpected case, but avoid wraparound problems below */
1167 if (remain > m->rfd->response_lifetime)
1168 return;
1169
1170 /* don't restart if we just restarted recently */
1171 if (m->rfd->response_lifetime - remain < 2)
1172 return;
1173
1174 thread_cancel (m->timer);
1175 m->timer = NULL;
1176 }
1177
1178 {
1179 char buf[BUFSIZ];
1180
1181 zlog_debug ("%s: target %s life %u", __func__,
1182 rfapiEthAddr2Str (&m->macaddr, buf, BUFSIZ),
1183 m->rfd->response_lifetime);
1184 }
1185 m->timer = thread_add_timer (bm->master, rfapiMonitorEthTimerExpire, m,
1186 m->rfd->response_lifetime);
1187}
1188
1189static int
1190mon_eth_cmp (void *a, void *b)
1191{
1192 struct rfapi_monitor_eth *m1;
1193 struct rfapi_monitor_eth *m2;
1194
1195 int i;
1196
1197 m1 = (struct rfapi_monitor_eth *) a;
1198 m2 = (struct rfapi_monitor_eth *) b;
1199
1200 /*
1201 * compare ethernet addresses
1202 */
1203 for (i = 0; i < ETHER_ADDR_LEN; ++i)
1204 {
1205 if (m1->macaddr.octet[i] != m2->macaddr.octet[i])
1206 return (m1->macaddr.octet[i] - m2->macaddr.octet[i]);
1207 }
1208
1209 /*
1210 * compare LNIs
1211 */
1212 return (m1->logical_net_id - m2->logical_net_id);
1213}
1214
1215static void
1216rfapiMonitorEthAttachImport (
1217 struct rfapi_import_table *it,
1218 struct route_node *rn, /* it node attach point if non-0 */
1219 struct rfapi_monitor_eth *mon) /* monitor struct to attach */
1220{
1221 struct skiplist *sl;
1222 int rc;
1223
1224 zlog_debug ("%s: it=%p", __func__, it);
1225
1226 rfapiMonitorCheckAttachAllowed ();
1227
1228 if (RFAPI_0_ETHERADDR (&mon->macaddr))
1229 {
1230 /*
1231 * These go on a different list
1232 */
1233 mon->next = it->eth0_queries;
1234 it->eth0_queries = mon;
1235#if DEBUG_L2_EXTRA
1236 zlog_debug ("%s: attached monitor %p to eth0 list", __func__, mon);
1237#endif
1238 return;
1239 }
1240
1241 if (rn == NULL)
1242 {
1243#if DEBUG_L2_EXTRA
1244 zlog_debug ("%s: rn is null!", __func__);
1245#endif
1246 return;
1247 }
1248
1249 /*
1250 * Get sl to attach to
1251 */
1252 sl = RFAPI_MONITOR_ETH_W_ALLOC (rn);
1253 if (!sl)
1254 {
1255 sl = RFAPI_MONITOR_ETH_W_ALLOC (rn) = skiplist_new (0, NULL, NULL);
1256 route_lock_node(rn); /* count skiplist mon_eth */
1257 }
1258
1259#if DEBUG_L2_EXTRA
1260 zlog_debug ("%s: rn=%p, rn->lock=%d, sl=%p, attaching eth mon %p",
1261 __func__, rn, rn->lock, sl, mon);
1262#endif
1263
1264 rc = skiplist_insert (sl, (void *) mon, (void *) mon);
1265 assert (!rc);
1266
1267 /* count eth monitor */
1268 route_lock_node(rn);
1269}
1270
1271/*
1272 * reattach monitors for this HD to import table
1273 */
1274static void
1275rfapiMonitorEthAttachImportHd (struct bgp *bgp, struct rfapi_descriptor *rfd)
1276{
1277 void *cursor;
1278 struct rfapi_monitor_eth *mon;
1279 int rc;
1280
1281 if (!rfd->mon_eth)
1282 {
1283 /*
1284 * No monitors for this HD
1285 */
1286 return;
1287 }
1288
1289 for (cursor = NULL,
1290 rc = skiplist_next (rfd->mon_eth, NULL, (void **) &mon, &cursor);
1291 rc == 0;
1292 rc = skiplist_next (rfd->mon_eth, NULL, (void **) &mon, &cursor))
1293 {
1294
1295 struct rfapi_import_table *it;
1296 struct prefix pfx_mac_buf;
1297 struct route_node *rn;
1298
1299 it = rfapiMacImportTableGet (bgp, mon->logical_net_id);
1300 assert (it);
1301
1302 memset ((void *) &pfx_mac_buf, 0, sizeof (struct prefix));
1303 pfx_mac_buf.family = AF_ETHERNET;
1304 pfx_mac_buf.prefixlen = 48;
1305 pfx_mac_buf.u.prefix_eth = mon->macaddr;
1306
1307 rn = route_node_get (it->imported_vpn[AFI_ETHER], &pfx_mac_buf);
1308 assert (rn);
1309
1310 (void) rfapiMonitorEthAttachImport (it, rn, mon);
1311 }
1312}
1313
1314static void
1315rfapiMonitorEthDetachImport (
1316 struct bgp *bgp,
1317 struct rfapi_monitor_eth *mon) /* monitor struct to detach */
1318{
1319 struct rfapi_import_table *it;
1320 struct prefix pfx_mac_buf;
1321 struct skiplist *sl;
1322 struct route_node *rn;
1323 int rc;
1324
1325 it = rfapiMacImportTableGet (bgp, mon->logical_net_id);
1326 assert (it);
1327
1328 if (RFAPI_0_ETHERADDR (&mon->macaddr))
1329 {
1330 struct rfapi_monitor_eth *prev;
1331 struct rfapi_monitor_eth *this = NULL;
1332
1333 for (prev = NULL,
1334 this = it->eth0_queries; this; prev = this, this = this->next)
1335 {
1336
1337 if (this == mon)
1338 break;
1339 }
1340 if (this)
1341 {
1342 if (!prev)
1343 {
1344 it->eth0_queries = this->next;
1345 }
1346 else
1347 {
1348 prev->next = this->next;
1349 }
1350 }
1351#if DEBUG_L2_EXTRA
1352 zlog_debug ("%s: it=%p, LNI=%d, detached eth0 mon %p",
1353 __func__, it, mon->logical_net_id, mon);
1354#endif
1355 return;
1356 }
1357
1358 memset ((void *) &pfx_mac_buf, 0, sizeof (struct prefix));
1359 pfx_mac_buf.family = AF_ETHERNET;
1360 pfx_mac_buf.prefixlen = 48;
1361 pfx_mac_buf.u.prefix_eth = mon->macaddr;
1362
1363 rn = route_node_get (it->imported_vpn[AFI_ETHER], &pfx_mac_buf);
1364 assert (rn);
1365
1366#if DEBUG_L2_EXTRA
1367 char buf_prefix[BUFSIZ];
1368 prefix2str (&rn->p, buf_prefix, BUFSIZ);
1369#endif
1370
1371 /*
1372 * Get sl to detach from
1373 */
1374 sl = RFAPI_MONITOR_ETH (rn);
1375#if DEBUG_L2_EXTRA
1376 zlog_debug ("%s: it=%p, rn=%p, rn->lock=%d, sl=%p, pfx=%s, LNI=%d, detaching eth mon %p",
1377 __func__, it, rn, rn->lock, sl, buf_prefix, mon->logical_net_id, mon);
1378#endif
1379 assert (sl);
1380
1381
1382 rc = skiplist_delete (sl, (void *) mon, (void *) mon);
1383 assert (!rc);
1384
1385 /* uncount eth monitor */
1386 route_unlock_node(rn);
1387}
1388
1389struct route_node *
1390rfapiMonitorEthAdd (
1391 struct bgp *bgp,
1392 struct rfapi_descriptor *rfd,
1393 struct ethaddr *macaddr,
1394 uint32_t logical_net_id)
1395{
1396 int rc;
1397 struct rfapi_monitor_eth mon_buf;
1398 struct rfapi_monitor_eth *val;
1399 struct rfapi_import_table *it;
1400 struct route_node *rn = NULL;
1401 struct prefix pfx_mac_buf;
1402
1403 if (!rfd->mon_eth)
1404 {
1405 rfd->mon_eth = skiplist_new (0, mon_eth_cmp, NULL);
1406 }
1407
1408 it = rfapiMacImportTableGet (bgp, logical_net_id);
1409 assert (it);
1410
1411 /*
1412 * Get route node in import table. Here is where we attach the
1413 * monitor.
1414 *
1415 * Look it up now because we return it to caller regardless of
1416 * whether we create a new monitor or not.
1417 */
1418 memset ((void *) &pfx_mac_buf, 0, sizeof (struct prefix));
1419 pfx_mac_buf.family = AF_ETHERNET;
1420 pfx_mac_buf.prefixlen = 48;
1421 pfx_mac_buf.u.prefix_eth = *macaddr;
1422
1423 if (!RFAPI_0_ETHERADDR (macaddr))
1424 {
1425 rn = route_node_get (it->imported_vpn[AFI_ETHER], &pfx_mac_buf);
1426 assert (rn);
1427 }
1428
1429 memset ((void *) &mon_buf, 0, sizeof (mon_buf));
1430 mon_buf.rfd = rfd;
1431 mon_buf.macaddr = *macaddr;
1432 mon_buf.logical_net_id = logical_net_id;
1433
1434 {
1435 char buf[BUFSIZ];
1436
1437 zlog_debug ("%s: LNI=%d: rfd=%p, pfx=%s",
1438 __func__, logical_net_id, rfd,
1439 rfapi_ntop (pfx_mac_buf.family, pfx_mac_buf.u.val, buf,
1440 BUFSIZ));
1441 }
1442
1443
1444 /*
1445 * look up query
1446 */
1447 rc = skiplist_search (rfd->mon_eth, (void *) &mon_buf, (void **) &val);
1448 if (!rc)
1449 {
1450 /*
1451 * Found monitor - we have seen this query before
1452 * restart timer
1453 */
1454 zlog_debug ("%s: already present in rfd->mon_eth, not adding",
1455 __func__);
1456 rfapiMonitorEthTimerRestart (val);
1457 return rn;
1458 }
1459
1460 /*
1461 * New query
1462 */
1463 val = XCALLOC (MTYPE_RFAPI_MONITOR_ETH, sizeof (struct rfapi_monitor_eth));
1464 assert (val);
1465 *val = mon_buf;
1466
1467 ++rfd->monitor_count;
1468 ++bgp->rfapi->monitor_count;
1469
1470 rc = skiplist_insert (rfd->mon_eth, val, val);
1471
1472#if DEBUG_L2_EXTRA
1473 zlog_debug ("%s: inserted rfd=%p mon_eth=%p, rc=%d", __func__, rfd, val,
1474 rc);
1475#endif
1476
1477 /*
1478 * start timer
1479 */
1480 rfapiMonitorEthTimerRestart (val);
1481
1482 if (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)
1483 {
1484 /*
1485 * callbacks turned off, so don't attach monitor to import table
1486 */
1487#if DEBUG_L2_EXTRA
1488 zlog_debug
1489 ("%s: callbacks turned off, not attaching mon_eth %p to import table",
1490 __func__, val);
1491#endif
1492 return rn;
1493 }
1494
1495 /*
1496 * attach to import table
1497 */
1498 rfapiMonitorEthAttachImport (it, rn, val);
1499
1500 return rn;
1501}
1502
1503void
1504rfapiMonitorEthDel (
1505 struct bgp *bgp,
1506 struct rfapi_descriptor *rfd,
1507 struct ethaddr *macaddr,
1508 uint32_t logical_net_id)
1509{
1510 struct rfapi_monitor_eth *val;
1511 struct rfapi_monitor_eth mon_buf;
1512 int rc;
1513
1514 zlog_debug ("%s: entry rfd=%p", __func__, rfd);
1515
1516 assert (rfd->mon_eth);
1517
1518 memset ((void *) &mon_buf, 0, sizeof (mon_buf));
1519 mon_buf.macaddr = *macaddr;
1520 mon_buf.logical_net_id = logical_net_id;
1521
1522 rc = skiplist_search (rfd->mon_eth, (void *) &mon_buf, (void **) &val);
1523 assert (!rc);
1524
1525 /*
1526 * remove from import table
1527 */
1528 if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE))
1529 {
1530 rfapiMonitorEthDetachImport (bgp, val);
1531 }
1532
1533 if (val->timer)
1534 {
1535 thread_cancel (val->timer);
1536 val->timer = NULL;
1537 }
1538
1539 /*
1540 * remove from rfd list
1541 */
1542 rc = skiplist_delete (rfd->mon_eth, val, val);
1543 assert (!rc);
1544
1545#if DEBUG_L2_EXTRA
1546 zlog_debug ("%s: freeing mon_eth %p", __func__, val);
1547#endif
1548 XFREE (MTYPE_RFAPI_MONITOR_ETH, val);
1549
1550 --rfd->monitor_count;
1551 --bgp->rfapi->monitor_count;
1552}
1553
1554
1555void
1556rfapiMonitorCallbacksOff (struct bgp *bgp)
1557{
1558 struct rfapi_import_table *it;
1559 afi_t afi;
1560 struct route_table *rt;
1561 struct route_node *rn;
1562 void *cursor;
1563 int rc;
1564 struct rfapi *h = bgp->rfapi;
1565
1566 if (bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE)
1567 {
1568 /*
1569 * Already off.
1570 */
1571 return;
1572 }
1573 bgp->rfapi_cfg->flags |= BGP_VNC_CONFIG_CALLBACK_DISABLE;
1574
1575#if DEBUG_L2_EXTRA
1576 zlog_debug ("%s: turned off callbacks", __func__);
1577#endif
1578
1579 if (h == NULL)
1580 return;
1581 /*
1582 * detach monitors from import VPN tables. The monitors
1583 * will still be linked in per-nve monitor lists.
1584 */
1585 for (it = h->imports; it; it = it->next)
1586 {
1587 for (afi = AFI_IP; afi < AFI_MAX; ++afi)
1588 {
1589
1590 struct rfapi_monitor_vpn *m;
1591 struct rfapi_monitor_vpn *next;
1592
1593 rt = it->imported_vpn[afi];
1594
1595 for (rn = route_top (rt); rn; rn = route_next (rn))
1596 {
1597 m = RFAPI_MONITOR_VPN (rn);
1598 if (RFAPI_MONITOR_VPN (rn))
1599 RFAPI_MONITOR_VPN_W_ALLOC (rn) = NULL;
1600 for (; m; m = next)
1601 {
1602 next = m->next;
1603 m->next = NULL; /* gratuitous safeness */
1604 m->node = NULL;
1605 route_unlock_node (rn); /* uncount */
1606 }
1607 }
1608
1609 for (m = it->vpn0_queries[afi]; m; m = next)
1610 {
1611 next = m->next;
1612 m->next = NULL; /* gratuitous safeness */
1613 m->node = NULL;
1614 }
1615 it->vpn0_queries[afi] = NULL; /* detach first monitor */
1616 }
1617 }
1618
1619 /*
1620 * detach monitors from import Eth tables. The monitors
1621 * will still be linked in per-nve monitor lists.
1622 */
1623
1624 /*
1625 * Loop over ethernet import tables
1626 */
1627 for (cursor = NULL,
1628 rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor);
1629 !rc; rc = skiplist_next (h->import_mac, NULL, (void **) &it, &cursor))
1630 {
1631 struct rfapi_monitor_eth *e;
1632 struct rfapi_monitor_eth *enext;
1633
1634 /*
1635 * The actual route table
1636 */
1637 rt = it->imported_vpn[AFI_ETHER];
1638
1639 /*
1640 * Find non-0 monitors (i.e., actual addresses, not FTD monitors)
1641 */
1642 for (rn = route_top (rt); rn; rn = route_next (rn))
1643 {
1644 struct skiplist *sl;
1645
1646 sl = RFAPI_MONITOR_ETH (rn);
1647 while (!skiplist_delete_first(sl))
1648 {
1649 route_unlock_node (rn); /* uncount monitor */
1650 }
1651 }
1652
1653 /*
1654 * Find 0-monitors (FTD queries)
1655 */
1656 for (e = it->eth0_queries; e; e = enext)
1657 {
1658#if DEBUG_L2_EXTRA
1659 zlog_debug ("%s: detaching eth0 mon %p", __func__, e);
1660#endif
1661 enext = e->next;
1662 e->next = NULL; /* gratuitous safeness */
1663 }
1664 it->eth0_queries = NULL; /* detach first monitor */
1665 }
1666}
1667
1668void
1669rfapiMonitorCallbacksOn (struct bgp *bgp)
1670{
1671 struct listnode *hnode;
1672 struct rfapi_descriptor *rfd;
1673
1674 if (!(bgp->rfapi_cfg->flags & BGP_VNC_CONFIG_CALLBACK_DISABLE))
1675 {
1676 /*
1677 * Already on. It's important that we don't try to reattach
1678 * monitors that are already attached because, in the interest
1679 * of performance, there is no checking at the lower level
1680 * whether a monitor is already attached. It leads to
1681 * corrupted chains (e.g., looped pointers)
1682 */
1683 return;
1684 }
1685 bgp->rfapi_cfg->flags &= ~BGP_VNC_CONFIG_CALLBACK_DISABLE;
1686#if DEBUG_L2_EXTRA
1687 zlog_debug ("%s: turned on callbacks", __func__);
1688#endif
1689 if (bgp->rfapi == NULL)
1690 return;
1691
1692 /*
1693 * reattach monitors
1694 */
1695 for (ALL_LIST_ELEMENTS_RO (&bgp->rfapi->descriptors, hnode, rfd))
1696 {
1697
1698 rfapiMonitorAttachImportHd (rfd);
1699 rfapiMonitorEthAttachImportHd (bgp, rfd);
1700 }
1701}