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