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