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