]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/rfapi/rfapi_rib.c
bgpd: Prevent memory leak of listener on shutdown
[mirror_frr.git] / bgpd / rfapi / rfapi_rib.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_rib.c
23 * Purpose: maintain per-nve ribs and generate change lists
24 */
25
f8b6f499
LB
26#include "lib/zebra.h"
27#include "lib/prefix.h"
fe08ba7e 28#include "lib/agg_table.h"
f8b6f499
LB
29#include "lib/vty.h"
30#include "lib/memory.h"
31#include "lib/log.h"
32#include "lib/skiplist.h"
33#include "lib/workqueue.h"
65efcfce 34
f8b6f499
LB
35#include "bgpd/bgpd.h"
36#include "bgpd/bgp_route.h"
37#include "bgpd/bgp_ecommunity.h"
38#include "bgpd/bgp_mplsvpn.h"
39#include "bgpd/bgp_vnc_types.h"
65efcfce 40
f8b6f499
LB
41#include "bgpd/rfapi/rfapi.h"
42#include "bgpd/rfapi/bgp_rfapi_cfg.h"
43#include "bgpd/rfapi/rfapi_import.h"
44#include "bgpd/rfapi/rfapi_private.h"
45#include "bgpd/rfapi/rfapi_vty.h"
46#include "bgpd/rfapi/vnc_import_bgp.h"
47#include "bgpd/rfapi/rfapi_rib.h"
48#include "bgpd/rfapi/rfapi_monitor.h"
49#include "bgpd/rfapi/rfapi_encap_tlv.h"
a3b55c25 50#include "bgpd/rfapi/vnc_debug.h"
65efcfce
LB
51
52#define DEBUG_PROCESS_PENDING_NODE 0
53#define DEBUG_PENDING_DELETE_ROUTE 0
54#define DEBUG_NHL 0
55#define DEBUG_RIB_SL_RD 0
56
57/* forward decl */
58#if DEBUG_NHL
d62a17ae 59static void rfapiRibShowRibSl(void *stream, struct prefix *pfx,
60 struct skiplist *sl);
65efcfce
LB
61#endif
62
63/*
64 * RIB
65 * ---
66 * Model of the set of routes currently in the NVE's RIB.
67 *
68 * node->info ptr to "struct skiplist".
69 * MUST be NULL if there are no routes.
70 * key = ptr to struct prefix {vn}
71 * val = ptr to struct rfapi_info
72 * skiplist.del = NULL
73 * skiplist.cmp = vnc_prefix_cmp
74 *
75 * node->aggregate ptr to "struct skiplist".
76 * key = ptr to struct prefix {vn}
77 * val = ptr to struct rfapi_info
78 * skiplist.del = rfapi_info_free
79 * skiplist.cmp = vnc_prefix_cmp
80 *
81 * This skiplist at "aggregate"
82 * contains the routes recently
83 * deleted
84 *
85 *
86 * Pending RIB
87 * -----------
88 * Sparse list of prefixes that need to be updated. Each node
89 * will have the complete set of routes for the prefix.
90 *
91 * node->info ptr to "struct list" (lib/linklist.h)
92 * "Cost List"
93 * List of routes sorted lowest cost first.
94 * This list is how the new complete set
95 * of routes should look.
96 * Set if there are updates to the prefix;
97 * MUST be NULL if there are no updates.
98 *
99 * .data = ptr to struct rfapi_info
100 * list.cmp = NULL (sorted manually)
101 * list.del = rfapi_info_free
102 *
103 * Special case: if node->info is 1, it means
104 * "delete all routes at this prefix".
105 *
106 * node->aggregate ptr to struct skiplist
107 * key = ptr to struct prefix {vn} (part of ri)
108 * val = struct rfapi_info
109 * skiplist.cmp = vnc_prefix_cmp
110 * skiplist.del = NULL
111 *
112 * ptlist is rewritten anew each time
113 * rfapiRibUpdatePendingNode() is called
114 *
115 * THE ptlist VALUES ARE REFERENCES TO THE
116 * rfapi_info STRUCTS IN THE node->info LIST.
117 */
118
119/*
120 * iterate over RIB to count responses, compare with running counters
121 */
d62a17ae 122void rfapiRibCheckCounts(
123 int checkstats, /* validate rfd & global counts */
124 unsigned int offset) /* number of ri's held separately */
65efcfce 125{
d62a17ae 126 struct rfapi_descriptor *rfd;
127 struct listnode *node;
128
129 struct bgp *bgp = bgp_get_default();
130
131 uint32_t t_pfx_active = 0;
132 uint32_t t_pfx_deleted = 0;
133
134 uint32_t t_ri_active = 0;
135 uint32_t t_ri_deleted = 0;
136 uint32_t t_ri_pend = 0;
137
138 unsigned int alloc_count;
139
140 /*
141 * loop over NVEs
142 */
143 for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, node, rfd)) {
144
145 afi_t afi;
146 uint32_t pfx_active = 0;
147 uint32_t pfx_deleted = 0;
148
149 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
150
fe08ba7e 151 struct agg_node *rn;
d62a17ae 152
fe08ba7e
DS
153 for (rn = agg_route_top(rfd->rib[afi]); rn;
154 rn = agg_route_next(rn)) {
d62a17ae 155
156 struct skiplist *sl = rn->info;
157 struct skiplist *dsl = rn->aggregate;
158 uint32_t ri_active = 0;
159 uint32_t ri_deleted = 0;
160
161 if (sl) {
162 ri_active = skiplist_count(sl);
163 assert(ri_active);
164 t_ri_active += ri_active;
165 ++pfx_active;
166 ++t_pfx_active;
167 }
168
169 if (dsl) {
170 ri_deleted = skiplist_count(dsl);
171 t_ri_deleted += ri_deleted;
172 ++pfx_deleted;
173 ++t_pfx_deleted;
174 }
175 }
fe08ba7e
DS
176 for (rn = agg_route_top(rfd->rib_pending[afi]); rn;
177 rn = agg_route_next(rn)) {
d62a17ae 178
179 struct list *l = rn->info; /* sorted by cost */
180 struct skiplist *sl = rn->aggregate;
181 uint32_t ri_pend_cost = 0;
182 uint32_t ri_pend_uniq = 0;
183
184 if (sl) {
185 ri_pend_uniq = skiplist_count(sl);
186 }
187
188 if (l && (l != (void *)1)) {
189 ri_pend_cost = l->count;
190 t_ri_pend += l->count;
191 }
192
193 assert(ri_pend_uniq == ri_pend_cost);
194 }
195 }
196
197 if (checkstats) {
198 if (pfx_active != rfd->rib_prefix_count) {
199 vnc_zlog_debug_verbose(
200 "%s: rfd %p actual pfx count %u != running %u",
201 __func__, rfd, pfx_active,
202 rfd->rib_prefix_count);
203 assert(0);
204 }
205 }
206 }
207
8cea9547 208 if (checkstats && bgp->rfapi) {
d62a17ae 209 if (t_pfx_active != bgp->rfapi->rib_prefix_count_total) {
210 vnc_zlog_debug_verbose(
211 "%s: actual total pfx count %u != running %u",
212 __func__, t_pfx_active,
213 bgp->rfapi->rib_prefix_count_total);
214 assert(0);
215 }
216 }
217
218 /*
219 * Check against memory allocation count
220 */
221 alloc_count = mtype_stats_alloc(MTYPE_RFAPI_INFO);
222 assert(t_ri_active + t_ri_deleted + t_ri_pend + offset == alloc_count);
65efcfce
LB
223}
224
4d762f26 225static struct rfapi_info *rfapi_info_new(void)
65efcfce 226{
d62a17ae 227 return XCALLOC(MTYPE_RFAPI_INFO, sizeof(struct rfapi_info));
65efcfce
LB
228}
229
d62a17ae 230void rfapiFreeRfapiUnOptionChain(struct rfapi_un_option *p)
65efcfce 231{
d62a17ae 232 while (p) {
233 struct rfapi_un_option *next;
234
235 next = p->next;
236 XFREE(MTYPE_RFAPI_UN_OPTION, p);
237 p = next;
238 }
65efcfce
LB
239}
240
d62a17ae 241void rfapiFreeRfapiVnOptionChain(struct rfapi_vn_option *p)
65efcfce 242{
d62a17ae 243 while (p) {
244 struct rfapi_vn_option *next;
245
246 next = p->next;
247 XFREE(MTYPE_RFAPI_VN_OPTION, p);
248 p = next;
249 }
65efcfce
LB
250}
251
252
d62a17ae 253static void rfapi_info_free(struct rfapi_info *goner)
65efcfce 254{
d62a17ae 255 if (goner) {
256 if (goner->tea_options) {
257 rfapiFreeBgpTeaOptionChain(goner->tea_options);
258 goner->tea_options = NULL;
259 }
260 if (goner->un_options) {
261 rfapiFreeRfapiUnOptionChain(goner->un_options);
262 goner->un_options = NULL;
263 }
264 if (goner->vn_options) {
265 rfapiFreeRfapiVnOptionChain(goner->vn_options);
266 goner->vn_options = NULL;
267 }
268 if (goner->timer) {
269 struct rfapi_rib_tcb *tcb;
270
c4efd0f4 271 tcb = goner->timer->arg;
b3d6bc6e 272 thread_cancel(&goner->timer);
d62a17ae 273 XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
d62a17ae 274 }
275 XFREE(MTYPE_RFAPI_INFO, goner);
276 }
65efcfce
LB
277}
278
279/*
280 * Timer control block for recently-deleted and expired routes
281 */
d62a17ae 282struct rfapi_rib_tcb {
283 struct rfapi_descriptor *rfd;
284 struct skiplist *sl;
285 struct rfapi_info *ri;
fe08ba7e 286 struct agg_node *rn;
d62a17ae 287 int flags;
65efcfce
LB
288#define RFAPI_RIB_TCB_FLAG_DELETED 0x00000001
289};
290
291/*
292 * remove route from rib
293 */
cc9f21da 294static void rfapiRibExpireTimer(struct thread *t)
65efcfce 295{
d62a17ae 296 struct rfapi_rib_tcb *tcb = t->arg;
297
298 RFAPI_RIB_CHECK_COUNTS(1, 0);
299
300 /*
301 * Forget reference to thread. Otherwise rfapi_info_free() will
302 * attempt to free thread pointer as an option chain
303 */
304 tcb->ri->timer = NULL;
305
306 /* "deleted" skiplist frees ri, "active" doesn't */
307 assert(!skiplist_delete(tcb->sl, &tcb->ri->rk, NULL));
308 if (!tcb->sl->del) {
309 /*
310 * XXX in this case, skiplist has no delete function: we must
311 * therefore delete rfapi_info explicitly.
312 */
313 rfapi_info_free(tcb->ri);
314 }
315
316 if (skiplist_empty(tcb->sl)) {
317 if (CHECK_FLAG(tcb->flags, RFAPI_RIB_TCB_FLAG_DELETED))
318 tcb->rn->aggregate = NULL;
319 else {
320 struct bgp *bgp = bgp_get_default();
321 tcb->rn->info = NULL;
322 RFAPI_RIB_PREFIX_COUNT_DECR(tcb->rfd, bgp->rfapi);
323 }
324 skiplist_free(tcb->sl);
fe08ba7e 325 agg_unlock_node(tcb->rn);
d62a17ae 326 }
327
328 XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
329
330 RFAPI_RIB_CHECK_COUNTS(1, 0);
65efcfce
LB
331}
332
fe08ba7e
DS
333static void rfapiRibStartTimer(struct rfapi_descriptor *rfd,
334 struct rfapi_info *ri,
335 struct agg_node *rn, /* route node attached to */
336 int deleted)
65efcfce 337{
d62a17ae 338 struct rfapi_rib_tcb *tcb = NULL;
d62a17ae 339
b3d6bc6e
MS
340 if (ri->timer) {
341 tcb = ri->timer->arg;
342 thread_cancel(&ri->timer);
d62a17ae 343 } else {
344 tcb = XCALLOC(MTYPE_RFAPI_RECENT_DELETE,
345 sizeof(struct rfapi_rib_tcb));
346 }
347 tcb->rfd = rfd;
348 tcb->ri = ri;
349 tcb->rn = rn;
350 if (deleted) {
351 tcb->sl = (struct skiplist *)rn->aggregate;
352 SET_FLAG(tcb->flags, RFAPI_RIB_TCB_FLAG_DELETED);
353 } else {
354 tcb->sl = (struct skiplist *)rn->info;
355 UNSET_FLAG(tcb->flags, RFAPI_RIB_TCB_FLAG_DELETED);
356 }
357
26a3ffd6
DS
358 vnc_zlog_debug_verbose("%s: rfd %p pfx %pRN life %u", __func__, rfd, rn,
359 ri->lifetime);
d62a17ae 360 ri->timer = NULL;
361 thread_add_timer(bm->master, rfapiRibExpireTimer, tcb, ri->lifetime,
362 &ri->timer);
363 assert(ri->timer);
65efcfce
LB
364}
365
d62a17ae 366extern void rfapi_rib_key_init(struct prefix *prefix, /* may be NULL */
367 struct prefix_rd *rd, /* may be NULL */
368 struct prefix *aux, /* may be NULL */
369 struct rfapi_rib_key *rk)
370
cedb5a71 371{
d62a17ae 372 memset((void *)rk, 0, sizeof(struct rfapi_rib_key));
373 if (prefix)
374 rk->vn = *prefix;
375 if (rd)
376 rk->rd = *rd;
377 if (aux)
378 rk->aux_prefix = *aux;
cedb5a71
LB
379}
380
65efcfce
LB
381/*
382 * Compares two <struct rfapi_rib_key>s
383 */
1a4189d4 384int rfapi_rib_key_cmp(const void *k1, const void *k2)
65efcfce 385{
1a4189d4
DS
386 const struct rfapi_rib_key *a = (struct rfapi_rib_key *)k1;
387 const struct rfapi_rib_key *b = (struct rfapi_rib_key *)k2;
d62a17ae 388 int ret;
65efcfce 389
d62a17ae 390 if (!a || !b)
391 return (a - b);
65efcfce 392
d62a17ae 393 ret = vnc_prefix_cmp(&a->vn, &b->vn);
394 if (ret)
395 return ret;
65efcfce 396
d62a17ae 397 ret = vnc_prefix_cmp(&a->rd, &b->rd);
398 if (ret)
399 return ret;
65efcfce 400
d62a17ae 401 ret = vnc_prefix_cmp(&a->aux_prefix, &b->aux_prefix);
65efcfce 402
d62a17ae 403 return ret;
65efcfce
LB
404}
405
406
407/*
408 * Note: this function will claim that two option chains are
409 * different unless their option items are in identical order.
410 * The consequence is that RFP updated responses can be sent
411 * unnecessarily, or that they might contain nexthop items
412 * that are not strictly needed.
413 *
414 * This function could be modified to compare option chains more
415 * thoroughly, but it's not clear that the extra compuation would
416 * be worth it.
417 */
d62a17ae 418static int bgp_tea_options_cmp(struct bgp_tea_options *a,
419 struct bgp_tea_options *b)
65efcfce 420{
d62a17ae 421 int rc;
422
423 if (!a || !b) {
424 return (a - b);
425 }
65efcfce 426
d62a17ae 427 if (a->type != b->type)
428 return (a->type - b->type);
429 if (a->length != b->length)
430 return (a->length = b->length);
431 if ((rc = memcmp(a->value, b->value, a->length)))
432 return rc;
433 if (!a->next != !b->next) { /* logical xor */
434 return (a->next - b->next);
435 }
436 if (a->next)
437 return bgp_tea_options_cmp(a->next, b->next);
438 return 0;
65efcfce
LB
439}
440
d62a17ae 441static int rfapi_info_cmp(struct rfapi_info *a, struct rfapi_info *b)
65efcfce 442{
d62a17ae 443 int rc;
65efcfce 444
d62a17ae 445 if (!a || !b)
446 return (a - b);
65efcfce 447
d62a17ae 448 if ((rc = rfapi_rib_key_cmp(&a->rk, &b->rk)))
449 return rc;
65efcfce 450
d62a17ae 451 if ((rc = vnc_prefix_cmp(&a->un, &b->un)))
452 return rc;
65efcfce 453
d62a17ae 454 if (a->cost != b->cost)
455 return (a->cost - b->cost);
65efcfce 456
d62a17ae 457 if (a->lifetime != b->lifetime)
458 return (a->lifetime - b->lifetime);
65efcfce 459
d62a17ae 460 if ((rc = bgp_tea_options_cmp(a->tea_options, b->tea_options)))
461 return rc;
65efcfce 462
d62a17ae 463 return 0;
65efcfce
LB
464}
465
d62a17ae 466void rfapiRibClear(struct rfapi_descriptor *rfd)
65efcfce 467{
d62a17ae 468 struct bgp *bgp;
469 afi_t afi;
65efcfce 470
d62a17ae 471 if (rfd->bgp)
472 bgp = rfd->bgp;
473 else
474 bgp = bgp_get_default();
1e20238a 475#ifdef DEBUG_L2_EXTRA
d62a17ae 476 vnc_zlog_debug_verbose("%s: rfd=%p", __func__, rfd);
65efcfce
LB
477#endif
478
d62a17ae 479 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
fe08ba7e
DS
480 struct agg_node *pn;
481 struct agg_node *rn;
d62a17ae 482
483 if (rfd->rib_pending[afi]) {
fe08ba7e
DS
484 for (pn = agg_route_top(rfd->rib_pending[afi]); pn;
485 pn = agg_route_next(pn)) {
d62a17ae 486 if (pn->aggregate) {
487 /*
488 * free references into the rfapi_info
489 * structures before
490 * freeing the structures themselves
491 */
492 skiplist_free(
493 (struct skiplist
494 *)(pn->aggregate));
495 pn->aggregate = NULL;
fe08ba7e 496 agg_unlock_node(
d62a17ae 497 pn); /* skiplist deleted */
498 }
499 /*
500 * free the rfapi_info structures
501 */
502 if (pn->info) {
503 if (pn->info != (void *)1) {
6a154c88 504 list_delete(
996c9314
LB
505 (struct list *
506 *)(&pn->info));
d62a17ae 507 }
508 pn->info = NULL;
affe9e99 509 /* linklist or 1 deleted */
fe08ba7e 510 agg_unlock_node(pn);
d62a17ae 511 }
512 }
513 }
514 if (rfd->rib[afi]) {
fe08ba7e
DS
515 for (rn = agg_route_top(rfd->rib[afi]); rn;
516 rn = agg_route_next(rn)) {
d62a17ae 517 if (rn->info) {
518
519 struct rfapi_info *ri;
520
9d303b37
DL
521 while (0 == skiplist_first(
522 (struct skiplist *)
523 rn->info,
524 NULL,
525 (void **)&ri)) {
d62a17ae 526
527 rfapi_info_free(ri);
528 skiplist_delete_first(
529 (struct skiplist *)
530 rn->info);
531 }
532 skiplist_free(
533 (struct skiplist *)rn->info);
534 rn->info = NULL;
fe08ba7e 535 agg_unlock_node(rn);
d62a17ae 536 RFAPI_RIB_PREFIX_COUNT_DECR(rfd,
537 bgp->rfapi);
538 }
539 if (rn->aggregate) {
540
541 struct rfapi_info *ri_del;
542
543 /* delete skiplist & contents */
544 while (!skiplist_first(
545 (struct skiplist
546 *)(rn->aggregate),
547 NULL, (void **)&ri_del)) {
548
549 /* sl->del takes care of ri_del
550 */
551 skiplist_delete_first((
552 struct skiplist
553 *)(rn->aggregate));
554 }
555 skiplist_free(
556 (struct skiplist
557 *)(rn->aggregate));
558
559 rn->aggregate = NULL;
fe08ba7e 560 agg_unlock_node(rn);
d62a17ae 561 }
562 }
563 }
564 }
e208c8f9
DS
565 if (rfd->updated_responses_queue)
566 work_queue_free_and_null(&rfd->updated_responses_queue);
65efcfce
LB
567}
568
569/*
570 * Release all dynamically-allocated memory that is part of an HD's RIB
571 */
d62a17ae 572void rfapiRibFree(struct rfapi_descriptor *rfd)
65efcfce 573{
d62a17ae 574 afi_t afi;
65efcfce
LB
575
576
d62a17ae 577 /*
578 * NB rfd is typically detached from master list, so is not included
579 * in the count performed by RFAPI_RIB_CHECK_COUNTS
580 */
65efcfce 581
d62a17ae 582 /*
583 * Free routes attached to radix trees
584 */
585 rfapiRibClear(rfd);
65efcfce 586
d62a17ae 587 /* Now the uncounted rfapi_info's are freed, so the check should succeed
588 */
589 RFAPI_RIB_CHECK_COUNTS(1, 0);
65efcfce 590
d62a17ae 591 /*
592 * Free radix trees
593 */
594 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
fe08ba7e
DS
595 if (rfd->rib_pending[afi])
596 agg_table_finish(rfd->rib_pending[afi]);
d62a17ae 597 rfd->rib_pending[afi] = NULL;
65efcfce 598
fe08ba7e
DS
599 if (rfd->rib[afi])
600 agg_table_finish(rfd->rib[afi]);
d62a17ae 601 rfd->rib[afi] = NULL;
65efcfce 602
fe08ba7e 603 /* NB agg_table_finish frees only prefix nodes, not chained
d62a17ae 604 * info */
fe08ba7e
DS
605 if (rfd->rsp_times[afi])
606 agg_table_finish(rfd->rsp_times[afi]);
d62a17ae 607 rfd->rib[afi] = NULL;
608 }
65efcfce
LB
609}
610
611/*
4b7e6066 612 * Copies struct bgp_path_info to struct rfapi_info, except for rk fields and un
65efcfce 613 */
40381db7 614static void rfapiRibBi2Ri(struct bgp_path_info *bpi, struct rfapi_info *ri,
d62a17ae 615 uint32_t lifetime)
65efcfce 616{
d62a17ae 617 struct bgp_attr_encap_subtlv *pEncap;
618
40381db7 619 ri->cost = rfapiRfpCost(bpi->attr);
d62a17ae 620 ri->lifetime = lifetime;
621
622 /* This loop based on rfapiRouteInfo2NextHopEntry() */
91ebf12c
DS
623 for (pEncap = bgp_attr_get_vnc_subtlvs(bpi->attr); pEncap;
624 pEncap = pEncap->next) {
d62a17ae 625 struct bgp_tea_options *hop;
626
627 switch (pEncap->type) {
628 case BGP_VNC_SUBTLV_TYPE_LIFETIME:
629 /* use configured lifetime, not attr lifetime */
630 break;
631
632 case BGP_VNC_SUBTLV_TYPE_RFPOPTION:
633 hop = XCALLOC(MTYPE_BGP_TEA_OPTIONS,
634 sizeof(struct bgp_tea_options));
635 assert(hop);
636 hop->type = pEncap->value[0];
637 hop->length = pEncap->value[1];
638 hop->value = XCALLOC(MTYPE_BGP_TEA_OPTIONS_VALUE,
639 pEncap->length - 2);
640 assert(hop->value);
641 memcpy(hop->value, pEncap->value + 2,
642 pEncap->length - 2);
643 if (hop->length > pEncap->length - 2) {
644 zlog_warn(
3efd0893 645 "%s: VNC subtlv length mismatch: RFP option says %d, attr says %d (shrinking)",
d62a17ae 646 __func__, hop->length,
647 pEncap->length - 2);
648 hop->length = pEncap->length - 2;
649 }
650 hop->next = ri->tea_options;
651 ri->tea_options = hop;
652 break;
653
654 default:
655 break;
656 }
657 }
658
659 rfapi_un_options_free(ri->un_options); /* maybe free old version */
40381db7 660 ri->un_options = rfapi_encap_tlv_to_un_option(bpi->attr);
d62a17ae 661
662 /*
663 * VN options
664 */
40381db7
DS
665 if (bpi->extra
666 && decode_rd_type(bpi->extra->vnc.import.rd.val)
d62a17ae 667 == RD_TYPE_VNC_ETH) {
668 /* ethernet route */
669
670 struct rfapi_vn_option *vo;
671
672 vo = XCALLOC(MTYPE_RFAPI_VN_OPTION,
673 sizeof(struct rfapi_vn_option));
674 assert(vo);
675
676 vo->type = RFAPI_VN_OPTION_TYPE_L2ADDR;
677
40381db7 678 /* copy from RD already stored in bpi, so we don't need it_node
d62a17ae 679 */
40381db7 680 memcpy(&vo->v.l2addr.macaddr, bpi->extra->vnc.import.rd.val + 2,
28328ea9 681 ETH_ALEN);
d62a17ae 682
b53e67a3 683 (void)rfapiEcommunityGetLNI(bgp_attr_get_ecommunity(bpi->attr),
8cea9547 684 &vo->v.l2addr.logical_net_id);
b53e67a3
DA
685 (void)rfapiEcommunityGetEthernetTag(
686 bgp_attr_get_ecommunity(bpi->attr),
687 &vo->v.l2addr.tag_id);
d62a17ae 688
689 /* local_nve_id comes from RD */
40381db7 690 vo->v.l2addr.local_nve_id = bpi->extra->vnc.import.rd.val[1];
d62a17ae 691
692 /* label comes from MP_REACH_NLRI label */
40381db7 693 vo->v.l2addr.label = decode_label(&bpi->extra->label[0]);
d62a17ae 694
695 rfapi_vn_options_free(
696 ri->vn_options); /* maybe free old version */
697 ri->vn_options = vo;
698 }
699
700 /*
701 * If there is an auxiliary IP address (L2 can have it), copy it
702 */
40381db7
DS
703 if (bpi->extra && bpi->extra->vnc.import.aux_prefix.family) {
704 ri->rk.aux_prefix = bpi->extra->vnc.import.aux_prefix;
d62a17ae 705 }
65efcfce
LB
706}
707
708/*
709 * rfapiRibPreloadBi
710 *
711 * Install route into NVE RIB model so as to be consistent with
712 * caller's response to rfapi_query().
713 *
714 * Also: return indication to caller whether this specific route
715 * should be included in the response to the NVE according to
716 * the following tests:
717 *
718 * 1. If there were prior duplicates of this route in this same
719 * query response, don't include the route.
720 *
721 * RETURN VALUE:
722 *
723 * 0 OK to include route in response
724 * !0 do not include route in response
725 */
d62a17ae 726int rfapiRibPreloadBi(
fe08ba7e 727 struct agg_node *rfd_rib_node, /* NULL = don't preload or filter */
d62a17ae 728 struct prefix *pfx_vn, struct prefix *pfx_un, uint32_t lifetime,
40381db7 729 struct bgp_path_info *bpi)
65efcfce 730{
d62a17ae 731 struct rfapi_descriptor *rfd;
732 struct skiplist *slRibPt = NULL;
733 struct rfapi_info *ori = NULL;
734 struct rfapi_rib_key rk;
fe08ba7e 735 struct agg_node *trn;
d62a17ae 736 afi_t afi;
26a3ffd6 737 const struct prefix *p = agg_node_get_prefix(rfd_rib_node);
d62a17ae 738
739 if (!rfd_rib_node)
740 return 0;
741
26a3ffd6 742 afi = family2afi(p->family);
d62a17ae 743
fe08ba7e 744 rfd = agg_get_table_info(agg_get_table(rfd_rib_node));
d62a17ae 745
746 memset((void *)&rk, 0, sizeof(rk));
747 rk.vn = *pfx_vn;
40381db7 748 rk.rd = bpi->extra->vnc.import.rd;
d62a17ae 749
750 /*
751 * If there is an auxiliary IP address (L2 can have it), copy it
752 */
40381db7
DS
753 if (bpi->extra->vnc.import.aux_prefix.family) {
754 rk.aux_prefix = bpi->extra->vnc.import.aux_prefix;
d62a17ae 755 }
756
757 /*
758 * is this route already in NVE's RIB?
759 */
760 slRibPt = (struct skiplist *)rfd_rib_node->info;
761
762 if (slRibPt && !skiplist_search(slRibPt, &rk, (void **)&ori)) {
763
764 if ((ori->rsp_counter == rfd->rsp_counter)
765 && (ori->last_sent_time == rfd->rsp_time)) {
766 return -1; /* duplicate in this response */
767 }
768
769 /* found: update contents of existing route in RIB */
770 ori->un = *pfx_un;
40381db7 771 rfapiRibBi2Ri(bpi, ori, lifetime);
d62a17ae 772 } else {
773 /* not found: add new route to RIB */
774 ori = rfapi_info_new();
775 ori->rk = rk;
776 ori->un = *pfx_un;
40381db7 777 rfapiRibBi2Ri(bpi, ori, lifetime);
d62a17ae 778
779 if (!slRibPt) {
780 slRibPt = skiplist_new(0, rfapi_rib_key_cmp, NULL);
781 rfd_rib_node->info = slRibPt;
fe08ba7e 782 agg_lock_node(rfd_rib_node);
d62a17ae 783 RFAPI_RIB_PREFIX_COUNT_INCR(rfd, rfd->bgp->rfapi);
784 }
785 skiplist_insert(slRibPt, &ori->rk, ori);
65efcfce
LB
786 }
787
d62a17ae 788 ori->last_sent_time = rfapi_time(NULL);
789
790 /*
791 * poke timer
792 */
793 RFAPI_RIB_CHECK_COUNTS(0, 0);
794 rfapiRibStartTimer(rfd, ori, rfd_rib_node, 0);
795 RFAPI_RIB_CHECK_COUNTS(0, 0);
796
797 /*
798 * Update last sent time for prefix
799 */
26a3ffd6 800 trn = agg_node_get(rfd->rsp_times[afi], p); /* locks trn */
d62a17ae 801 trn->info = (void *)(uintptr_t)bgp_clock();
c10e14e9 802 if (agg_node_get_lock_count(trn) > 1)
fe08ba7e 803 agg_unlock_node(trn);
d62a17ae 804
805 return 0;
65efcfce
LB
806}
807
808/*
809 * Frees rfapi_info items at node
810 *
811 * Adjust 'rib' and 'rib_pending' as follows:
812 *
813 * If rib_pending node->info is 1 (magic value):
814 * callback: NHL = RIB NHL with lifetime = withdraw_lifetime_value
815 * RIB = remove all routes at the node
816 * DONE
817 *
818 * For each item at rib node:
819 * if not present in pending node, move RIB item to "delete list"
820 *
821 * For each item at pending rib node:
822 * if present (same vn/un) in rib node with same lifetime & options, drop
823 * matching item from pending node
824 *
825 * For each remaining item at pending rib node, add or replace item
826 * at rib node.
827 *
828 * Construct NHL as concatenation of pending list + delete list
829 *
830 * Clear pending node
831 */
d62a17ae 832static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd,
833 afi_t afi,
fe08ba7e 834 struct agg_node *pn, /* pending node */
d62a17ae 835 struct rfapi_next_hop_entry **head,
836 struct rfapi_next_hop_entry **tail)
65efcfce 837{
d62a17ae 838 struct listnode *node = NULL;
839 struct listnode *nnode = NULL;
840 struct rfapi_info *ri = NULL; /* happy valgrind */
841 struct rfapi_ip_prefix hp = {0}; /* pfx to put in NHE */
fe08ba7e 842 struct agg_node *rn = NULL;
d62a17ae 843 struct skiplist *slRibPt = NULL; /* rib list */
844 struct skiplist *slPendPt = NULL;
845 struct list *lPendCost = NULL;
846 struct list *delete_list = NULL;
847 int printedprefix = 0;
d62a17ae 848 int rib_node_started_nonempty = 0;
849 int sendingsomeroutes = 0;
26a3ffd6 850 const struct prefix *p;
65efcfce 851#if DEBUG_PROCESS_PENDING_NODE
d62a17ae 852 unsigned int count_rib_initial = 0;
853 unsigned int count_pend_vn_initial = 0;
854 unsigned int count_pend_cost_initial = 0;
65efcfce
LB
855#endif
856
d62a17ae 857 assert(pn);
26a3ffd6
DS
858 p = agg_node_get_prefix(pn);
859 vnc_zlog_debug_verbose("%s: afi=%d, %pRN pn->info=%p", __func__, afi,
860 pn, pn->info);
65efcfce 861
d62a17ae 862 if (AFI_L2VPN != afi) {
26a3ffd6 863 rfapiQprefix2Rprefix(p, &hp);
d62a17ae 864 }
65efcfce 865
d62a17ae 866 RFAPI_RIB_CHECK_COUNTS(1, 0);
65efcfce 867
d62a17ae 868 /*
869 * Find corresponding RIB node
870 */
26a3ffd6 871 rn = agg_node_get(rfd->rib[afi], p); /* locks rn */
65efcfce 872
d62a17ae 873 /*
874 * RIB skiplist has key=rfapi_addr={vn,un}, val = rfapi_info,
875 * skiplist.del = NULL
876 */
877 slRibPt = (struct skiplist *)rn->info;
878 if (slRibPt)
879 rib_node_started_nonempty = 1;
65efcfce 880
d62a17ae 881 slPendPt = (struct skiplist *)(pn->aggregate);
882 lPendCost = (struct list *)(pn->info);
65efcfce
LB
883
884#if DEBUG_PROCESS_PENDING_NODE
d62a17ae 885 /* debugging */
886 if (slRibPt)
887 count_rib_initial = skiplist_count(slRibPt);
65efcfce 888
d62a17ae 889 if (slPendPt)
890 count_pend_vn_initial = skiplist_count(slPendPt);
65efcfce 891
d62a17ae 892 if (lPendCost && lPendCost != (struct list *)1)
893 count_pend_cost_initial = lPendCost->count;
65efcfce
LB
894#endif
895
896
d62a17ae 897 /*
898 * Handle special case: delete all routes at prefix
899 */
900 if (lPendCost == (struct list *)1) {
901 vnc_zlog_debug_verbose("%s: lPendCost=1 => delete all",
902 __func__);
903 if (slRibPt && !skiplist_empty(slRibPt)) {
904 delete_list = list_new();
905 while (0
906 == skiplist_first(slRibPt, NULL, (void **)&ri)) {
d62a17ae 907 listnode_add(delete_list, ri);
908 vnc_zlog_debug_verbose(
909 "%s: after listnode_add, delete_list->count=%d",
910 __func__, delete_list->count);
911 rfapiFreeBgpTeaOptionChain(ri->tea_options);
912 ri->tea_options = NULL;
913
914 if (ri->timer) {
915 struct rfapi_rib_tcb *tcb;
916
b3d6bc6e
MS
917 tcb = ri->timer->arg;
918 thread_cancel(&ri->timer);
d62a17ae 919 XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
d62a17ae 920 }
921
d62a17ae 922 vnc_zlog_debug_verbose(
2dbe669b
DA
923 "%s: put dl pfx=%pRN vn=%pFX un=%pFX cost=%d life=%d vn_options=%p",
924 __func__, pn, &ri->rk.vn, &ri->un,
925 ri->cost, ri->lifetime, ri->vn_options);
d62a17ae 926
927 skiplist_delete_first(slRibPt);
928 }
929
930 assert(skiplist_empty(slRibPt));
931
932 skiplist_free(slRibPt);
933 rn->info = slRibPt = NULL;
fe08ba7e 934 agg_unlock_node(rn);
d62a17ae 935
936 lPendCost = pn->info = NULL;
fe08ba7e 937 agg_unlock_node(pn);
d62a17ae 938
939 goto callback;
940 }
941 if (slRibPt) {
942 skiplist_free(slRibPt);
943 rn->info = NULL;
fe08ba7e 944 agg_unlock_node(rn);
d62a17ae 945 }
946
947 assert(!slPendPt);
948 if (slPendPt) { /* TBD I think we can toss this block */
949 skiplist_free(slPendPt);
950 pn->aggregate = NULL;
fe08ba7e 951 agg_unlock_node(pn);
d62a17ae 952 }
953
954 pn->info = NULL;
fe08ba7e 955 agg_unlock_node(pn);
d62a17ae 956
fe08ba7e 957 agg_unlock_node(rn); /* agg_node_get() */
d62a17ae 958
959 if (rib_node_started_nonempty) {
960 RFAPI_RIB_PREFIX_COUNT_DECR(rfd, bgp->rfapi);
961 }
962
963 RFAPI_RIB_CHECK_COUNTS(1, 0);
964
965 return;
966 }
967
968 vnc_zlog_debug_verbose("%s: lPendCost->count=%d, slRibPt->count=%d",
969 __func__,
970 (lPendCost ? (int)lPendCost->count : -1),
971 (slRibPt ? (int)slRibPt->count : -1));
972
973 /*
974 * Iterate over routes at RIB Node.
975 * If not found at Pending Node, delete from RIB Node and add to
976 * deletelist
977 * If found at Pending Node
978 * If identical rfapi_info, delete from Pending Node
979 */
980 if (slRibPt) {
981 void *cursor = NULL;
982 struct rfapi_info *ori;
983
984 /*
985 * Iterate over RIB List
986 *
987 */
988 while (!skiplist_next(slRibPt, NULL, (void **)&ori, &cursor)) {
989
990 if (skiplist_search(slPendPt, &ori->rk, (void **)&ri)) {
991 /*
992 * Not in Pending list, so it should be deleted
993 */
994 if (!delete_list)
995 delete_list = list_new();
996 listnode_add(delete_list, ori);
997 rfapiFreeBgpTeaOptionChain(ori->tea_options);
998 ori->tea_options = NULL;
999 if (ori->timer) {
1000 struct rfapi_rib_tcb *tcb;
1001
b3d6bc6e
MS
1002 tcb = ori->timer->arg;
1003 thread_cancel(&ori->timer);
d62a17ae 1004 XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
d62a17ae 1005 }
65efcfce
LB
1006
1007#if DEBUG_PROCESS_PENDING_NODE
d62a17ae 1008 /* deleted from slRibPt below, after we're done
1009 * iterating */
1010 vnc_zlog_debug_verbose(
1011 "%s: slRibPt ri %p not matched in pending list, delete",
1012 __func__, ori);
65efcfce
LB
1013#endif
1014
d62a17ae 1015 } else {
1016 /*
1017 * Found in pending list. If same lifetime,
1018 * cost, options,
1019 * then remove from pending list because the
1020 * route
1021 * hasn't changed.
1022 */
1023 if (!rfapi_info_cmp(ori, ri)) {
1024 skiplist_delete(slPendPt, &ri->rk,
1025 NULL);
1026 assert(lPendCost);
1027 if (lPendCost) {
1028 /* linear walk: might need
1029 * optimization */
1030 listnode_delete(lPendCost,
1031 ri); /* XXX
1032 doesn't
1033 free
1034 data!
1035 bug? */
1036 rfapi_info_free(
1037 ri); /* grr... */
1038 }
1039 }
65efcfce 1040#if DEBUG_PROCESS_PENDING_NODE
d62a17ae 1041 vnc_zlog_debug_verbose(
1042 "%s: slRibPt ri %p matched in pending list, %s",
1043 __func__, ori,
1044 (same ? "same info"
1045 : "different info"));
65efcfce 1046#endif
d62a17ae 1047 }
1048 }
1049 /*
1050 * Go back and delete items from RIB
1051 */
1052 if (delete_list) {
1053 for (ALL_LIST_ELEMENTS_RO(delete_list, node, ri)) {
1054 vnc_zlog_debug_verbose(
1055 "%s: deleting ri %p from slRibPt",
1056 __func__, ri);
1057 assert(!skiplist_delete(slRibPt, &ri->rk,
1058 NULL));
1059 }
1060 if (skiplist_empty(slRibPt)) {
1061 skiplist_free(slRibPt);
1062 slRibPt = rn->info = NULL;
fe08ba7e 1063 agg_unlock_node(rn);
d62a17ae 1064 }
1065 }
1066 }
1067
1068 RFAPI_RIB_CHECK_COUNTS(0, (delete_list ? delete_list->count : 0));
1069
1070 /*
1071 * Iterate over routes at Pending Node
1072 *
1073 * If {vn} found at RIB Node, update RIB Node route contents to match PN
1074 * If {vn} NOT found at RIB Node, add copy to RIB Node
1075 */
1076 if (lPendCost) {
1077 for (ALL_LIST_ELEMENTS_RO(lPendCost, node, ri)) {
1078
1079 struct rfapi_info *ori;
1080
1081 if (slRibPt
1082 && !skiplist_search(slRibPt, &ri->rk,
1083 (void **)&ori)) {
1084
1085 /* found: update contents of existing route in
1086 * RIB */
1087 ori->un = ri->un;
1088 ori->cost = ri->cost;
1089 ori->lifetime = ri->lifetime;
1090 rfapiFreeBgpTeaOptionChain(ori->tea_options);
1091 ori->tea_options =
1092 rfapiOptionsDup(ri->tea_options);
1093 ori->last_sent_time = rfapi_time(NULL);
1094
1095 rfapiFreeRfapiVnOptionChain(ori->vn_options);
1096 ori->vn_options =
1097 rfapiVnOptionsDup(ri->vn_options);
1098
1099 rfapiFreeRfapiUnOptionChain(ori->un_options);
1100 ori->un_options =
1101 rfapiUnOptionsDup(ri->un_options);
1102
1103 vnc_zlog_debug_verbose(
1104 "%s: matched lPendCost item %p in slRibPt, rewrote",
1105 __func__, ri);
1106
1107 } else {
1108
06b9f471 1109 char buf_rd[RD_ADDRSTRLEN];
d62a17ae 1110
1111 /* not found: add new route to RIB */
1112 ori = rfapi_info_new();
1113 ori->rk = ri->rk;
1114 ori->un = ri->un;
1115 ori->cost = ri->cost;
1116 ori->lifetime = ri->lifetime;
1117 ori->tea_options =
1118 rfapiOptionsDup(ri->tea_options);
1119 ori->last_sent_time = rfapi_time(NULL);
1120 ori->vn_options =
1121 rfapiVnOptionsDup(ri->vn_options);
1122 ori->un_options =
1123 rfapiUnOptionsDup(ri->un_options);
1124
1125 if (!slRibPt) {
1126 slRibPt = skiplist_new(
1127 0, rfapi_rib_key_cmp, NULL);
1128 rn->info = slRibPt;
fe08ba7e 1129 agg_lock_node(rn);
d62a17ae 1130 }
1131 skiplist_insert(slRibPt, &ori->rk, ori);
65efcfce
LB
1132
1133#if DEBUG_RIB_SL_RD
d62a17ae 1134 prefix_rd2str(&ori->rk.rd, buf_rd,
1135 sizeof(buf_rd));
65efcfce 1136#else
d62a17ae 1137 buf_rd[0] = 0;
65efcfce
LB
1138#endif
1139
d62a17ae 1140 vnc_zlog_debug_verbose(
1141 "%s: nomatch lPendCost item %p in slRibPt, added (rd=%s)",
1142 __func__, ri, buf_rd);
1143 }
1144
1145 /*
1146 * poke timer
1147 */
1148 RFAPI_RIB_CHECK_COUNTS(
1149 0, (delete_list ? delete_list->count : 0));
1150 rfapiRibStartTimer(rfd, ori, rn, 0);
1151 RFAPI_RIB_CHECK_COUNTS(
1152 0, (delete_list ? delete_list->count : 0));
1153 }
1154 }
65efcfce
LB
1155
1156
1157callback:
d62a17ae 1158 /*
1159 * Construct NHL as concatenation of pending list + delete list
1160 */
1161
1162
1163 RFAPI_RIB_CHECK_COUNTS(0, (delete_list ? delete_list->count : 0));
1164
1165 if (lPendCost) {
1166
1167 char buf[BUFSIZ];
1168 char buf2[BUFSIZ];
1169
1170 vnc_zlog_debug_verbose("%s: lPendCost->count now %d", __func__,
1171 lPendCost->count);
26a3ffd6 1172 vnc_zlog_debug_verbose("%s: For prefix %pRN (a)", __func__, pn);
d62a17ae 1173 printedprefix = 1;
1174
1175 for (ALL_LIST_ELEMENTS(lPendCost, node, nnode, ri)) {
1176
1177 struct rfapi_next_hop_entry *new;
fe08ba7e 1178 struct agg_node *trn;
d62a17ae 1179
1180 new = XCALLOC(MTYPE_RFAPI_NEXTHOP,
1181 sizeof(struct rfapi_next_hop_entry));
1182 assert(new);
1183
1184 if (ri->rk.aux_prefix.family) {
1185 rfapiQprefix2Rprefix(&ri->rk.aux_prefix,
1186 &new->prefix);
1187 } else {
1188 new->prefix = hp;
1189 if (AFI_L2VPN == afi) {
1190 /* hp is 0; need to set length to match
1191 * AF of vn */
1192 new->prefix.length =
1193 (ri->rk.vn.family == AF_INET)
1194 ? 32
1195 : 128;
1196 }
1197 }
1198 new->prefix.cost = ri->cost;
1199 new->lifetime = ri->lifetime;
1200 rfapiQprefix2Raddr(&ri->rk.vn, &new->vn_address);
1201 rfapiQprefix2Raddr(&ri->un, &new->un_address);
1202 /* free option chain from ri */
1203 rfapiFreeBgpTeaOptionChain(ri->tea_options);
1204
1205 ri->tea_options =
1206 NULL; /* option chain was transferred to NHL */
1207
1208 new->vn_options = ri->vn_options;
1209 ri->vn_options =
1210 NULL; /* option chain was transferred to NHL */
1211
1212 new->un_options = ri->un_options;
1213 ri->un_options =
1214 NULL; /* option chain was transferred to NHL */
1215
1216 if (*tail)
1217 (*tail)->next = new;
1218 *tail = new;
1219 if (!*head) {
1220 *head = new;
1221 }
1222 sendingsomeroutes = 1;
1223
1224 ++rfd->stat_count_nh_reachable;
1225 ++bgp->rfapi->stat.count_updated_response_updates;
1226
1227 /*
1228 * update this NVE's timestamp for this prefix
1229 */
fe08ba7e 1230 trn = agg_node_get(rfd->rsp_times[afi],
26a3ffd6 1231 p); /* locks trn */
d62a17ae 1232 trn->info = (void *)(uintptr_t)bgp_clock();
c10e14e9 1233 if (agg_node_get_lock_count(trn) > 1)
fe08ba7e 1234 agg_unlock_node(trn);
d62a17ae 1235
1236 rfapiRfapiIpAddr2Str(&new->vn_address, buf, BUFSIZ);
1237 rfapiRfapiIpAddr2Str(&new->un_address, buf2, BUFSIZ);
1238 vnc_zlog_debug_verbose(
1239 "%s: add vn=%s un=%s cost=%d life=%d",
1240 __func__, buf, buf2, new->prefix.cost,
1241 new->lifetime);
1242 }
1243 }
1244
1245 RFAPI_RIB_CHECK_COUNTS(0, (delete_list ? delete_list->count : 0));
1246
1247 if (delete_list) {
1248
1249 char buf[BUFSIZ];
1250 char buf2[BUFSIZ];
1251
1252 if (!printedprefix) {
26a3ffd6
DS
1253 vnc_zlog_debug_verbose("%s: For prefix %pRN (d)",
1254 __func__, pn);
d62a17ae 1255 }
1256 vnc_zlog_debug_verbose("%s: delete_list has %d elements",
1257 __func__, delete_list->count);
1258
1259 RFAPI_RIB_CHECK_COUNTS(0, delete_list->count);
1260 if (!CHECK_FLAG(bgp->rfapi_cfg->flags,
1261 BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE)) {
1262
1263 for (ALL_LIST_ELEMENTS(delete_list, node, nnode, ri)) {
1264
1265 struct rfapi_next_hop_entry *new;
1266 struct rfapi_info *ri_del;
1267
1268 RFAPI_RIB_CHECK_COUNTS(0, delete_list->count);
1269 new = XCALLOC(
1270 MTYPE_RFAPI_NEXTHOP,
1271 sizeof(struct rfapi_next_hop_entry));
1272 assert(new);
1273
1274 if (ri->rk.aux_prefix.family) {
1275 rfapiQprefix2Rprefix(&ri->rk.aux_prefix,
1276 &new->prefix);
1277 } else {
1278 new->prefix = hp;
1279 if (AFI_L2VPN == afi) {
1280 /* hp is 0; need to set length
1281 * to match AF of vn */
1282 new->prefix.length =
1283 (ri->rk.vn.family
1284 == AF_INET)
1285 ? 32
1286 : 128;
1287 }
1288 }
1289
1290 new->prefix.cost = ri->cost;
1291 new->lifetime = RFAPI_REMOVE_RESPONSE_LIFETIME;
1292 rfapiQprefix2Raddr(&ri->rk.vn,
1293 &new->vn_address);
1294 rfapiQprefix2Raddr(&ri->un, &new->un_address);
1295
1296 new->vn_options = ri->vn_options;
1297 ri->vn_options = NULL; /* option chain was
1298 transferred to NHL */
1299
1300 new->un_options = ri->un_options;
1301 ri->un_options = NULL; /* option chain was
1302 transferred to NHL */
1303
1304 if (*tail)
1305 (*tail)->next = new;
1306 *tail = new;
1307 if (!*head) {
1308 *head = new;
1309 }
1310 ++rfd->stat_count_nh_removal;
1311 ++bgp->rfapi->stat
1312 .count_updated_response_deletes;
1313
1314 rfapiRfapiIpAddr2Str(&new->vn_address, buf,
1315 BUFSIZ);
1316 rfapiRfapiIpAddr2Str(&new->un_address, buf2,
1317 BUFSIZ);
1318 vnc_zlog_debug_verbose(
1319 "%s: DEL vn=%s un=%s cost=%d life=%d",
1320 __func__, buf, buf2, new->prefix.cost,
1321 new->lifetime);
1322
1323 RFAPI_RIB_CHECK_COUNTS(0, delete_list->count);
1324 /*
1325 * Update/add to list of recent deletions at
1326 * this prefix
1327 */
1328 if (!rn->aggregate) {
1329 rn->aggregate = skiplist_new(
1330 0, rfapi_rib_key_cmp,
1331 (void (*)(void *))
1332 rfapi_info_free);
fe08ba7e 1333 agg_lock_node(rn);
d62a17ae 1334 }
1335 RFAPI_RIB_CHECK_COUNTS(0, delete_list->count);
1336
1337 /* sanity check lifetime */
1338 if (ri->lifetime
1339 > RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY)
1340 ri->lifetime =
1341 RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY;
1342
1343 RFAPI_RIB_CHECK_COUNTS(0, delete_list->count);
1344 /* cancel normal expire timer */
1345 if (ri->timer) {
1346 struct rfapi_rib_tcb *tcb;
1347
b3d6bc6e
MS
1348 tcb = ri->timer->arg;
1349 thread_cancel(&ri->timer);
d62a17ae 1350 XFREE(MTYPE_RFAPI_RECENT_DELETE, tcb);
d62a17ae 1351 }
1352 RFAPI_RIB_CHECK_COUNTS(0, delete_list->count);
1353
1354 /*
1355 * Look in "recently-deleted" list
1356 */
1357 if (skiplist_search(
1358 (struct skiplist *)(rn->aggregate),
1359 &ri->rk, (void **)&ri_del)) {
1360
1361 int rc;
1362
1363 RFAPI_RIB_CHECK_COUNTS(
1364 0, delete_list->count);
1365 /*
1366 * NOT in "recently-deleted" list
1367 */
1368 list_delete_node(
1369 delete_list,
1370 node); /* does not free ri */
1371 rc = skiplist_insert(
1372 (struct skiplist
1373 *)(rn->aggregate),
1374 &ri->rk, ri);
1375 assert(!rc);
1376
1377 RFAPI_RIB_CHECK_COUNTS(
1378 0, delete_list->count);
1379 rfapiRibStartTimer(rfd, ri, rn, 1);
1380 RFAPI_RIB_CHECK_COUNTS(
1381 0, delete_list->count);
1382 ri->last_sent_time = rfapi_time(NULL);
65efcfce 1383#if DEBUG_RIB_SL_RD
d62a17ae 1384 {
06b9f471
DS
1385 char buf_rd[RD_ADDRSTRLEN];
1386
d62a17ae 1387 vnc_zlog_debug_verbose(
1388 "%s: move route to recently deleted list, rd=%s",
06b9f471 1389 __func__,
996c9314
LB
1390 prefix_rd2str(
1391 &ri->rk.rd,
1392 buf_rd,
1393 sizeof(buf_rd)));
d62a17ae 1394 }
65efcfce
LB
1395#endif
1396
d62a17ae 1397 } else {
1398 /*
1399 * IN "recently-deleted" list
1400 */
1401 RFAPI_RIB_CHECK_COUNTS(
1402 0, delete_list->count);
1403 rfapiRibStartTimer(rfd, ri_del, rn, 1);
1404 RFAPI_RIB_CHECK_COUNTS(
1405 0, delete_list->count);
1406 ri->last_sent_time = rfapi_time(NULL);
1407 }
1408 }
1409 } else {
1410 vnc_zlog_debug_verbose(
1411 "%s: response removal disabled, omitting removals",
1412 __func__);
1413 }
1414
1415 delete_list->del = (void (*)(void *))rfapi_info_free;
6a154c88 1416 list_delete(&delete_list);
d62a17ae 1417 }
1418
1419 RFAPI_RIB_CHECK_COUNTS(0, 0);
1420
1421 /*
fe08ba7e 1422 * Reset pending lists. The final agg_unlock_node() will probably
d62a17ae 1423 * cause the pending node to be released.
1424 */
1425 if (slPendPt) {
1426 skiplist_free(slPendPt);
1427 pn->aggregate = NULL;
fe08ba7e 1428 agg_unlock_node(pn);
d62a17ae 1429 }
1430 if (lPendCost) {
6a154c88 1431 list_delete(&lPendCost);
d62a17ae 1432 pn->info = NULL;
fe08ba7e 1433 agg_unlock_node(pn);
d62a17ae 1434 }
1435 RFAPI_RIB_CHECK_COUNTS(0, 0);
1436
1437 if (rib_node_started_nonempty) {
1438 if (!rn->info) {
1439 RFAPI_RIB_PREFIX_COUNT_DECR(rfd, bgp->rfapi);
1440 }
1441 } else {
1442 if (rn->info) {
1443 RFAPI_RIB_PREFIX_COUNT_INCR(rfd, bgp->rfapi);
1444 }
1445 }
1446
1447 if (sendingsomeroutes)
26a3ffd6 1448 rfapiMonitorTimersRestart(rfd, p);
d62a17ae 1449
fe08ba7e 1450 agg_unlock_node(rn); /* agg_node_get() */
d62a17ae 1451
1452 RFAPI_RIB_CHECK_COUNTS(1, 0);
65efcfce
LB
1453}
1454
1455/*
1456 * regardless of targets, construct a single callback by doing
1457 * only one traversal of the pending RIB
1458 *
1459 *
1460 * Do callback
1461 *
1462 */
d62a17ae 1463static void rib_do_callback_onepass(struct rfapi_descriptor *rfd, afi_t afi)
65efcfce 1464{
d62a17ae 1465 struct bgp *bgp = bgp_get_default();
1466 struct rfapi_next_hop_entry *head = NULL;
1467 struct rfapi_next_hop_entry *tail = NULL;
fe08ba7e 1468 struct agg_node *rn;
65efcfce 1469
1e20238a 1470#ifdef DEBUG_L2_EXTRA
d62a17ae 1471 vnc_zlog_debug_verbose("%s: rfd=%p, afi=%d", __func__, rfd, afi);
65efcfce
LB
1472#endif
1473
d62a17ae 1474 if (!rfd->rib_pending[afi])
1475 return;
65efcfce 1476
d62a17ae 1477 assert(bgp->rfapi);
65efcfce 1478
fe08ba7e
DS
1479 for (rn = agg_route_top(rfd->rib_pending[afi]); rn;
1480 rn = agg_route_next(rn)) {
d62a17ae 1481 process_pending_node(bgp, rfd, afi, rn, &head, &tail);
1482 }
65efcfce 1483
d62a17ae 1484 if (head) {
1485 rfapi_response_cb_t *f;
65efcfce
LB
1486
1487#if DEBUG_NHL
d62a17ae 1488 vnc_zlog_debug_verbose("%s: response callback NHL follows:",
1489 __func__);
1490 rfapiPrintNhl(NULL, head);
65efcfce
LB
1491#endif
1492
d62a17ae 1493 if (rfd->response_cb)
1494 f = rfd->response_cb;
1495 else
1496 f = bgp->rfapi->rfp_methods.response_cb;
1497
1498 bgp->rfapi->flags |= RFAPI_INCALLBACK;
1499 vnc_zlog_debug_verbose("%s: invoking updated response callback",
1500 __func__);
1501 (*f)(head, rfd->cookie);
1502 bgp->rfapi->flags &= ~RFAPI_INCALLBACK;
1503 ++bgp->rfapi->response_updated_count;
1504 }
65efcfce
LB
1505}
1506
d62a17ae 1507static wq_item_status rfapiRibDoQueuedCallback(struct work_queue *wq,
1508 void *data)
65efcfce 1509{
d62a17ae 1510 struct rfapi_descriptor *rfd;
1511 afi_t afi;
1512 uint32_t queued_flag;
65efcfce 1513
d62a17ae 1514 RFAPI_RIB_CHECK_COUNTS(1, 0);
65efcfce 1515
d62a17ae 1516 rfd = ((struct rfapi_updated_responses_queue *)data)->rfd;
1517 afi = ((struct rfapi_updated_responses_queue *)data)->afi;
65efcfce 1518
d62a17ae 1519 /* Make sure the HD wasn't closed after the work item was scheduled */
1520 if (rfapi_check(rfd))
1521 return WQ_SUCCESS;
65efcfce 1522
d62a17ae 1523 rib_do_callback_onepass(rfd, afi);
65efcfce 1524
d62a17ae 1525 queued_flag = RFAPI_QUEUED_FLAG(afi);
65efcfce 1526
d62a17ae 1527 UNSET_FLAG(rfd->flags, queued_flag);
65efcfce 1528
d62a17ae 1529 RFAPI_RIB_CHECK_COUNTS(1, 0);
65efcfce 1530
d62a17ae 1531 return WQ_SUCCESS;
65efcfce
LB
1532}
1533
d62a17ae 1534static void rfapiRibQueueItemDelete(struct work_queue *wq, void *data)
65efcfce 1535{
d62a17ae 1536 XFREE(MTYPE_RFAPI_UPDATED_RESPONSE_QUEUE, data);
65efcfce
LB
1537}
1538
d62a17ae 1539static void updated_responses_queue_init(struct rfapi_descriptor *rfd)
65efcfce 1540{
d62a17ae 1541 if (rfd->updated_responses_queue)
1542 return;
1543
1544 rfd->updated_responses_queue =
1545 work_queue_new(bm->master, "rfapi updated responses");
1546 assert(rfd->updated_responses_queue);
1547
1548 rfd->updated_responses_queue->spec.workfunc = rfapiRibDoQueuedCallback;
1549 rfd->updated_responses_queue->spec.del_item_data =
1550 rfapiRibQueueItemDelete;
1551 rfd->updated_responses_queue->spec.max_retries = 0;
1552 rfd->updated_responses_queue->spec.hold = 1;
65efcfce
LB
1553}
1554
1555/*
1556 * Called when an import table node is modified. Construct a
1557 * new complete nexthop list, sorted by cost (lowest first),
1558 * based on the import table node.
1559 *
1560 * Filter out duplicate nexthops (vn address). There should be
1561 * only one UN address per VN address from the point of view of
1562 * a given import table, so we can probably ignore UN addresses
1563 * while filtering.
1564 *
1565 * Based on rfapiNhlAddNodeRoutes()
1566 */
d62a17ae 1567void rfapiRibUpdatePendingNode(
1568 struct bgp *bgp, struct rfapi_descriptor *rfd,
1569 struct rfapi_import_table *it, /* needed for L2 */
fe08ba7e 1570 struct agg_node *it_node, uint32_t lifetime)
65efcfce 1571{
26a3ffd6 1572 const struct prefix *prefix;
40381db7 1573 struct bgp_path_info *bpi;
fe08ba7e 1574 struct agg_node *pn;
d62a17ae 1575 afi_t afi;
1576 uint32_t queued_flag;
1577 int count = 0;
d62a17ae 1578
1579 vnc_zlog_debug_verbose("%s: entry", __func__);
1580
1581 if (CHECK_FLAG(bgp->rfapi_cfg->flags, BGP_VNC_CONFIG_CALLBACK_DISABLE))
1582 return;
1583
1584 vnc_zlog_debug_verbose("%s: callbacks are not disabled", __func__);
1585
1586 RFAPI_RIB_CHECK_COUNTS(1, 0);
1587
26a3ffd6 1588 prefix = agg_node_get_prefix(it_node);
d62a17ae 1589 afi = family2afi(prefix->family);
2dbe669b 1590 vnc_zlog_debug_verbose("%s: prefix=%pFX", __func__, prefix);
d62a17ae 1591
fe08ba7e 1592 pn = agg_node_get(rfd->rib_pending[afi], prefix);
d62a17ae 1593 assert(pn);
1594
1595 vnc_zlog_debug_verbose("%s: pn->info=%p, pn->aggregate=%p", __func__,
1596 pn->info, pn->aggregate);
1597
1598 if (pn->aggregate) {
1599 /*
1600 * free references into the rfapi_info structures before
1601 * freeing the structures themselves
1602 */
1603 skiplist_free((struct skiplist *)(pn->aggregate));
1604 pn->aggregate = NULL;
fe08ba7e 1605 agg_unlock_node(pn); /* skiplist deleted */
d62a17ae 1606 }
1607
1608
1609 /*
1610 * free the rfapi_info structures
1611 */
1612 if (pn->info) {
1613 if (pn->info != (void *)1) {
6a154c88 1614 list_delete((struct list **)(&pn->info));
d62a17ae 1615 }
1616 pn->info = NULL;
fe08ba7e 1617 agg_unlock_node(pn); /* linklist or 1 deleted */
d62a17ae 1618 }
1619
1620 /*
40381db7 1621 * The BPIs in the import table are already sorted by cost
d62a17ae 1622 */
40381db7 1623 for (bpi = it_node->info; bpi; bpi = bpi->next) {
d62a17ae 1624
1625 struct rfapi_info *ri;
1626 struct prefix pfx_nh;
1627
40381db7 1628 if (!bpi->extra) {
d62a17ae 1629 /* shouldn't happen */
1630 /* TBD increment error stats counter */
1631 continue;
1632 }
1633
40381db7 1634 rfapiNexthop2Prefix(bpi->attr, &pfx_nh);
d62a17ae 1635
1636 /*
1637 * Omit route if nexthop is self
1638 */
1639 if (CHECK_FLAG(bgp->rfapi_cfg->flags,
1640 BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP)) {
1641
1642 struct prefix pfx_vn;
1643
cbb65f5e 1644 assert(!rfapiRaddr2Qprefix(&rfd->vn_addr, &pfx_vn));
d62a17ae 1645 if (prefix_same(&pfx_vn, &pfx_nh))
1646 continue;
1647 }
1648
1649 ri = rfapi_info_new();
1650 ri->rk.vn = pfx_nh;
40381db7 1651 ri->rk.rd = bpi->extra->vnc.import.rd;
d62a17ae 1652 /*
1653 * If there is an auxiliary IP address (L2 can have it), copy it
1654 */
40381db7
DS
1655 if (bpi->extra->vnc.import.aux_prefix.family) {
1656 ri->rk.aux_prefix = bpi->extra->vnc.import.aux_prefix;
d62a17ae 1657 }
1658
40381db7 1659 if (rfapiGetUnAddrOfVpnBi(bpi, &ri->un)) {
d62a17ae 1660 rfapi_info_free(ri);
1661 continue;
1662 }
1663
1664 if (!pn->aggregate) {
1665 pn->aggregate =
1666 skiplist_new(0, rfapi_rib_key_cmp, NULL);
fe08ba7e 1667 agg_lock_node(pn);
d62a17ae 1668 }
1669
1670 /*
1671 * If we have already added this nexthop, the insert will fail.
1672 * Note that the skiplist key is a pointer INTO the rfapi_info
1673 * structure which will be added to the "info" list.
1674 * The skiplist entry VALUE is not used for anything but
1675 * might be useful during debugging.
1676 */
1677 if (skiplist_insert((struct skiplist *)pn->aggregate, &ri->rk,
1678 ri)) {
1679
1680 /*
1681 * duplicate
1682 */
1683 rfapi_info_free(ri);
1684 continue;
1685 }
1686
40381db7 1687 rfapiRibBi2Ri(bpi, ri, lifetime);
d62a17ae 1688
1689 if (!pn->info) {
1690 pn->info = list_new();
1691 ((struct list *)(pn->info))->del =
1692 (void (*)(void *))rfapi_info_free;
fe08ba7e 1693 agg_lock_node(pn);
d62a17ae 1694 }
1695
1696 listnode_add((struct list *)(pn->info), ri);
1697 }
1698
1699 if (pn->info) {
1700 count = ((struct list *)(pn->info))->count;
1701 }
1702
1703 if (!count) {
1704 assert(!pn->info);
1705 assert(!pn->aggregate);
1706 pn->info = (void *)1; /* magic value means this node has no
1707 routes */
fe08ba7e 1708 agg_lock_node(pn);
d62a17ae 1709 }
1710
fe08ba7e 1711 agg_unlock_node(pn); /* agg_node_get */
d62a17ae 1712
1713 queued_flag = RFAPI_QUEUED_FLAG(afi);
1714
1715 if (!CHECK_FLAG(rfd->flags, queued_flag)) {
1716
1717 struct rfapi_updated_responses_queue *urq;
1718
1719 urq = XCALLOC(MTYPE_RFAPI_UPDATED_RESPONSE_QUEUE,
1720 sizeof(struct rfapi_updated_responses_queue));
1721 assert(urq);
1722 if (!rfd->updated_responses_queue)
1723 updated_responses_queue_init(rfd);
1724
1725 SET_FLAG(rfd->flags, queued_flag);
1726 urq->rfd = rfd;
1727 urq->afi = afi;
1728 work_queue_add(rfd->updated_responses_queue, urq);
1729 }
1730 RFAPI_RIB_CHECK_COUNTS(1, 0);
65efcfce
LB
1731}
1732
d62a17ae 1733void rfapiRibUpdatePendingNodeSubtree(
1734 struct bgp *bgp, struct rfapi_descriptor *rfd,
fe08ba7e
DS
1735 struct rfapi_import_table *it, struct agg_node *it_node,
1736 struct agg_node *omit_subtree, /* may be NULL */
d62a17ae 1737 uint32_t lifetime)
65efcfce 1738{
d62a17ae 1739 /* FIXME: need to find a better way here to work without sticking our
1740 * hands in node->link */
fe08ba7e
DS
1741 if (agg_node_left(it_node)
1742 && (agg_node_left(it_node) != omit_subtree)) {
1743 if (agg_node_left(it_node)->info)
1744 rfapiRibUpdatePendingNode(
1745 bgp, rfd, it, agg_node_left(it_node), lifetime);
1746 rfapiRibUpdatePendingNodeSubtree(bgp, rfd, it,
1747 agg_node_left(it_node),
d62a17ae 1748 omit_subtree, lifetime);
1749 }
1750
fe08ba7e
DS
1751 if (agg_node_right(it_node)
1752 && (agg_node_right(it_node) != omit_subtree)) {
1753 if (agg_node_right(it_node)->info)
d62a17ae 1754 rfapiRibUpdatePendingNode(bgp, rfd, it,
fe08ba7e
DS
1755 agg_node_right(it_node),
1756 lifetime);
1757 rfapiRibUpdatePendingNodeSubtree(bgp, rfd, it,
1758 agg_node_right(it_node),
d62a17ae 1759 omit_subtree, lifetime);
1760 }
65efcfce
LB
1761}
1762
1763/*
1764 * RETURN VALUE
1765 *
1766 * 0 allow prefix to be included in response
1767 * !0 don't allow prefix to be included in response
1768 */
d62a17ae 1769int rfapiRibFTDFilterRecentPrefix(
1770 struct rfapi_descriptor *rfd,
fe08ba7e 1771 struct agg_node *it_rn, /* import table node */
d62a17ae 1772 struct prefix *pfx_target_original) /* query target */
65efcfce 1773{
d62a17ae 1774 struct bgp *bgp = rfd->bgp;
26a3ffd6
DS
1775 const struct prefix *p = agg_node_get_prefix(it_rn);
1776 afi_t afi = family2afi(p->family);
d62a17ae 1777 time_t prefix_time;
fe08ba7e 1778 struct agg_node *trn;
d62a17ae 1779
1780 /*
1781 * Not in FTD mode, so allow prefix
1782 */
1783 if (bgp->rfapi_cfg->rfp_cfg.download_type != RFAPI_RFP_DOWNLOAD_FULL)
1784 return 0;
1785
1786 /*
1787 * TBD
1788 * This matches behavior of now-obsolete rfapiRibFTDFilterRecent(),
1789 * but we need to decide if that is correct.
1790 */
26a3ffd6 1791 if (p->family == AF_ETHERNET)
d62a17ae 1792 return 0;
65efcfce 1793
1e20238a 1794#ifdef DEBUG_FTD_FILTER_RECENT
d62a17ae 1795 {
2dbe669b
DA
1796 vnc_zlog_debug_verbose("%s: prefix %pFX", __func__,
1797 agg_node_get_prefix(it_rn));
d62a17ae 1798 }
65efcfce
LB
1799#endif
1800
d62a17ae 1801 /*
1802 * prefix covers target address, so allow prefix
1803 */
26a3ffd6 1804 if (prefix_match(p, pfx_target_original)) {
1e20238a 1805#ifdef DEBUG_FTD_FILTER_RECENT
d62a17ae 1806 vnc_zlog_debug_verbose("%s: prefix covers target, allowed",
1807 __func__);
65efcfce 1808#endif
d62a17ae 1809 return 0;
1810 }
65efcfce 1811
d62a17ae 1812 /*
1813 * check this NVE's timestamp for this prefix
1814 */
26a3ffd6 1815 trn = agg_node_get(rfd->rsp_times[afi], p); /* locks trn */
d62a17ae 1816 prefix_time = (time_t)trn->info;
c10e14e9 1817 if (agg_node_get_lock_count(trn) > 1)
fe08ba7e 1818 agg_unlock_node(trn);
65efcfce 1819
1e20238a 1820#ifdef DEBUG_FTD_FILTER_RECENT
d62a17ae 1821 vnc_zlog_debug_verbose("%s: last sent time %lu, last allowed time %lu",
1822 __func__, prefix_time,
1823 rfd->ftd_last_allowed_time);
65efcfce
LB
1824#endif
1825
d62a17ae 1826 /*
1827 * haven't sent this prefix, which doesn't cover target address,
1828 * to NVE since ftd_advertisement_interval, so OK to send now.
1829 */
1830 if (prefix_time <= rfd->ftd_last_allowed_time)
1831 return 0;
65efcfce 1832
d62a17ae 1833 return 1;
65efcfce
LB
1834}
1835
1836/*
1837 * Call when rfapi returns from rfapi_query() so the RIB reflects
1838 * the routes sent to the NVE before the first updated response
1839 *
1840 * Also: remove duplicates from response. Caller should use returned
1841 * value of nexthop chain.
1842 */
1843struct rfapi_next_hop_entry *
d62a17ae 1844rfapiRibPreload(struct bgp *bgp, struct rfapi_descriptor *rfd,
1845 struct rfapi_next_hop_entry *response, int use_eth_resolution)
65efcfce 1846{
d62a17ae 1847 struct rfapi_next_hop_entry *nhp;
1848 struct rfapi_next_hop_entry *nhp_next;
1849 struct rfapi_next_hop_entry *head = NULL;
1850 struct rfapi_next_hop_entry *tail = NULL;
1851 time_t new_last_sent_time;
1852
1853 vnc_zlog_debug_verbose("%s: loading response=%p, use_eth_resolution=%d",
1854 __func__, response, use_eth_resolution);
1855
1856 new_last_sent_time = rfapi_time(NULL);
1857
1858 for (nhp = response; nhp; nhp = nhp_next) {
1859
1860 struct prefix pfx;
1861 struct rfapi_rib_key rk;
1862 afi_t afi;
1863 struct rfapi_info *ri;
1864 int need_insert;
fe08ba7e 1865 struct agg_node *rn;
d62a17ae 1866 int rib_node_started_nonempty = 0;
fe08ba7e 1867 struct agg_node *trn;
d62a17ae 1868 int allowed = 0;
1869
1870 /* save in case we delete nhp */
1871 nhp_next = nhp->next;
1872
1873 if (nhp->lifetime == RFAPI_REMOVE_RESPONSE_LIFETIME) {
1874 /*
1875 * weird, shouldn't happen
1876 */
1877 vnc_zlog_debug_verbose(
1878 "%s: got nhp->lifetime == RFAPI_REMOVE_RESPONSE_LIFETIME",
1879 __func__);
1880 continue;
1881 }
1882
1883
1884 if (use_eth_resolution) {
1885 /* get the prefix of the ethernet address in the L2
1886 * option */
1887 struct rfapi_l2address_option *pL2o;
1888 struct rfapi_vn_option *vo;
1889
1890 /*
1891 * Look for VN option of type
1892 * RFAPI_VN_OPTION_TYPE_L2ADDR
1893 */
1894 for (pL2o = NULL, vo = nhp->vn_options; vo;
1895 vo = vo->next) {
1896 if (RFAPI_VN_OPTION_TYPE_L2ADDR == vo->type) {
1897 pL2o = &vo->v.l2addr;
1898 break;
1899 }
1900 }
1901
1902 if (!pL2o) {
1903 /*
1904 * not supposed to happen
1905 */
1906 vnc_zlog_debug_verbose("%s: missing L2 info",
1907 __func__);
1908 continue;
1909 }
1910
1911 afi = AFI_L2VPN;
1912 rfapiL2o2Qprefix(pL2o, &pfx);
1913 } else {
1914 rfapiRprefix2Qprefix(&nhp->prefix, &pfx);
1915 afi = family2afi(pfx.family);
1916 }
1917
1918 /*
1919 * TBD for ethernet, rib must know the right way to distinguish
1920 * duplicate routes
1921 *
1922 * Current approach: prefix is key to radix tree; then
1923 * each prefix has a set of routes with unique VN addrs
1924 */
1925
1926 /*
1927 * Look up prefix in RIB
1928 */
fe08ba7e 1929 rn = agg_node_get(rfd->rib[afi], &pfx); /* locks rn */
d62a17ae 1930
1931 if (rn->info) {
1932 rib_node_started_nonempty = 1;
1933 } else {
1934 rn->info = skiplist_new(0, rfapi_rib_key_cmp, NULL);
fe08ba7e 1935 agg_lock_node(rn);
d62a17ae 1936 }
1937
1938 /*
1939 * Look up route at prefix
1940 */
1941 need_insert = 0;
1942 memset((void *)&rk, 0, sizeof(rk));
1943 assert(!rfapiRaddr2Qprefix(&nhp->vn_address, &rk.vn));
1944
1945 if (use_eth_resolution) {
1946 /* copy what came from aux_prefix to rk.aux_prefix */
1947 rfapiRprefix2Qprefix(&nhp->prefix, &rk.aux_prefix);
1948 if (RFAPI_0_PREFIX(&rk.aux_prefix)
1949 && RFAPI_HOST_PREFIX(&rk.aux_prefix)) {
1950 /* mark as "none" if nhp->prefix is 0/32 or
1951 * 0/128 */
c7ca5ccf 1952 rk.aux_prefix.family = AF_UNSPEC;
d62a17ae 1953 }
1954 }
65efcfce
LB
1955
1956#if DEBUG_NHL
d62a17ae 1957 {
872ed4c7 1958 char str_aux_prefix[PREFIX_STRLEN];
d62a17ae 1959
d62a17ae 1960 str_aux_prefix[0] = 0;
1961
872ed4c7
DS
1962 prefix2str(&rk.aux_prefix, str_aux_prefix,
1963 sizeof(str_aux_prefix));
d62a17ae 1964
1965 if (!rk.aux_prefix.family) {
1966 }
1967 vnc_zlog_debug_verbose(
2dbe669b
DA
1968 "%s: rk.vn=%pFX rk.aux_prefix=%s", __func__,
1969 &rk.vn,
d62a17ae 1970 (rk.aux_prefix.family ? str_aux_prefix : "-"));
1971 }
1972 vnc_zlog_debug_verbose(
1973 "%s: RIB skiplist for this prefix follows", __func__);
b54892e0
DS
1974 rfapiRibShowRibSl(NULL, agg_node_get_prefix(rn),
1975 (struct skiplist *)rn->info);
65efcfce
LB
1976#endif
1977
1978
d62a17ae 1979 if (!skiplist_search((struct skiplist *)rn->info, &rk,
1980 (void **)&ri)) {
1981 /*
1982 * Already have this route; make values match
1983 */
1984 rfapiFreeRfapiUnOptionChain(ri->un_options);
1985 ri->un_options = NULL;
1986 rfapiFreeRfapiVnOptionChain(ri->vn_options);
1987 ri->vn_options = NULL;
65efcfce
LB
1988
1989#if DEBUG_NHL
d62a17ae 1990 vnc_zlog_debug_verbose("%s: found in RIB", __func__);
65efcfce
LB
1991#endif
1992
d62a17ae 1993 /*
1994 * Filter duplicate routes from initial response.
1995 * Check timestamps to avoid wraparound problems
1996 */
1997 if ((ri->rsp_counter != rfd->rsp_counter)
1998 || (ri->last_sent_time != new_last_sent_time)) {
65efcfce
LB
1999
2000#if DEBUG_NHL
d62a17ae 2001 vnc_zlog_debug_verbose(
2002 "%s: allowed due to counter/timestamp diff",
2003 __func__);
65efcfce 2004#endif
d62a17ae 2005 allowed = 1;
2006 }
65efcfce 2007
d62a17ae 2008 } else {
65efcfce
LB
2009
2010#if DEBUG_NHL
d62a17ae 2011 vnc_zlog_debug_verbose(
2012 "%s: allowed due to not yet in RIB", __func__);
65efcfce 2013#endif
d62a17ae 2014 /* not found: add new route to RIB */
2015 ri = rfapi_info_new();
2016 need_insert = 1;
2017 allowed = 1;
2018 }
2019
2020 ri->rk = rk;
2021 assert(!rfapiRaddr2Qprefix(&nhp->un_address, &ri->un));
2022 ri->cost = nhp->prefix.cost;
2023 ri->lifetime = nhp->lifetime;
2024 ri->vn_options = rfapiVnOptionsDup(nhp->vn_options);
2025 ri->rsp_counter = rfd->rsp_counter;
2026 ri->last_sent_time = rfapi_time(NULL);
2027
2028 if (need_insert) {
2029 int rc;
2030 rc = skiplist_insert((struct skiplist *)rn->info,
2031 &ri->rk, ri);
2032 assert(!rc);
2033 }
2034
2035 if (!rib_node_started_nonempty) {
2036 RFAPI_RIB_PREFIX_COUNT_INCR(rfd, bgp->rfapi);
2037 }
2038
2039 RFAPI_RIB_CHECK_COUNTS(0, 0);
2040 rfapiRibStartTimer(rfd, ri, rn, 0);
2041 RFAPI_RIB_CHECK_COUNTS(0, 0);
2042
fe08ba7e 2043 agg_unlock_node(rn);
d62a17ae 2044
2045 /*
2046 * update this NVE's timestamp for this prefix
2047 */
fe08ba7e 2048 trn = agg_node_get(rfd->rsp_times[afi], &pfx); /* locks trn */
d62a17ae 2049 trn->info = (void *)(uintptr_t)bgp_clock();
c10e14e9 2050 if (agg_node_get_lock_count(trn) > 1)
fe08ba7e 2051 agg_unlock_node(trn);
d62a17ae 2052
2dbe669b
DA
2053 vnc_zlog_debug_verbose(
2054 "%s: added pfx=%pFX nh[vn]=%pFX, cost=%u, lifetime=%u, allowed=%d",
2055 __func__, &pfx, &rk.vn, nhp->prefix.cost, nhp->lifetime,
2056 allowed);
d62a17ae 2057
2058 if (allowed) {
2059 if (tail)
2060 (tail)->next = nhp;
2061 tail = nhp;
2062 if (!head) {
2063 head = nhp;
2064 }
2065 } else {
2066 rfapi_un_options_free(nhp->un_options);
2067 nhp->un_options = NULL;
2068 rfapi_vn_options_free(nhp->vn_options);
2069 nhp->vn_options = NULL;
2070
2071 XFREE(MTYPE_RFAPI_NEXTHOP, nhp);
d62a17ae 2072 }
2073 }
2074
2075 if (tail)
2076 tail->next = NULL;
2077 return head;
65efcfce
LB
2078}
2079
d62a17ae 2080void rfapiRibPendingDeleteRoute(struct bgp *bgp, struct rfapi_import_table *it,
fe08ba7e 2081 afi_t afi, struct agg_node *it_node)
65efcfce 2082{
d62a17ae 2083 struct rfapi_descriptor *rfd;
2084 struct listnode *node;
26a3ffd6 2085 const struct prefix *p = agg_node_get_prefix(it_node);
d62a17ae 2086
26a3ffd6
DS
2087 vnc_zlog_debug_verbose("%s: entry, it=%p, afi=%d, it_node=%p, pfx=%pRN",
2088 __func__, it, afi, it_node, it_node);
d62a17ae 2089
2090 if (AFI_L2VPN == afi) {
2091 /*
2092 * ethernet import tables are per-LNI and each ethernet monitor
2093 * identifies the rfd that owns it.
2094 */
2095 struct rfapi_monitor_eth *m;
fe08ba7e 2096 struct agg_node *rn;
d62a17ae 2097 struct skiplist *sl;
2098 void *cursor;
2099 int rc;
2100
2101 /*
2102 * route-specific monitors
2103 */
2104 if ((sl = RFAPI_MONITOR_ETH(it_node))) {
2105
2106 vnc_zlog_debug_verbose(
2107 "%s: route-specific skiplist: %p", __func__,
2108 sl);
2109
2110 for (cursor = NULL,
8998807f 2111 rc = skiplist_next(sl, NULL, (void **)&m, &cursor);
d62a17ae 2112 !rc; rc = skiplist_next(sl, NULL, (void **)&m,
8998807f 2113 &cursor)) {
65efcfce
LB
2114
2115#if DEBUG_PENDING_DELETE_ROUTE
d62a17ae 2116 vnc_zlog_debug_verbose("%s: eth monitor rfd=%p",
2117 __func__, m->rfd);
65efcfce 2118#endif
d62a17ae 2119 /*
2120 * If we have already sent a route with this
2121 * prefix to this
2122 * NVE, it's OK to send an update with the
2123 * delete
2124 */
fe08ba7e 2125 if ((rn = agg_node_lookup(m->rfd->rib[afi],
26a3ffd6 2126 p))) {
d62a17ae 2127 rfapiRibUpdatePendingNode(
2128 bgp, m->rfd, it, it_node,
2129 m->rfd->response_lifetime);
fe08ba7e 2130 agg_unlock_node(rn);
d62a17ae 2131 }
2132 }
2133 }
2134
2135 /*
2136 * all-routes/FTD monitors
2137 */
2138 for (m = it->eth0_queries; m; m = m->next) {
65efcfce 2139#if DEBUG_PENDING_DELETE_ROUTE
d62a17ae 2140 vnc_zlog_debug_verbose("%s: eth0 monitor rfd=%p",
2141 __func__, m->rfd);
65efcfce 2142#endif
d62a17ae 2143 /*
2144 * If we have already sent a route with this prefix to
2145 * this
2146 * NVE, it's OK to send an update with the delete
2147 */
26a3ffd6 2148 if ((rn = agg_node_lookup(m->rfd->rib[afi], p))) {
d62a17ae 2149 rfapiRibUpdatePendingNode(
2150 bgp, m->rfd, it, it_node,
2151 m->rfd->response_lifetime);
94f7f37d 2152 agg_unlock_node(rn);
d62a17ae 2153 }
2154 }
2155
2156 } else {
2157 /*
2158 * Find RFDs that reference this import table
2159 */
2160 for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, node,
2161 rfd)) {
2162
fe08ba7e 2163 struct agg_node *rn;
d62a17ae 2164
2165 vnc_zlog_debug_verbose(
2166 "%s: comparing rfd(%p)->import_table=%p to it=%p",
2167 __func__, rfd, rfd->import_table, it);
2168
2169 if (rfd->import_table != it)
2170 continue;
2171
2172 vnc_zlog_debug_verbose("%s: matched rfd %p", __func__,
2173 rfd);
2174
2175 /*
2176 * If we have sent a response to this NVE with this
2177 * prefix
2178 * previously, we should send an updated response.
2179 */
26a3ffd6 2180 if ((rn = agg_node_lookup(rfd->rib[afi], p))) {
d62a17ae 2181 rfapiRibUpdatePendingNode(
2182 bgp, rfd, it, it_node,
2183 rfd->response_lifetime);
fe08ba7e 2184 agg_unlock_node(rn);
d62a17ae 2185 }
2186 }
2187 }
65efcfce
LB
2188}
2189
d62a17ae 2190void rfapiRibShowResponsesSummary(void *stream)
65efcfce 2191{
d62a17ae 2192 int (*fp)(void *, const char *, ...);
2193 struct vty *vty;
2194 void *out;
2195 const char *vty_newline;
2196 struct bgp *bgp = bgp_get_default();
2197
2198 int nves = 0;
2199 int nves_with_nonempty_ribs = 0;
2200 struct rfapi_descriptor *rfd;
2201 struct listnode *node;
2202
d62a17ae 2203 if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
2204 return;
9b86009a
RW
2205 if (!bgp) {
2206 fp(out, "Unable to find default BGP instance\n");
2207 return;
2208 }
d62a17ae 2209
2210 fp(out, "%-24s ", "Responses: (Prefixes)");
2211 fp(out, "%-8s %-8u ", "Active:", bgp->rfapi->rib_prefix_count_total);
2212 fp(out, "%-8s %-8u",
2213 "Maximum:", bgp->rfapi->rib_prefix_count_total_max);
2214 fp(out, "\n");
2215
2216 fp(out, "%-24s ", " (Updated)");
2217 fp(out, "%-8s %-8u ",
2218 "Update:", bgp->rfapi->stat.count_updated_response_updates);
2219 fp(out, "%-8s %-8u",
2220 "Remove:", bgp->rfapi->stat.count_updated_response_deletes);
2221 fp(out, "%-8s %-8u", "Total:",
2222 bgp->rfapi->stat.count_updated_response_updates
2223 + bgp->rfapi->stat.count_updated_response_deletes);
2224 fp(out, "\n");
2225
2226 fp(out, "%-24s ", " (NVEs)");
2227 for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, node, rfd)) {
2228 ++nves;
2229 if (rfd->rib_prefix_count)
2230 ++nves_with_nonempty_ribs;
2231 }
2232 fp(out, "%-8s %-8u ", "Active:", nves_with_nonempty_ribs);
2233 fp(out, "%-8s %-8u", "Total:", nves);
2234 fp(out, "\n");
65efcfce
LB
2235}
2236
d62a17ae 2237void rfapiRibShowResponsesSummaryClear(void)
65efcfce 2238{
d62a17ae 2239 struct bgp *bgp = bgp_get_default();
65efcfce 2240
d62a17ae 2241 bgp->rfapi->rib_prefix_count_total_max =
2242 bgp->rfapi->rib_prefix_count_total;
65efcfce
LB
2243}
2244
d62a17ae 2245static int print_rib_sl(int (*fp)(void *, const char *, ...), struct vty *vty,
2246 void *out, struct skiplist *sl, int deleted,
2247 char *str_pfx, int *printedprefix)
65efcfce 2248{
d62a17ae 2249 struct rfapi_info *ri;
2250 int rc;
2251 void *cursor;
2252 int routes_displayed = 0;
2253
2254 cursor = NULL;
2255 for (rc = skiplist_next(sl, NULL, (void **)&ri, &cursor); !rc;
2256 rc = skiplist_next(sl, NULL, (void **)&ri, &cursor)) {
2257
872ed4c7
DS
2258 char str_vn[PREFIX_STRLEN];
2259 char str_un[PREFIX_STRLEN];
d62a17ae 2260 char str_lifetime[BUFSIZ];
2261 char str_age[BUFSIZ];
2262 char *p;
06b9f471 2263 char str_rd[RD_ADDRSTRLEN];
d62a17ae 2264
2265 ++routes_displayed;
2266
872ed4c7 2267 prefix2str(&ri->rk.vn, str_vn, sizeof(str_vn));
d62a17ae 2268 p = index(str_vn, '/');
2269 if (p)
2270 *p = 0;
2271
872ed4c7 2272 prefix2str(&ri->un, str_un, sizeof(str_un));
d62a17ae 2273 p = index(str_un, '/');
2274 if (p)
2275 *p = 0;
2276
2277 rfapiFormatSeconds(ri->lifetime, str_lifetime, BUFSIZ);
1e20238a 2278#ifdef RFAPI_REGISTRATIONS_REPORT_AGE
d62a17ae 2279 rfapiFormatAge(ri->last_sent_time, str_age, BUFSIZ);
65efcfce 2280#else
d62a17ae 2281 {
2282 time_t now = rfapi_time(NULL);
2283 time_t expire =
2284 ri->last_sent_time + (time_t)ri->lifetime;
2285 /* allow for delayed/async removal */
2286 rfapiFormatSeconds((expire > now ? expire - now : 1),
2287 str_age, BUFSIZ);
2288 }
65efcfce
LB
2289#endif
2290
d62a17ae 2291 str_rd[0] = 0; /* start empty */
65efcfce 2292#if DEBUG_RIB_SL_RD
06b9f471 2293 prefix_rd2str(&ri->rk.rd, str_rd, sizeof(str_rd));
65efcfce
LB
2294#endif
2295
06b9f471 2296 fp(out, " %c %-20s %-15s %-15s %-4u %-8s %-8s %s\n",
d62a17ae 2297 deleted ? 'r' : ' ', *printedprefix ? "" : str_pfx, str_vn,
2298 str_un, ri->cost, str_lifetime, str_age, str_rd);
65efcfce 2299
d62a17ae 2300 if (!*printedprefix)
2301 *printedprefix = 1;
2302 }
2303 return routes_displayed;
65efcfce
LB
2304}
2305
2306#if DEBUG_NHL
2307/*
2308 * This one is for debugging (set stream to NULL to send output to log)
2309 */
d62a17ae 2310static void rfapiRibShowRibSl(void *stream, struct prefix *pfx,
2311 struct skiplist *sl)
65efcfce 2312{
d62a17ae 2313 int (*fp)(void *, const char *, ...);
2314 struct vty *vty;
2315 void *out;
2316 const char *vty_newline;
65efcfce 2317
d62a17ae 2318 int nhs_displayed = 0;
872ed4c7 2319 char str_pfx[PREFIX_STRLEN];
d62a17ae 2320 int printedprefix = 0;
65efcfce 2321
d62a17ae 2322 if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
2323 return;
65efcfce 2324
872ed4c7 2325 prefix2str(pfx, str_pfx, sizeof(str_pfx));
65efcfce 2326
d62a17ae 2327 nhs_displayed +=
2328 print_rib_sl(fp, vty, out, sl, 0, str_pfx, &printedprefix);
65efcfce
LB
2329}
2330#endif
2331
d62a17ae 2332void rfapiRibShowResponses(void *stream, struct prefix *pfx_match,
2333 int show_removed)
65efcfce 2334{
d62a17ae 2335 int (*fp)(void *, const char *, ...);
2336 struct vty *vty;
2337 void *out;
2338 const char *vty_newline;
2339
2340 struct rfapi_descriptor *rfd;
2341 struct listnode *node;
2342
2343 struct bgp *bgp = bgp_get_default();
2344 int printedheader = 0;
2345 int routes_total = 0;
2346 int nhs_total = 0;
2347 int prefixes_total = 0;
2348 int prefixes_displayed = 0;
2349 int nves_total = 0;
2350 int nves_with_routes = 0;
2351 int nves_displayed = 0;
2352 int routes_displayed = 0;
2353 int nhs_displayed = 0;
2354
2355 if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
2356 return;
9b86009a
RW
2357 if (!bgp) {
2358 fp(out, "Unable to find default BGP instance\n");
2359 return;
2360 }
2361
d62a17ae 2362 /*
2363 * loop over NVEs
2364 */
2365 for (ALL_LIST_ELEMENTS_RO(&bgp->rfapi->descriptors, node, rfd)) {
2366
2367 int printednve = 0;
2368 afi_t afi;
2369
2370 ++nves_total;
2371 if (rfd->rib_prefix_count)
2372 ++nves_with_routes;
2373
2374 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
2375
fe08ba7e 2376 struct agg_node *rn;
d62a17ae 2377
2378 if (!rfd->rib[afi])
2379 continue;
2380
fe08ba7e
DS
2381 for (rn = agg_route_top(rfd->rib[afi]); rn;
2382 rn = agg_route_next(rn)) {
26a3ffd6
DS
2383 const struct prefix *p =
2384 agg_node_get_prefix(rn);
d62a17ae 2385 struct skiplist *sl;
872ed4c7 2386 char str_pfx[PREFIX_STRLEN];
d62a17ae 2387 int printedprefix = 0;
2388
2389 if (!show_removed)
2390 sl = rn->info;
2391 else
2392 sl = rn->aggregate;
2393
2394 if (!sl)
2395 continue;
2396
2397 routes_total++;
2398 nhs_total += skiplist_count(sl);
2399 ++prefixes_total;
2400
26a3ffd6
DS
2401 if (pfx_match && !prefix_match(pfx_match, p)
2402 && !prefix_match(p, pfx_match))
d62a17ae 2403 continue;
2404
2405 ++prefixes_displayed;
2406
2407 if (!printedheader) {
2408 ++printedheader;
2409
2410 fp(out, "\n[%s]\n",
2411 show_removed ? "Removed" : "Active");
2412 fp(out, "%-15s %-15s\n", "Querying VN",
2413 "Querying UN");
2414 fp(out,
2415 " %-20s %-15s %-15s %4s %-8s %-8s\n",
2416 "Prefix", "Registered VN",
2417 "Registered UN", "Cost", "Lifetime",
1e20238a 2418#ifdef RFAPI_REGISTRATIONS_REPORT_AGE
d62a17ae 2419 "Age"
65efcfce 2420#else
d62a17ae 2421 "Remaining"
65efcfce 2422#endif
1e20238a 2423 );
d62a17ae 2424 }
2425 if (!printednve) {
2426 char str_vn[BUFSIZ];
2427 char str_un[BUFSIZ];
2428
2429 ++printednve;
2430 ++nves_displayed;
2431
2432 fp(out, "%-15s %-15s\n",
2433 rfapiRfapiIpAddr2Str(&rfd->vn_addr,
2434 str_vn, BUFSIZ),
2435 rfapiRfapiIpAddr2Str(&rfd->un_addr,
2436 str_un,
2437 BUFSIZ));
2438 }
26a3ffd6 2439 prefix2str(p, str_pfx, sizeof(str_pfx));
d62a17ae 2440 // fp(out, " %s\n", buf); /* prefix */
2441
2442 routes_displayed++;
2443 nhs_displayed += print_rib_sl(
2444 fp, vty, out, sl, show_removed, str_pfx,
2445 &printedprefix);
2446 }
2447 }
2448 }
2449
2450 if (routes_total) {
2451 fp(out, "\n");
2452 fp(out, "Displayed %u NVEs, and %u out of %u %s prefixes",
2453 nves_displayed, routes_displayed, routes_total,
2454 show_removed ? "removed" : "active");
2455 if (nhs_displayed != routes_displayed
2456 || nhs_total != routes_total)
2457 fp(out, " with %u out of %u next hops", nhs_displayed,
2458 nhs_total);
2459 fp(out, "\n");
2460 }
65efcfce 2461}