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