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