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