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