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