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