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