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