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