3 * Copyright 2009-2016, LabN Consulting, L.L.C.
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.
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.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 * Purpose: maintain per-nve ribs and generate change lists
28 #include "lib/zebra.h"
29 #include "lib/prefix.h"
30 #include "lib/table.h"
32 #include "lib/memory.h"
34 #include "lib/skiplist.h"
35 #include "lib/workqueue.h"
37 #include "bgpd/bgpd.h"
38 #include "bgpd/bgp_route.h"
39 #include "bgpd/bgp_ecommunity.h"
40 #include "bgpd/bgp_mplsvpn.h"
41 #include "bgpd/bgp_vnc_types.h"
43 #include "bgpd/rfapi/rfapi.h"
44 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
45 #include "bgpd/rfapi/rfapi_import.h"
46 #include "bgpd/rfapi/rfapi_private.h"
47 #include "bgpd/rfapi/rfapi_vty.h"
48 #include "bgpd/rfapi/vnc_import_bgp.h"
49 #include "bgpd/rfapi/rfapi_rib.h"
50 #include "bgpd/rfapi/rfapi_monitor.h"
51 #include "bgpd/rfapi/rfapi_encap_tlv.h"
52 #include "bgpd/rfapi/vnc_debug.h"
54 #define DEBUG_PROCESS_PENDING_NODE 0
55 #define DEBUG_PENDING_DELETE_ROUTE 0
57 #define DEBUG_RIB_SL_RD 0
61 static void rfapiRibShowRibSl(void *stream
, struct prefix
*pfx
,
68 * Model of the set of routes currently in the NVE's RIB.
70 * node->info ptr to "struct skiplist".
71 * MUST be NULL if there are no routes.
72 * key = ptr to struct prefix {vn}
73 * val = ptr to struct rfapi_info
75 * skiplist.cmp = vnc_prefix_cmp
77 * node->aggregate ptr to "struct skiplist".
78 * key = ptr to struct prefix {vn}
79 * val = ptr to struct rfapi_info
80 * skiplist.del = rfapi_info_free
81 * skiplist.cmp = vnc_prefix_cmp
83 * This skiplist at "aggregate"
84 * contains the routes recently
90 * Sparse list of prefixes that need to be updated. Each node
91 * will have the complete set of routes for the prefix.
93 * node->info ptr to "struct list" (lib/linklist.h)
95 * List of routes sorted lowest cost first.
96 * This list is how the new complete set
97 * of routes should look.
98 * Set if there are updates to the prefix;
99 * MUST be NULL if there are no updates.
101 * .data = ptr to struct rfapi_info
102 * list.cmp = NULL (sorted manually)
103 * list.del = rfapi_info_free
105 * Special case: if node->info is 1, it means
106 * "delete all routes at this prefix".
108 * node->aggregate ptr to struct skiplist
109 * key = ptr to struct prefix {vn} (part of ri)
110 * val = struct rfapi_info
111 * skiplist.cmp = vnc_prefix_cmp
112 * skiplist.del = NULL
114 * ptlist is rewritten anew each time
115 * rfapiRibUpdatePendingNode() is called
117 * THE ptlist VALUES ARE REFERENCES TO THE
118 * rfapi_info STRUCTS IN THE node->info LIST.
122 * iterate over RIB to count responses, compare with running counters
124 void rfapiRibCheckCounts(
125 int checkstats
, /* validate rfd & global counts */
126 unsigned int offset
) /* number of ri's held separately */
128 struct rfapi_descriptor
*rfd
;
129 struct listnode
*node
;
131 struct bgp
*bgp
= bgp_get_default();
133 uint32_t t_pfx_active
= 0;
134 uint32_t t_pfx_deleted
= 0;
136 uint32_t t_ri_active
= 0;
137 uint32_t t_ri_deleted
= 0;
138 uint32_t t_ri_pend
= 0;
140 unsigned int alloc_count
;
145 for (ALL_LIST_ELEMENTS_RO(&bgp
->rfapi
->descriptors
, node
, rfd
)) {
148 uint32_t pfx_active
= 0;
149 uint32_t pfx_deleted
= 0;
151 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
153 struct route_node
*rn
;
155 for (rn
= route_top(rfd
->rib
[afi
]); rn
;
156 rn
= route_next(rn
)) {
158 struct skiplist
*sl
= rn
->info
;
159 struct skiplist
*dsl
= rn
->aggregate
;
160 uint32_t ri_active
= 0;
161 uint32_t ri_deleted
= 0;
164 ri_active
= skiplist_count(sl
);
166 t_ri_active
+= ri_active
;
172 ri_deleted
= skiplist_count(dsl
);
173 t_ri_deleted
+= ri_deleted
;
178 for (rn
= route_top(rfd
->rib_pending
[afi
]); rn
;
179 rn
= route_next(rn
)) {
181 struct list
*l
= rn
->info
; /* sorted by cost */
182 struct skiplist
*sl
= rn
->aggregate
;
183 uint32_t ri_pend_cost
= 0;
184 uint32_t ri_pend_uniq
= 0;
187 ri_pend_uniq
= skiplist_count(sl
);
190 if (l
&& (l
!= (void *)1)) {
191 ri_pend_cost
= l
->count
;
192 t_ri_pend
+= l
->count
;
195 assert(ri_pend_uniq
== ri_pend_cost
);
200 if (pfx_active
!= rfd
->rib_prefix_count
) {
201 vnc_zlog_debug_verbose(
202 "%s: rfd %p actual pfx count %u != running %u",
203 __func__
, rfd
, pfx_active
,
204 rfd
->rib_prefix_count
);
210 if (checkstats
&& bgp
->rfapi
) {
211 if (t_pfx_active
!= bgp
->rfapi
->rib_prefix_count_total
) {
212 vnc_zlog_debug_verbose(
213 "%s: actual total pfx count %u != running %u",
214 __func__
, t_pfx_active
,
215 bgp
->rfapi
->rib_prefix_count_total
);
221 * Check against memory allocation count
223 alloc_count
= mtype_stats_alloc(MTYPE_RFAPI_INFO
);
224 assert(t_ri_active
+ t_ri_deleted
+ t_ri_pend
+ offset
== alloc_count
);
227 static struct rfapi_info
*rfapi_info_new()
229 return XCALLOC(MTYPE_RFAPI_INFO
, sizeof(struct rfapi_info
));
232 void rfapiFreeRfapiUnOptionChain(struct rfapi_un_option
*p
)
235 struct rfapi_un_option
*next
;
238 XFREE(MTYPE_RFAPI_UN_OPTION
, p
);
243 void rfapiFreeRfapiVnOptionChain(struct rfapi_vn_option
*p
)
246 struct rfapi_vn_option
*next
;
249 XFREE(MTYPE_RFAPI_VN_OPTION
, p
);
255 static void rfapi_info_free(struct rfapi_info
*goner
)
258 if (goner
->tea_options
) {
259 rfapiFreeBgpTeaOptionChain(goner
->tea_options
);
260 goner
->tea_options
= NULL
;
262 if (goner
->un_options
) {
263 rfapiFreeRfapiUnOptionChain(goner
->un_options
);
264 goner
->un_options
= NULL
;
266 if (goner
->vn_options
) {
267 rfapiFreeRfapiVnOptionChain(goner
->vn_options
);
268 goner
->vn_options
= NULL
;
271 struct rfapi_rib_tcb
*tcb
;
273 tcb
= ((struct thread
*)goner
->timer
)->arg
;
274 thread_cancel((struct thread
*)goner
->timer
);
275 XFREE(MTYPE_RFAPI_RECENT_DELETE
, tcb
);
278 XFREE(MTYPE_RFAPI_INFO
, goner
);
283 * Timer control block for recently-deleted and expired routes
285 struct rfapi_rib_tcb
{
286 struct rfapi_descriptor
*rfd
;
288 struct rfapi_info
*ri
;
289 struct route_node
*rn
;
291 #define RFAPI_RIB_TCB_FLAG_DELETED 0x00000001
295 * remove route from rib
297 static int rfapiRibExpireTimer(struct thread
*t
)
299 struct rfapi_rib_tcb
*tcb
= t
->arg
;
301 RFAPI_RIB_CHECK_COUNTS(1, 0);
304 * Forget reference to thread. Otherwise rfapi_info_free() will
305 * attempt to free thread pointer as an option chain
307 tcb
->ri
->timer
= NULL
;
309 /* "deleted" skiplist frees ri, "active" doesn't */
310 assert(!skiplist_delete(tcb
->sl
, &tcb
->ri
->rk
, NULL
));
313 * XXX in this case, skiplist has no delete function: we must
314 * therefore delete rfapi_info explicitly.
316 rfapi_info_free(tcb
->ri
);
319 if (skiplist_empty(tcb
->sl
)) {
320 if (CHECK_FLAG(tcb
->flags
, RFAPI_RIB_TCB_FLAG_DELETED
))
321 tcb
->rn
->aggregate
= NULL
;
323 struct bgp
*bgp
= bgp_get_default();
324 tcb
->rn
->info
= NULL
;
325 RFAPI_RIB_PREFIX_COUNT_DECR(tcb
->rfd
, bgp
->rfapi
);
327 skiplist_free(tcb
->sl
);
328 route_unlock_node(tcb
->rn
);
331 XFREE(MTYPE_RFAPI_RECENT_DELETE
, tcb
);
333 RFAPI_RIB_CHECK_COUNTS(1, 0);
339 rfapiRibStartTimer(struct rfapi_descriptor
*rfd
, struct rfapi_info
*ri
,
340 struct route_node
*rn
, /* route node attached to */
343 struct thread
*t
= ri
->timer
;
344 struct rfapi_rib_tcb
*tcb
= NULL
;
345 char buf_prefix
[PREFIX_STRLEN
];
352 tcb
= XCALLOC(MTYPE_RFAPI_RECENT_DELETE
,
353 sizeof(struct rfapi_rib_tcb
));
359 tcb
->sl
= (struct skiplist
*)rn
->aggregate
;
360 SET_FLAG(tcb
->flags
, RFAPI_RIB_TCB_FLAG_DELETED
);
362 tcb
->sl
= (struct skiplist
*)rn
->info
;
363 UNSET_FLAG(tcb
->flags
, RFAPI_RIB_TCB_FLAG_DELETED
);
366 prefix2str(&rn
->p
, buf_prefix
, sizeof(buf_prefix
));
367 vnc_zlog_debug_verbose("%s: rfd %p pfx %s life %u", __func__
, rfd
,
368 buf_prefix
, ri
->lifetime
);
370 thread_add_timer(bm
->master
, rfapiRibExpireTimer
, tcb
, ri
->lifetime
,
375 extern void rfapi_rib_key_init(struct prefix
*prefix
, /* may be NULL */
376 struct prefix_rd
*rd
, /* may be NULL */
377 struct prefix
*aux
, /* may be NULL */
378 struct rfapi_rib_key
*rk
)
381 memset((void *)rk
, 0, sizeof(struct rfapi_rib_key
));
387 rk
->aux_prefix
= *aux
;
391 * Compares two <struct rfapi_rib_key>s
393 int rfapi_rib_key_cmp(void *k1
, void *k2
)
395 struct rfapi_rib_key
*a
= (struct rfapi_rib_key
*)k1
;
396 struct rfapi_rib_key
*b
= (struct rfapi_rib_key
*)k2
;
402 ret
= vnc_prefix_cmp(&a
->vn
, &b
->vn
);
406 ret
= vnc_prefix_cmp(&a
->rd
, &b
->rd
);
410 ret
= vnc_prefix_cmp(&a
->aux_prefix
, &b
->aux_prefix
);
417 * Note: this function will claim that two option chains are
418 * different unless their option items are in identical order.
419 * The consequence is that RFP updated responses can be sent
420 * unnecessarily, or that they might contain nexthop items
421 * that are not strictly needed.
423 * This function could be modified to compare option chains more
424 * thoroughly, but it's not clear that the extra compuation would
427 static int bgp_tea_options_cmp(struct bgp_tea_options
*a
,
428 struct bgp_tea_options
*b
)
436 if (a
->type
!= b
->type
)
437 return (a
->type
- b
->type
);
438 if (a
->length
!= b
->length
)
439 return (a
->length
= b
->length
);
440 if ((rc
= memcmp(a
->value
, b
->value
, a
->length
)))
442 if (!a
->next
!= !b
->next
) { /* logical xor */
443 return (a
->next
- b
->next
);
446 return bgp_tea_options_cmp(a
->next
, b
->next
);
450 static int rfapi_info_cmp(struct rfapi_info
*a
, struct rfapi_info
*b
)
457 if ((rc
= rfapi_rib_key_cmp(&a
->rk
, &b
->rk
)))
460 if ((rc
= vnc_prefix_cmp(&a
->un
, &b
->un
)))
463 if (a
->cost
!= b
->cost
)
464 return (a
->cost
- b
->cost
);
466 if (a
->lifetime
!= b
->lifetime
)
467 return (a
->lifetime
- b
->lifetime
);
469 if ((rc
= bgp_tea_options_cmp(a
->tea_options
, b
->tea_options
)))
475 void rfapiRibClear(struct rfapi_descriptor
*rfd
)
483 bgp
= bgp_get_default();
485 vnc_zlog_debug_verbose("%s: rfd=%p", __func__
, rfd
);
488 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
489 struct route_node
*pn
;
490 struct route_node
*rn
;
492 if (rfd
->rib_pending
[afi
]) {
493 for (pn
= route_top(rfd
->rib_pending
[afi
]); pn
;
494 pn
= route_next(pn
)) {
497 * free references into the rfapi_info
499 * freeing the structures themselves
504 pn
->aggregate
= NULL
;
506 pn
); /* skiplist deleted */
509 * free the rfapi_info structures
512 if (pn
->info
!= (void *)1) {
513 list_delete_and_null(
518 /* linklist or 1 deleted */
519 route_unlock_node(pn
);
524 for (rn
= route_top(rfd
->rib
[afi
]); rn
;
525 rn
= route_next(rn
)) {
528 struct rfapi_info
*ri
;
530 while (0 == skiplist_first(
537 skiplist_delete_first(
542 (struct skiplist
*)rn
->info
);
544 route_unlock_node(rn
);
545 RFAPI_RIB_PREFIX_COUNT_DECR(rfd
,
550 struct rfapi_info
*ri_del
;
552 /* delete skiplist & contents */
553 while (!skiplist_first(
556 NULL
, (void **)&ri_del
)) {
558 /* sl->del takes care of ri_del
560 skiplist_delete_first((
568 rn
->aggregate
= NULL
;
569 route_unlock_node(rn
);
574 if (rfd
->updated_responses_queue
) {
575 work_queue_free(rfd
->updated_responses_queue
);
576 rfd
->updated_responses_queue
= NULL
;
581 * Release all dynamically-allocated memory that is part of an HD's RIB
583 void rfapiRibFree(struct rfapi_descriptor
*rfd
)
589 * NB rfd is typically detached from master list, so is not included
590 * in the count performed by RFAPI_RIB_CHECK_COUNTS
594 * Free routes attached to radix trees
598 /* Now the uncounted rfapi_info's are freed, so the check should succeed
600 RFAPI_RIB_CHECK_COUNTS(1, 0);
605 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
606 route_table_finish(rfd
->rib_pending
[afi
]);
607 rfd
->rib_pending
[afi
] = NULL
;
609 route_table_finish(rfd
->rib
[afi
]);
610 rfd
->rib
[afi
] = NULL
;
612 /* NB route_table_finish frees only prefix nodes, not chained
614 route_table_finish(rfd
->rsp_times
[afi
]);
615 rfd
->rib
[afi
] = NULL
;
620 * Copies struct bgp_info to struct rfapi_info, except for rk fields and un
622 static void rfapiRibBi2Ri(struct bgp_info
*bi
, struct rfapi_info
*ri
,
625 struct bgp_attr_encap_subtlv
*pEncap
;
627 ri
->cost
= rfapiRfpCost(bi
->attr
);
628 ri
->lifetime
= lifetime
;
630 /* This loop based on rfapiRouteInfo2NextHopEntry() */
631 for (pEncap
= bi
->attr
->vnc_subtlvs
; pEncap
; pEncap
= pEncap
->next
) {
632 struct bgp_tea_options
*hop
;
634 switch (pEncap
->type
) {
635 case BGP_VNC_SUBTLV_TYPE_LIFETIME
:
636 /* use configured lifetime, not attr lifetime */
639 case BGP_VNC_SUBTLV_TYPE_RFPOPTION
:
640 hop
= XCALLOC(MTYPE_BGP_TEA_OPTIONS
,
641 sizeof(struct bgp_tea_options
));
643 hop
->type
= pEncap
->value
[0];
644 hop
->length
= pEncap
->value
[1];
645 hop
->value
= XCALLOC(MTYPE_BGP_TEA_OPTIONS_VALUE
,
648 memcpy(hop
->value
, pEncap
->value
+ 2,
650 if (hop
->length
> pEncap
->length
- 2) {
652 "%s: VNC subtlv length mismatch: "
653 "RFP option says %d, attr says %d "
655 __func__
, hop
->length
,
657 hop
->length
= pEncap
->length
- 2;
659 hop
->next
= ri
->tea_options
;
660 ri
->tea_options
= hop
;
668 rfapi_un_options_free(ri
->un_options
); /* maybe free old version */
669 ri
->un_options
= rfapi_encap_tlv_to_un_option(bi
->attr
);
675 && decode_rd_type(bi
->extra
->vnc
.import
.rd
.val
)
676 == RD_TYPE_VNC_ETH
) {
679 struct rfapi_vn_option
*vo
;
681 vo
= XCALLOC(MTYPE_RFAPI_VN_OPTION
,
682 sizeof(struct rfapi_vn_option
));
685 vo
->type
= RFAPI_VN_OPTION_TYPE_L2ADDR
;
687 /* copy from RD already stored in bi, so we don't need it_node
689 memcpy(&vo
->v
.l2addr
.macaddr
, bi
->extra
->vnc
.import
.rd
.val
+ 2,
692 (void)rfapiEcommunityGetLNI(bi
->attr
->ecommunity
,
693 &vo
->v
.l2addr
.logical_net_id
);
694 (void)rfapiEcommunityGetEthernetTag(bi
->attr
->ecommunity
,
695 &vo
->v
.l2addr
.tag_id
);
697 /* local_nve_id comes from RD */
698 vo
->v
.l2addr
.local_nve_id
= bi
->extra
->vnc
.import
.rd
.val
[1];
700 /* label comes from MP_REACH_NLRI label */
701 vo
->v
.l2addr
.label
= decode_label(&bi
->extra
->label
[0]);
703 rfapi_vn_options_free(
704 ri
->vn_options
); /* maybe free old version */
709 * If there is an auxiliary IP address (L2 can have it), copy it
711 if (bi
->extra
&& bi
->extra
->vnc
.import
.aux_prefix
.family
) {
712 ri
->rk
.aux_prefix
= bi
->extra
->vnc
.import
.aux_prefix
;
719 * Install route into NVE RIB model so as to be consistent with
720 * caller's response to rfapi_query().
722 * Also: return indication to caller whether this specific route
723 * should be included in the response to the NVE according to
724 * the following tests:
726 * 1. If there were prior duplicates of this route in this same
727 * query response, don't include the route.
731 * 0 OK to include route in response
732 * !0 do not include route in response
734 int rfapiRibPreloadBi(
735 struct route_node
*rfd_rib_node
, /* NULL = don't preload or filter */
736 struct prefix
*pfx_vn
, struct prefix
*pfx_un
, uint32_t lifetime
,
739 struct rfapi_descriptor
*rfd
;
740 struct skiplist
*slRibPt
= NULL
;
741 struct rfapi_info
*ori
= NULL
;
742 struct rfapi_rib_key rk
;
743 struct route_node
*trn
;
749 afi
= family2afi(rfd_rib_node
->p
.family
);
751 rfd
= (struct rfapi_descriptor
*)(rfd_rib_node
->table
->info
);
753 memset((void *)&rk
, 0, sizeof(rk
));
755 rk
.rd
= bi
->extra
->vnc
.import
.rd
;
758 * If there is an auxiliary IP address (L2 can have it), copy it
760 if (bi
->extra
->vnc
.import
.aux_prefix
.family
) {
761 rk
.aux_prefix
= bi
->extra
->vnc
.import
.aux_prefix
;
765 * is this route already in NVE's RIB?
767 slRibPt
= (struct skiplist
*)rfd_rib_node
->info
;
769 if (slRibPt
&& !skiplist_search(slRibPt
, &rk
, (void **)&ori
)) {
771 if ((ori
->rsp_counter
== rfd
->rsp_counter
)
772 && (ori
->last_sent_time
== rfd
->rsp_time
)) {
773 return -1; /* duplicate in this response */
776 /* found: update contents of existing route in RIB */
778 rfapiRibBi2Ri(bi
, ori
, lifetime
);
780 /* not found: add new route to RIB */
781 ori
= rfapi_info_new();
784 rfapiRibBi2Ri(bi
, ori
, lifetime
);
787 slRibPt
= skiplist_new(0, rfapi_rib_key_cmp
, NULL
);
788 rfd_rib_node
->info
= slRibPt
;
789 route_lock_node(rfd_rib_node
);
790 RFAPI_RIB_PREFIX_COUNT_INCR(rfd
, rfd
->bgp
->rfapi
);
792 skiplist_insert(slRibPt
, &ori
->rk
, ori
);
795 ori
->last_sent_time
= rfapi_time(NULL
);
800 RFAPI_RIB_CHECK_COUNTS(0, 0);
801 rfapiRibStartTimer(rfd
, ori
, rfd_rib_node
, 0);
802 RFAPI_RIB_CHECK_COUNTS(0, 0);
805 * Update last sent time for prefix
807 trn
= route_node_get(rfd
->rsp_times
[afi
],
808 &rfd_rib_node
->p
); /* locks trn */
809 trn
->info
= (void *)(uintptr_t)bgp_clock();
811 route_unlock_node(trn
);
817 * Frees rfapi_info items at node
819 * Adjust 'rib' and 'rib_pending' as follows:
821 * If rib_pending node->info is 1 (magic value):
822 * callback: NHL = RIB NHL with lifetime = withdraw_lifetime_value
823 * RIB = remove all routes at the node
826 * For each item at rib node:
827 * if not present in pending node, move RIB item to "delete list"
829 * For each item at pending rib node:
830 * if present (same vn/un) in rib node with same lifetime & options, drop
831 * matching item from pending node
833 * For each remaining item at pending rib node, add or replace item
836 * Construct NHL as concatenation of pending list + delete list
840 static void process_pending_node(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
,
842 struct route_node
*pn
, /* pending node */
843 struct rfapi_next_hop_entry
**head
,
844 struct rfapi_next_hop_entry
**tail
)
846 struct listnode
*node
= NULL
;
847 struct listnode
*nnode
= NULL
;
848 struct rfapi_info
*ri
= NULL
; /* happy valgrind */
849 struct rfapi_ip_prefix hp
= {0}; /* pfx to put in NHE */
850 struct route_node
*rn
= NULL
;
851 struct skiplist
*slRibPt
= NULL
; /* rib list */
852 struct skiplist
*slPendPt
= NULL
;
853 struct list
*lPendCost
= NULL
;
854 struct list
*delete_list
= NULL
;
855 int printedprefix
= 0;
856 char buf_prefix
[PREFIX_STRLEN
];
857 int rib_node_started_nonempty
= 0;
858 int sendingsomeroutes
= 0;
860 #if DEBUG_PROCESS_PENDING_NODE
861 unsigned int count_rib_initial
= 0;
862 unsigned int count_pend_vn_initial
= 0;
863 unsigned int count_pend_cost_initial
= 0;
867 prefix2str(&pn
->p
, buf_prefix
, sizeof(buf_prefix
));
868 vnc_zlog_debug_verbose("%s: afi=%d, %s pn->info=%p", __func__
, afi
,
869 buf_prefix
, pn
->info
);
871 if (AFI_L2VPN
!= afi
) {
872 rfapiQprefix2Rprefix(&pn
->p
, &hp
);
875 RFAPI_RIB_CHECK_COUNTS(1, 0);
878 * Find corresponding RIB node
880 rn
= route_node_get(rfd
->rib
[afi
], &pn
->p
); /* locks rn */
883 * RIB skiplist has key=rfapi_addr={vn,un}, val = rfapi_info,
884 * skiplist.del = NULL
886 slRibPt
= (struct skiplist
*)rn
->info
;
888 rib_node_started_nonempty
= 1;
890 slPendPt
= (struct skiplist
*)(pn
->aggregate
);
891 lPendCost
= (struct list
*)(pn
->info
);
893 #if DEBUG_PROCESS_PENDING_NODE
896 count_rib_initial
= skiplist_count(slRibPt
);
899 count_pend_vn_initial
= skiplist_count(slPendPt
);
901 if (lPendCost
&& lPendCost
!= (struct list
*)1)
902 count_pend_cost_initial
= lPendCost
->count
;
907 * Handle special case: delete all routes at prefix
909 if (lPendCost
== (struct list
*)1) {
910 vnc_zlog_debug_verbose("%s: lPendCost=1 => delete all",
912 if (slRibPt
&& !skiplist_empty(slRibPt
)) {
913 delete_list
= list_new();
915 == skiplist_first(slRibPt
, NULL
, (void **)&ri
)) {
917 char buf
[PREFIX_STRLEN
];
918 char buf2
[PREFIX_STRLEN
];
920 listnode_add(delete_list
, ri
);
921 vnc_zlog_debug_verbose(
922 "%s: after listnode_add, delete_list->count=%d",
923 __func__
, delete_list
->count
);
924 rfapiFreeBgpTeaOptionChain(ri
->tea_options
);
925 ri
->tea_options
= NULL
;
928 struct rfapi_rib_tcb
*tcb
;
930 tcb
= ((struct thread
*)ri
->timer
)->arg
;
931 thread_cancel(ri
->timer
);
932 XFREE(MTYPE_RFAPI_RECENT_DELETE
, tcb
);
936 prefix2str(&ri
->rk
.vn
, buf
, sizeof(buf
));
937 prefix2str(&ri
->un
, buf2
, sizeof(buf2
));
938 vnc_zlog_debug_verbose(
939 "%s: put dl pfx=%s vn=%s un=%s cost=%d life=%d vn_options=%p",
940 __func__
, buf_prefix
, buf
, buf2
,
941 ri
->cost
, ri
->lifetime
, ri
->vn_options
);
943 skiplist_delete_first(slRibPt
);
946 assert(skiplist_empty(slRibPt
));
948 skiplist_free(slRibPt
);
949 rn
->info
= slRibPt
= NULL
;
950 route_unlock_node(rn
);
952 lPendCost
= pn
->info
= NULL
;
953 route_unlock_node(pn
);
958 skiplist_free(slRibPt
);
960 route_unlock_node(rn
);
964 if (slPendPt
) { /* TBD I think we can toss this block */
965 skiplist_free(slPendPt
);
966 pn
->aggregate
= NULL
;
967 route_unlock_node(pn
);
971 route_unlock_node(pn
);
973 route_unlock_node(rn
); /* route_node_get() */
975 if (rib_node_started_nonempty
) {
976 RFAPI_RIB_PREFIX_COUNT_DECR(rfd
, bgp
->rfapi
);
979 RFAPI_RIB_CHECK_COUNTS(1, 0);
984 vnc_zlog_debug_verbose("%s: lPendCost->count=%d, slRibPt->count=%d",
986 (lPendCost
? (int)lPendCost
->count
: -1),
987 (slRibPt
? (int)slRibPt
->count
: -1));
990 * Iterate over routes at RIB Node.
991 * If not found at Pending Node, delete from RIB Node and add to
993 * If found at Pending Node
994 * If identical rfapi_info, delete from Pending Node
998 struct rfapi_info
*ori
;
1001 * Iterate over RIB List
1004 while (!skiplist_next(slRibPt
, NULL
, (void **)&ori
, &cursor
)) {
1006 if (skiplist_search(slPendPt
, &ori
->rk
, (void **)&ri
)) {
1008 * Not in Pending list, so it should be deleted
1011 delete_list
= list_new();
1012 listnode_add(delete_list
, ori
);
1013 rfapiFreeBgpTeaOptionChain(ori
->tea_options
);
1014 ori
->tea_options
= NULL
;
1016 struct rfapi_rib_tcb
*tcb
;
1018 tcb
= ((struct thread
*)ori
->timer
)
1020 thread_cancel(ori
->timer
);
1021 XFREE(MTYPE_RFAPI_RECENT_DELETE
, tcb
);
1025 #if DEBUG_PROCESS_PENDING_NODE
1026 /* deleted from slRibPt below, after we're done
1028 vnc_zlog_debug_verbose(
1029 "%s: slRibPt ri %p not matched in pending list, delete",
1035 * Found in pending list. If same lifetime,
1037 * then remove from pending list because the
1041 if (!rfapi_info_cmp(ori
, ri
)) {
1042 skiplist_delete(slPendPt
, &ri
->rk
,
1046 /* linear walk: might need
1048 listnode_delete(lPendCost
,
1058 #if DEBUG_PROCESS_PENDING_NODE
1059 vnc_zlog_debug_verbose(
1060 "%s: slRibPt ri %p matched in pending list, %s",
1063 : "different info"));
1068 * Go back and delete items from RIB
1071 for (ALL_LIST_ELEMENTS_RO(delete_list
, node
, ri
)) {
1072 vnc_zlog_debug_verbose(
1073 "%s: deleting ri %p from slRibPt",
1075 assert(!skiplist_delete(slRibPt
, &ri
->rk
,
1078 if (skiplist_empty(slRibPt
)) {
1079 skiplist_free(slRibPt
);
1080 slRibPt
= rn
->info
= NULL
;
1081 route_unlock_node(rn
);
1086 RFAPI_RIB_CHECK_COUNTS(0, (delete_list
? delete_list
->count
: 0));
1089 * Iterate over routes at Pending Node
1091 * If {vn} found at RIB Node, update RIB Node route contents to match PN
1092 * If {vn} NOT found at RIB Node, add copy to RIB Node
1095 for (ALL_LIST_ELEMENTS_RO(lPendCost
, node
, ri
)) {
1097 struct rfapi_info
*ori
;
1100 && !skiplist_search(slRibPt
, &ri
->rk
,
1103 /* found: update contents of existing route in
1106 ori
->cost
= ri
->cost
;
1107 ori
->lifetime
= ri
->lifetime
;
1108 rfapiFreeBgpTeaOptionChain(ori
->tea_options
);
1110 rfapiOptionsDup(ri
->tea_options
);
1111 ori
->last_sent_time
= rfapi_time(NULL
);
1113 rfapiFreeRfapiVnOptionChain(ori
->vn_options
);
1115 rfapiVnOptionsDup(ri
->vn_options
);
1117 rfapiFreeRfapiUnOptionChain(ori
->un_options
);
1119 rfapiUnOptionsDup(ri
->un_options
);
1121 vnc_zlog_debug_verbose(
1122 "%s: matched lPendCost item %p in slRibPt, rewrote",
1127 char buf_rd
[RD_ADDRSTRLEN
];
1129 /* not found: add new route to RIB */
1130 ori
= rfapi_info_new();
1133 ori
->cost
= ri
->cost
;
1134 ori
->lifetime
= ri
->lifetime
;
1136 rfapiOptionsDup(ri
->tea_options
);
1137 ori
->last_sent_time
= rfapi_time(NULL
);
1139 rfapiVnOptionsDup(ri
->vn_options
);
1141 rfapiUnOptionsDup(ri
->un_options
);
1144 slRibPt
= skiplist_new(
1145 0, rfapi_rib_key_cmp
, NULL
);
1147 route_lock_node(rn
);
1149 skiplist_insert(slRibPt
, &ori
->rk
, ori
);
1152 prefix_rd2str(&ori
->rk
.rd
, buf_rd
,
1158 vnc_zlog_debug_verbose(
1159 "%s: nomatch lPendCost item %p in slRibPt, added (rd=%s)",
1160 __func__
, ri
, buf_rd
);
1166 RFAPI_RIB_CHECK_COUNTS(
1167 0, (delete_list
? delete_list
->count
: 0));
1168 rfapiRibStartTimer(rfd
, ori
, rn
, 0);
1169 RFAPI_RIB_CHECK_COUNTS(
1170 0, (delete_list
? delete_list
->count
: 0));
1177 * Construct NHL as concatenation of pending list + delete list
1181 RFAPI_RIB_CHECK_COUNTS(0, (delete_list
? delete_list
->count
: 0));
1188 vnc_zlog_debug_verbose("%s: lPendCost->count now %d", __func__
,
1190 vnc_zlog_debug_verbose("%s: For prefix %s (a)", __func__
,
1194 for (ALL_LIST_ELEMENTS(lPendCost
, node
, nnode
, ri
)) {
1196 struct rfapi_next_hop_entry
*new;
1197 struct route_node
*trn
;
1199 new = XCALLOC(MTYPE_RFAPI_NEXTHOP
,
1200 sizeof(struct rfapi_next_hop_entry
));
1203 if (ri
->rk
.aux_prefix
.family
) {
1204 rfapiQprefix2Rprefix(&ri
->rk
.aux_prefix
,
1208 if (AFI_L2VPN
== afi
) {
1209 /* hp is 0; need to set length to match
1211 new->prefix
.length
=
1212 (ri
->rk
.vn
.family
== AF_INET
)
1217 new->prefix
.cost
= ri
->cost
;
1218 new->lifetime
= ri
->lifetime
;
1219 rfapiQprefix2Raddr(&ri
->rk
.vn
, &new->vn_address
);
1220 rfapiQprefix2Raddr(&ri
->un
, &new->un_address
);
1221 /* free option chain from ri */
1222 rfapiFreeBgpTeaOptionChain(ri
->tea_options
);
1225 NULL
; /* option chain was transferred to NHL */
1227 new->vn_options
= ri
->vn_options
;
1229 NULL
; /* option chain was transferred to NHL */
1231 new->un_options
= ri
->un_options
;
1233 NULL
; /* option chain was transferred to NHL */
1236 (*tail
)->next
= new;
1241 sendingsomeroutes
= 1;
1243 ++rfd
->stat_count_nh_reachable
;
1244 ++bgp
->rfapi
->stat
.count_updated_response_updates
;
1247 * update this NVE's timestamp for this prefix
1249 trn
= route_node_get(rfd
->rsp_times
[afi
],
1250 &pn
->p
); /* locks trn */
1251 trn
->info
= (void *)(uintptr_t)bgp_clock();
1253 route_unlock_node(trn
);
1255 rfapiRfapiIpAddr2Str(&new->vn_address
, buf
, BUFSIZ
);
1256 rfapiRfapiIpAddr2Str(&new->un_address
, buf2
, BUFSIZ
);
1257 vnc_zlog_debug_verbose(
1258 "%s: add vn=%s un=%s cost=%d life=%d",
1259 __func__
, buf
, buf2
, new->prefix
.cost
,
1264 RFAPI_RIB_CHECK_COUNTS(0, (delete_list
? delete_list
->count
: 0));
1271 if (!printedprefix
) {
1272 vnc_zlog_debug_verbose("%s: For prefix %s (d)",
1273 __func__
, buf_prefix
);
1275 vnc_zlog_debug_verbose("%s: delete_list has %d elements",
1276 __func__
, delete_list
->count
);
1278 RFAPI_RIB_CHECK_COUNTS(0, delete_list
->count
);
1279 if (!CHECK_FLAG(bgp
->rfapi_cfg
->flags
,
1280 BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE
)) {
1282 for (ALL_LIST_ELEMENTS(delete_list
, node
, nnode
, ri
)) {
1284 struct rfapi_next_hop_entry
*new;
1285 struct rfapi_info
*ri_del
;
1287 RFAPI_RIB_CHECK_COUNTS(0, delete_list
->count
);
1289 MTYPE_RFAPI_NEXTHOP
,
1290 sizeof(struct rfapi_next_hop_entry
));
1293 if (ri
->rk
.aux_prefix
.family
) {
1294 rfapiQprefix2Rprefix(&ri
->rk
.aux_prefix
,
1298 if (AFI_L2VPN
== afi
) {
1299 /* hp is 0; need to set length
1300 * to match AF of vn */
1301 new->prefix
.length
=
1309 new->prefix
.cost
= ri
->cost
;
1310 new->lifetime
= RFAPI_REMOVE_RESPONSE_LIFETIME
;
1311 rfapiQprefix2Raddr(&ri
->rk
.vn
,
1313 rfapiQprefix2Raddr(&ri
->un
, &new->un_address
);
1315 new->vn_options
= ri
->vn_options
;
1316 ri
->vn_options
= NULL
; /* option chain was
1317 transferred to NHL */
1319 new->un_options
= ri
->un_options
;
1320 ri
->un_options
= NULL
; /* option chain was
1321 transferred to NHL */
1324 (*tail
)->next
= new;
1329 ++rfd
->stat_count_nh_removal
;
1331 .count_updated_response_deletes
;
1333 rfapiRfapiIpAddr2Str(&new->vn_address
, buf
,
1335 rfapiRfapiIpAddr2Str(&new->un_address
, buf2
,
1337 vnc_zlog_debug_verbose(
1338 "%s: DEL vn=%s un=%s cost=%d life=%d",
1339 __func__
, buf
, buf2
, new->prefix
.cost
,
1342 RFAPI_RIB_CHECK_COUNTS(0, delete_list
->count
);
1344 * Update/add to list of recent deletions at
1347 if (!rn
->aggregate
) {
1348 rn
->aggregate
= skiplist_new(
1349 0, rfapi_rib_key_cmp
,
1352 route_lock_node(rn
);
1354 RFAPI_RIB_CHECK_COUNTS(0, delete_list
->count
);
1356 /* sanity check lifetime */
1358 > RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY
)
1360 RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY
;
1362 RFAPI_RIB_CHECK_COUNTS(0, delete_list
->count
);
1363 /* cancel normal expire timer */
1365 struct rfapi_rib_tcb
*tcb
;
1367 tcb
= ((struct thread
*)ri
->timer
)->arg
;
1369 (struct thread
*)ri
->timer
);
1370 XFREE(MTYPE_RFAPI_RECENT_DELETE
, tcb
);
1373 RFAPI_RIB_CHECK_COUNTS(0, delete_list
->count
);
1376 * Look in "recently-deleted" list
1378 if (skiplist_search(
1379 (struct skiplist
*)(rn
->aggregate
),
1380 &ri
->rk
, (void **)&ri_del
)) {
1384 RFAPI_RIB_CHECK_COUNTS(
1385 0, delete_list
->count
);
1387 * NOT in "recently-deleted" list
1391 node
); /* does not free ri */
1392 rc
= skiplist_insert(
1398 RFAPI_RIB_CHECK_COUNTS(
1399 0, delete_list
->count
);
1400 rfapiRibStartTimer(rfd
, ri
, rn
, 1);
1401 RFAPI_RIB_CHECK_COUNTS(
1402 0, delete_list
->count
);
1403 ri
->last_sent_time
= rfapi_time(NULL
);
1406 char buf_rd
[RD_ADDRSTRLEN
];
1408 vnc_zlog_debug_verbose(
1409 "%s: move route to recently deleted list, rd=%s",
1420 * IN "recently-deleted" list
1422 RFAPI_RIB_CHECK_COUNTS(
1423 0, delete_list
->count
);
1424 rfapiRibStartTimer(rfd
, ri_del
, rn
, 1);
1425 RFAPI_RIB_CHECK_COUNTS(
1426 0, delete_list
->count
);
1427 ri
->last_sent_time
= rfapi_time(NULL
);
1431 vnc_zlog_debug_verbose(
1432 "%s: response removal disabled, omitting removals",
1436 delete_list
->del
= (void (*)(void *))rfapi_info_free
;
1437 list_delete_and_null(&delete_list
);
1440 RFAPI_RIB_CHECK_COUNTS(0, 0);
1443 * Reset pending lists. The final route_unlock_node() will probably
1444 * cause the pending node to be released.
1447 skiplist_free(slPendPt
);
1448 pn
->aggregate
= NULL
;
1449 route_unlock_node(pn
);
1452 list_delete_and_null(&lPendCost
);
1454 route_unlock_node(pn
);
1456 RFAPI_RIB_CHECK_COUNTS(0, 0);
1458 if (rib_node_started_nonempty
) {
1460 RFAPI_RIB_PREFIX_COUNT_DECR(rfd
, bgp
->rfapi
);
1464 RFAPI_RIB_PREFIX_COUNT_INCR(rfd
, bgp
->rfapi
);
1468 if (sendingsomeroutes
)
1469 rfapiMonitorTimersRestart(rfd
, &pn
->p
);
1471 route_unlock_node(rn
); /* route_node_get() */
1473 RFAPI_RIB_CHECK_COUNTS(1, 0);
1477 * regardless of targets, construct a single callback by doing
1478 * only one traversal of the pending RIB
1484 static void rib_do_callback_onepass(struct rfapi_descriptor
*rfd
, afi_t afi
)
1486 struct bgp
*bgp
= bgp_get_default();
1487 struct rfapi_next_hop_entry
*head
= NULL
;
1488 struct rfapi_next_hop_entry
*tail
= NULL
;
1489 struct route_node
*rn
;
1492 vnc_zlog_debug_verbose("%s: rfd=%p, afi=%d", __func__
, rfd
, afi
);
1495 if (!rfd
->rib_pending
[afi
])
1500 for (rn
= route_top(rfd
->rib_pending
[afi
]); rn
; rn
= route_next(rn
)) {
1501 process_pending_node(bgp
, rfd
, afi
, rn
, &head
, &tail
);
1505 rfapi_response_cb_t
*f
;
1508 vnc_zlog_debug_verbose("%s: response callback NHL follows:",
1510 rfapiPrintNhl(NULL
, head
);
1513 if (rfd
->response_cb
)
1514 f
= rfd
->response_cb
;
1516 f
= bgp
->rfapi
->rfp_methods
.response_cb
;
1518 bgp
->rfapi
->flags
|= RFAPI_INCALLBACK
;
1519 vnc_zlog_debug_verbose("%s: invoking updated response callback",
1521 (*f
)(head
, rfd
->cookie
);
1522 bgp
->rfapi
->flags
&= ~RFAPI_INCALLBACK
;
1523 ++bgp
->rfapi
->response_updated_count
;
1527 static wq_item_status
rfapiRibDoQueuedCallback(struct work_queue
*wq
,
1530 struct rfapi_descriptor
*rfd
;
1532 uint32_t queued_flag
;
1534 RFAPI_RIB_CHECK_COUNTS(1, 0);
1536 rfd
= ((struct rfapi_updated_responses_queue
*)data
)->rfd
;
1537 afi
= ((struct rfapi_updated_responses_queue
*)data
)->afi
;
1539 /* Make sure the HD wasn't closed after the work item was scheduled */
1540 if (rfapi_check(rfd
))
1543 rib_do_callback_onepass(rfd
, afi
);
1545 queued_flag
= RFAPI_QUEUED_FLAG(afi
);
1547 UNSET_FLAG(rfd
->flags
, queued_flag
);
1549 RFAPI_RIB_CHECK_COUNTS(1, 0);
1554 static void rfapiRibQueueItemDelete(struct work_queue
*wq
, void *data
)
1556 XFREE(MTYPE_RFAPI_UPDATED_RESPONSE_QUEUE
, data
);
1559 static void updated_responses_queue_init(struct rfapi_descriptor
*rfd
)
1561 if (rfd
->updated_responses_queue
)
1564 rfd
->updated_responses_queue
=
1565 work_queue_new(bm
->master
, "rfapi updated responses");
1566 assert(rfd
->updated_responses_queue
);
1568 rfd
->updated_responses_queue
->spec
.workfunc
= rfapiRibDoQueuedCallback
;
1569 rfd
->updated_responses_queue
->spec
.del_item_data
=
1570 rfapiRibQueueItemDelete
;
1571 rfd
->updated_responses_queue
->spec
.max_retries
= 0;
1572 rfd
->updated_responses_queue
->spec
.hold
= 1;
1576 * Called when an import table node is modified. Construct a
1577 * new complete nexthop list, sorted by cost (lowest first),
1578 * based on the import table node.
1580 * Filter out duplicate nexthops (vn address). There should be
1581 * only one UN address per VN address from the point of view of
1582 * a given import table, so we can probably ignore UN addresses
1585 * Based on rfapiNhlAddNodeRoutes()
1587 void rfapiRibUpdatePendingNode(
1588 struct bgp
*bgp
, struct rfapi_descriptor
*rfd
,
1589 struct rfapi_import_table
*it
, /* needed for L2 */
1590 struct route_node
*it_node
, uint32_t lifetime
)
1592 struct prefix
*prefix
;
1593 struct bgp_info
*bi
;
1594 struct route_node
*pn
;
1596 uint32_t queued_flag
;
1598 char buf
[PREFIX_STRLEN
];
1600 vnc_zlog_debug_verbose("%s: entry", __func__
);
1602 if (CHECK_FLAG(bgp
->rfapi_cfg
->flags
, BGP_VNC_CONFIG_CALLBACK_DISABLE
))
1605 vnc_zlog_debug_verbose("%s: callbacks are not disabled", __func__
);
1607 RFAPI_RIB_CHECK_COUNTS(1, 0);
1609 prefix
= &it_node
->p
;
1610 afi
= family2afi(prefix
->family
);
1611 prefix2str(prefix
, buf
, sizeof(buf
));
1612 vnc_zlog_debug_verbose("%s: prefix=%s", __func__
, buf
);
1614 pn
= route_node_get(rfd
->rib_pending
[afi
], prefix
);
1617 vnc_zlog_debug_verbose("%s: pn->info=%p, pn->aggregate=%p", __func__
,
1618 pn
->info
, pn
->aggregate
);
1620 if (pn
->aggregate
) {
1622 * free references into the rfapi_info structures before
1623 * freeing the structures themselves
1625 skiplist_free((struct skiplist
*)(pn
->aggregate
));
1626 pn
->aggregate
= NULL
;
1627 route_unlock_node(pn
); /* skiplist deleted */
1632 * free the rfapi_info structures
1635 if (pn
->info
!= (void *)1) {
1636 list_delete_and_null((struct list
**)(&pn
->info
));
1639 route_unlock_node(pn
); /* linklist or 1 deleted */
1643 * The BIs in the import table are already sorted by cost
1645 for (bi
= it_node
->info
; bi
; bi
= bi
->next
) {
1647 struct rfapi_info
*ri
;
1648 struct prefix pfx_nh
;
1651 /* shouldn't happen */
1652 /* TBD increment error stats counter */
1656 /* shouldn't happen */
1657 /* TBD increment error stats counter */
1661 rfapiNexthop2Prefix(bi
->attr
, &pfx_nh
);
1664 * Omit route if nexthop is self
1666 if (CHECK_FLAG(bgp
->rfapi_cfg
->flags
,
1667 BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP
)) {
1669 struct prefix pfx_vn
;
1671 assert(!rfapiRaddr2Qprefix(&rfd
->vn_addr
, &pfx_vn
));
1672 if (prefix_same(&pfx_vn
, &pfx_nh
))
1676 ri
= rfapi_info_new();
1678 ri
->rk
.rd
= bi
->extra
->vnc
.import
.rd
;
1680 * If there is an auxiliary IP address (L2 can have it), copy it
1682 if (bi
->extra
->vnc
.import
.aux_prefix
.family
) {
1683 ri
->rk
.aux_prefix
= bi
->extra
->vnc
.import
.aux_prefix
;
1686 if (rfapiGetUnAddrOfVpnBi(bi
, &ri
->un
)) {
1687 rfapi_info_free(ri
);
1691 if (!pn
->aggregate
) {
1693 skiplist_new(0, rfapi_rib_key_cmp
, NULL
);
1694 route_lock_node(pn
);
1698 * If we have already added this nexthop, the insert will fail.
1699 * Note that the skiplist key is a pointer INTO the rfapi_info
1700 * structure which will be added to the "info" list.
1701 * The skiplist entry VALUE is not used for anything but
1702 * might be useful during debugging.
1704 if (skiplist_insert((struct skiplist
*)pn
->aggregate
, &ri
->rk
,
1710 rfapi_info_free(ri
);
1714 rfapiRibBi2Ri(bi
, ri
, lifetime
);
1717 pn
->info
= list_new();
1718 ((struct list
*)(pn
->info
))->del
=
1719 (void (*)(void *))rfapi_info_free
;
1720 route_lock_node(pn
);
1723 listnode_add((struct list
*)(pn
->info
), ri
);
1727 count
= ((struct list
*)(pn
->info
))->count
;
1732 assert(!pn
->aggregate
);
1733 pn
->info
= (void *)1; /* magic value means this node has no
1735 route_lock_node(pn
);
1738 route_unlock_node(pn
); /* route_node_get */
1740 queued_flag
= RFAPI_QUEUED_FLAG(afi
);
1742 if (!CHECK_FLAG(rfd
->flags
, queued_flag
)) {
1744 struct rfapi_updated_responses_queue
*urq
;
1746 urq
= XCALLOC(MTYPE_RFAPI_UPDATED_RESPONSE_QUEUE
,
1747 sizeof(struct rfapi_updated_responses_queue
));
1749 if (!rfd
->updated_responses_queue
)
1750 updated_responses_queue_init(rfd
);
1752 SET_FLAG(rfd
->flags
, queued_flag
);
1755 work_queue_add(rfd
->updated_responses_queue
, urq
);
1757 RFAPI_RIB_CHECK_COUNTS(1, 0);
1760 void rfapiRibUpdatePendingNodeSubtree(
1761 struct bgp
*bgp
, struct rfapi_descriptor
*rfd
,
1762 struct rfapi_import_table
*it
, struct route_node
*it_node
,
1763 struct route_node
*omit_subtree
, /* may be NULL */
1766 /* FIXME: need to find a better way here to work without sticking our
1767 * hands in node->link */
1768 if (it_node
->l_left
&& (it_node
->l_left
!= omit_subtree
)) {
1769 if (it_node
->l_left
->info
)
1770 rfapiRibUpdatePendingNode(bgp
, rfd
, it
, it_node
->l_left
,
1772 rfapiRibUpdatePendingNodeSubtree(bgp
, rfd
, it
, it_node
->l_left
,
1773 omit_subtree
, lifetime
);
1776 if (it_node
->l_right
&& (it_node
->l_right
!= omit_subtree
)) {
1777 if (it_node
->l_right
->info
)
1778 rfapiRibUpdatePendingNode(bgp
, rfd
, it
,
1779 it_node
->l_right
, lifetime
);
1780 rfapiRibUpdatePendingNodeSubtree(bgp
, rfd
, it
, it_node
->l_right
,
1781 omit_subtree
, lifetime
);
1788 * 0 allow prefix to be included in response
1789 * !0 don't allow prefix to be included in response
1791 int rfapiRibFTDFilterRecentPrefix(
1792 struct rfapi_descriptor
*rfd
,
1793 struct route_node
*it_rn
, /* import table node */
1794 struct prefix
*pfx_target_original
) /* query target */
1796 struct bgp
*bgp
= rfd
->bgp
;
1797 afi_t afi
= family2afi(it_rn
->p
.family
);
1799 struct route_node
*trn
;
1802 * Not in FTD mode, so allow prefix
1804 if (bgp
->rfapi_cfg
->rfp_cfg
.download_type
!= RFAPI_RFP_DOWNLOAD_FULL
)
1809 * This matches behavior of now-obsolete rfapiRibFTDFilterRecent(),
1810 * but we need to decide if that is correct.
1812 if (it_rn
->p
.family
== AF_ETHERNET
)
1815 #if DEBUG_FTD_FILTER_RECENT
1817 char buf_pfx
[PREFIX_STRLEN
];
1819 prefix2str(&it_rn
->p
, buf_pfx
, sizeof(buf_pfx
));
1820 vnc_zlog_debug_verbose("%s: prefix %s", __func__
, buf_pfx
);
1825 * prefix covers target address, so allow prefix
1827 if (prefix_match(&it_rn
->p
, pfx_target_original
)) {
1828 #if DEBUG_FTD_FILTER_RECENT
1829 vnc_zlog_debug_verbose("%s: prefix covers target, allowed",
1836 * check this NVE's timestamp for this prefix
1838 trn
= route_node_get(rfd
->rsp_times
[afi
], &it_rn
->p
); /* locks trn */
1839 prefix_time
= (time_t)trn
->info
;
1841 route_unlock_node(trn
);
1843 #if DEBUG_FTD_FILTER_RECENT
1844 vnc_zlog_debug_verbose("%s: last sent time %lu, last allowed time %lu",
1845 __func__
, prefix_time
,
1846 rfd
->ftd_last_allowed_time
);
1850 * haven't sent this prefix, which doesn't cover target address,
1851 * to NVE since ftd_advertisement_interval, so OK to send now.
1853 if (prefix_time
<= rfd
->ftd_last_allowed_time
)
1860 * Call when rfapi returns from rfapi_query() so the RIB reflects
1861 * the routes sent to the NVE before the first updated response
1863 * Also: remove duplicates from response. Caller should use returned
1864 * value of nexthop chain.
1866 struct rfapi_next_hop_entry
*
1867 rfapiRibPreload(struct bgp
*bgp
, struct rfapi_descriptor
*rfd
,
1868 struct rfapi_next_hop_entry
*response
, int use_eth_resolution
)
1870 struct rfapi_next_hop_entry
*nhp
;
1871 struct rfapi_next_hop_entry
*nhp_next
;
1872 struct rfapi_next_hop_entry
*head
= NULL
;
1873 struct rfapi_next_hop_entry
*tail
= NULL
;
1874 time_t new_last_sent_time
;
1876 vnc_zlog_debug_verbose("%s: loading response=%p, use_eth_resolution=%d",
1877 __func__
, response
, use_eth_resolution
);
1879 new_last_sent_time
= rfapi_time(NULL
);
1881 for (nhp
= response
; nhp
; nhp
= nhp_next
) {
1884 struct rfapi_rib_key rk
;
1886 struct rfapi_info
*ri
;
1888 struct route_node
*rn
;
1889 int rib_node_started_nonempty
= 0;
1890 struct route_node
*trn
;
1893 /* save in case we delete nhp */
1894 nhp_next
= nhp
->next
;
1896 if (nhp
->lifetime
== RFAPI_REMOVE_RESPONSE_LIFETIME
) {
1898 * weird, shouldn't happen
1900 vnc_zlog_debug_verbose(
1901 "%s: got nhp->lifetime == RFAPI_REMOVE_RESPONSE_LIFETIME",
1907 if (use_eth_resolution
) {
1908 /* get the prefix of the ethernet address in the L2
1910 struct rfapi_l2address_option
*pL2o
;
1911 struct rfapi_vn_option
*vo
;
1914 * Look for VN option of type
1915 * RFAPI_VN_OPTION_TYPE_L2ADDR
1917 for (pL2o
= NULL
, vo
= nhp
->vn_options
; vo
;
1919 if (RFAPI_VN_OPTION_TYPE_L2ADDR
== vo
->type
) {
1920 pL2o
= &vo
->v
.l2addr
;
1927 * not supposed to happen
1929 vnc_zlog_debug_verbose("%s: missing L2 info",
1935 rfapiL2o2Qprefix(pL2o
, &pfx
);
1937 rfapiRprefix2Qprefix(&nhp
->prefix
, &pfx
);
1938 afi
= family2afi(pfx
.family
);
1942 * TBD for ethernet, rib must know the right way to distinguish
1945 * Current approach: prefix is key to radix tree; then
1946 * each prefix has a set of routes with unique VN addrs
1950 * Look up prefix in RIB
1952 rn
= route_node_get(rfd
->rib
[afi
], &pfx
); /* locks rn */
1955 rib_node_started_nonempty
= 1;
1957 rn
->info
= skiplist_new(0, rfapi_rib_key_cmp
, NULL
);
1958 route_lock_node(rn
);
1962 * Look up route at prefix
1965 memset((void *)&rk
, 0, sizeof(rk
));
1966 assert(!rfapiRaddr2Qprefix(&nhp
->vn_address
, &rk
.vn
));
1968 if (use_eth_resolution
) {
1969 /* copy what came from aux_prefix to rk.aux_prefix */
1970 rfapiRprefix2Qprefix(&nhp
->prefix
, &rk
.aux_prefix
);
1971 if (RFAPI_0_PREFIX(&rk
.aux_prefix
)
1972 && RFAPI_HOST_PREFIX(&rk
.aux_prefix
)) {
1973 /* mark as "none" if nhp->prefix is 0/32 or
1975 rk
.aux_prefix
.family
= 0;
1981 char str_vn
[PREFIX_STRLEN
];
1982 char str_aux_prefix
[PREFIX_STRLEN
];
1985 str_aux_prefix
[0] = 0;
1987 prefix2str(&rk
.vn
, str_vn
, sizeof(str_vn
));
1988 prefix2str(&rk
.aux_prefix
, str_aux_prefix
,
1989 sizeof(str_aux_prefix
));
1991 if (!rk
.aux_prefix
.family
) {
1993 vnc_zlog_debug_verbose(
1994 "%s: rk.vn=%s rk.aux_prefix=%s", __func__
,
1996 (rk
.aux_prefix
.family
? str_aux_prefix
: "-"));
1998 vnc_zlog_debug_verbose(
1999 "%s: RIB skiplist for this prefix follows", __func__
);
2000 rfapiRibShowRibSl(NULL
, &rn
->p
, (struct skiplist
*)rn
->info
);
2004 if (!skiplist_search((struct skiplist
*)rn
->info
, &rk
,
2007 * Already have this route; make values match
2009 rfapiFreeRfapiUnOptionChain(ri
->un_options
);
2010 ri
->un_options
= NULL
;
2011 rfapiFreeRfapiVnOptionChain(ri
->vn_options
);
2012 ri
->vn_options
= NULL
;
2015 vnc_zlog_debug_verbose("%s: found in RIB", __func__
);
2019 * Filter duplicate routes from initial response.
2020 * Check timestamps to avoid wraparound problems
2022 if ((ri
->rsp_counter
!= rfd
->rsp_counter
)
2023 || (ri
->last_sent_time
!= new_last_sent_time
)) {
2026 vnc_zlog_debug_verbose(
2027 "%s: allowed due to counter/timestamp diff",
2036 vnc_zlog_debug_verbose(
2037 "%s: allowed due to not yet in RIB", __func__
);
2039 /* not found: add new route to RIB */
2040 ri
= rfapi_info_new();
2046 assert(!rfapiRaddr2Qprefix(&nhp
->un_address
, &ri
->un
));
2047 ri
->cost
= nhp
->prefix
.cost
;
2048 ri
->lifetime
= nhp
->lifetime
;
2049 ri
->vn_options
= rfapiVnOptionsDup(nhp
->vn_options
);
2050 ri
->rsp_counter
= rfd
->rsp_counter
;
2051 ri
->last_sent_time
= rfapi_time(NULL
);
2055 rc
= skiplist_insert((struct skiplist
*)rn
->info
,
2060 if (!rib_node_started_nonempty
) {
2061 RFAPI_RIB_PREFIX_COUNT_INCR(rfd
, bgp
->rfapi
);
2064 RFAPI_RIB_CHECK_COUNTS(0, 0);
2065 rfapiRibStartTimer(rfd
, ri
, rn
, 0);
2066 RFAPI_RIB_CHECK_COUNTS(0, 0);
2068 route_unlock_node(rn
);
2071 * update this NVE's timestamp for this prefix
2073 trn
= route_node_get(rfd
->rsp_times
[afi
], &pfx
); /* locks trn */
2074 trn
->info
= (void *)(uintptr_t)bgp_clock();
2076 route_unlock_node(trn
);
2079 char str_pfx
[PREFIX_STRLEN
];
2080 char str_pfx_vn
[PREFIX_STRLEN
];
2082 prefix2str(&pfx
, str_pfx
, sizeof(str_pfx
));
2083 prefix2str(&rk
.vn
, str_pfx_vn
, sizeof(str_pfx_vn
));
2084 vnc_zlog_debug_verbose(
2085 "%s: added pfx=%s nh[vn]=%s, cost=%u, lifetime=%u, allowed=%d",
2086 __func__
, str_pfx
, str_pfx_vn
, nhp
->prefix
.cost
,
2087 nhp
->lifetime
, allowed
);
2098 rfapi_un_options_free(nhp
->un_options
);
2099 nhp
->un_options
= NULL
;
2100 rfapi_vn_options_free(nhp
->vn_options
);
2101 nhp
->vn_options
= NULL
;
2103 XFREE(MTYPE_RFAPI_NEXTHOP
, nhp
);
2113 void rfapiRibPendingDeleteRoute(struct bgp
*bgp
, struct rfapi_import_table
*it
,
2114 afi_t afi
, struct route_node
*it_node
)
2116 struct rfapi_descriptor
*rfd
;
2117 struct listnode
*node
;
2118 char buf
[PREFIX_STRLEN
];
2120 prefix2str(&it_node
->p
, buf
, sizeof(buf
));
2121 vnc_zlog_debug_verbose("%s: entry, it=%p, afi=%d, it_node=%p, pfx=%s",
2122 __func__
, it
, afi
, it_node
, buf
);
2124 if (AFI_L2VPN
== afi
) {
2126 * ethernet import tables are per-LNI and each ethernet monitor
2127 * identifies the rfd that owns it.
2129 struct rfapi_monitor_eth
*m
;
2130 struct route_node
*rn
;
2131 struct skiplist
*sl
;
2136 * route-specific monitors
2138 if ((sl
= RFAPI_MONITOR_ETH(it_node
))) {
2140 vnc_zlog_debug_verbose(
2141 "%s: route-specific skiplist: %p", __func__
,
2145 rc
= skiplist_next(sl
, NULL
, (void **)&m
,
2147 !rc
; rc
= skiplist_next(sl
, NULL
, (void **)&m
,
2148 (void **)&cursor
)) {
2150 #if DEBUG_PENDING_DELETE_ROUTE
2151 vnc_zlog_debug_verbose("%s: eth monitor rfd=%p",
2155 * If we have already sent a route with this
2157 * NVE, it's OK to send an update with the
2160 if ((rn
= route_node_lookup(m
->rfd
->rib
[afi
],
2162 rfapiRibUpdatePendingNode(
2163 bgp
, m
->rfd
, it
, it_node
,
2164 m
->rfd
->response_lifetime
);
2165 route_unlock_node(rn
);
2171 * all-routes/FTD monitors
2173 for (m
= it
->eth0_queries
; m
; m
= m
->next
) {
2174 #if DEBUG_PENDING_DELETE_ROUTE
2175 vnc_zlog_debug_verbose("%s: eth0 monitor rfd=%p",
2179 * If we have already sent a route with this prefix to
2181 * NVE, it's OK to send an update with the delete
2183 if ((rn
= route_node_lookup(m
->rfd
->rib
[afi
],
2185 rfapiRibUpdatePendingNode(
2186 bgp
, m
->rfd
, it
, it_node
,
2187 m
->rfd
->response_lifetime
);
2193 * Find RFDs that reference this import table
2195 for (ALL_LIST_ELEMENTS_RO(&bgp
->rfapi
->descriptors
, node
,
2198 struct route_node
*rn
;
2200 vnc_zlog_debug_verbose(
2201 "%s: comparing rfd(%p)->import_table=%p to it=%p",
2202 __func__
, rfd
, rfd
->import_table
, it
);
2204 if (rfd
->import_table
!= it
)
2207 vnc_zlog_debug_verbose("%s: matched rfd %p", __func__
,
2211 * If we have sent a response to this NVE with this
2213 * previously, we should send an updated response.
2215 if ((rn
= route_node_lookup(rfd
->rib
[afi
],
2217 rfapiRibUpdatePendingNode(
2218 bgp
, rfd
, it
, it_node
,
2219 rfd
->response_lifetime
);
2220 route_unlock_node(rn
);
2226 void rfapiRibShowResponsesSummary(void *stream
)
2228 int (*fp
)(void *, const char *, ...);
2231 const char *vty_newline
;
2232 struct bgp
*bgp
= bgp_get_default();
2235 int nves_with_nonempty_ribs
= 0;
2236 struct rfapi_descriptor
*rfd
;
2237 struct listnode
*node
;
2239 if (rfapiStream2Vty(stream
, &fp
, &vty
, &out
, &vty_newline
) == 0)
2242 fp(out
, "Unable to find default BGP instance\n");
2246 fp(out
, "%-24s ", "Responses: (Prefixes)");
2247 fp(out
, "%-8s %-8u ", "Active:", bgp
->rfapi
->rib_prefix_count_total
);
2248 fp(out
, "%-8s %-8u",
2249 "Maximum:", bgp
->rfapi
->rib_prefix_count_total_max
);
2252 fp(out
, "%-24s ", " (Updated)");
2253 fp(out
, "%-8s %-8u ",
2254 "Update:", bgp
->rfapi
->stat
.count_updated_response_updates
);
2255 fp(out
, "%-8s %-8u",
2256 "Remove:", bgp
->rfapi
->stat
.count_updated_response_deletes
);
2257 fp(out
, "%-8s %-8u", "Total:",
2258 bgp
->rfapi
->stat
.count_updated_response_updates
2259 + bgp
->rfapi
->stat
.count_updated_response_deletes
);
2262 fp(out
, "%-24s ", " (NVEs)");
2263 for (ALL_LIST_ELEMENTS_RO(&bgp
->rfapi
->descriptors
, node
, rfd
)) {
2265 if (rfd
->rib_prefix_count
)
2266 ++nves_with_nonempty_ribs
;
2268 fp(out
, "%-8s %-8u ", "Active:", nves_with_nonempty_ribs
);
2269 fp(out
, "%-8s %-8u", "Total:", nves
);
2273 void rfapiRibShowResponsesSummaryClear(void)
2275 struct bgp
*bgp
= bgp_get_default();
2277 bgp
->rfapi
->rib_prefix_count_total_max
=
2278 bgp
->rfapi
->rib_prefix_count_total
;
2281 static int print_rib_sl(int (*fp
)(void *, const char *, ...), struct vty
*vty
,
2282 void *out
, struct skiplist
*sl
, int deleted
,
2283 char *str_pfx
, int *printedprefix
)
2285 struct rfapi_info
*ri
;
2288 int routes_displayed
= 0;
2291 for (rc
= skiplist_next(sl
, NULL
, (void **)&ri
, &cursor
); !rc
;
2292 rc
= skiplist_next(sl
, NULL
, (void **)&ri
, &cursor
)) {
2294 char str_vn
[PREFIX_STRLEN
];
2295 char str_un
[PREFIX_STRLEN
];
2296 char str_lifetime
[BUFSIZ
];
2297 char str_age
[BUFSIZ
];
2299 char str_rd
[RD_ADDRSTRLEN
];
2303 prefix2str(&ri
->rk
.vn
, str_vn
, sizeof(str_vn
));
2304 p
= index(str_vn
, '/');
2308 prefix2str(&ri
->un
, str_un
, sizeof(str_un
));
2309 p
= index(str_un
, '/');
2313 rfapiFormatSeconds(ri
->lifetime
, str_lifetime
, BUFSIZ
);
2314 #if RFAPI_REGISTRATIONS_REPORT_AGE
2315 rfapiFormatAge(ri
->last_sent_time
, str_age
, BUFSIZ
);
2318 time_t now
= rfapi_time(NULL
);
2320 ri
->last_sent_time
+ (time_t)ri
->lifetime
;
2321 /* allow for delayed/async removal */
2322 rfapiFormatSeconds((expire
> now
? expire
- now
: 1),
2327 str_rd
[0] = 0; /* start empty */
2329 prefix_rd2str(&ri
->rk
.rd
, str_rd
, sizeof(str_rd
));
2332 fp(out
, " %c %-20s %-15s %-15s %-4u %-8s %-8s %s\n",
2333 deleted
? 'r' : ' ', *printedprefix
? "" : str_pfx
, str_vn
,
2334 str_un
, ri
->cost
, str_lifetime
, str_age
, str_rd
);
2336 if (!*printedprefix
)
2339 return routes_displayed
;
2344 * This one is for debugging (set stream to NULL to send output to log)
2346 static void rfapiRibShowRibSl(void *stream
, struct prefix
*pfx
,
2347 struct skiplist
*sl
)
2349 int (*fp
)(void *, const char *, ...);
2352 const char *vty_newline
;
2354 int nhs_displayed
= 0;
2355 char str_pfx
[PREFIX_STRLEN
];
2356 int printedprefix
= 0;
2358 if (rfapiStream2Vty(stream
, &fp
, &vty
, &out
, &vty_newline
) == 0)
2361 prefix2str(pfx
, str_pfx
, sizeof(str_pfx
));
2364 print_rib_sl(fp
, vty
, out
, sl
, 0, str_pfx
, &printedprefix
);
2368 void rfapiRibShowResponses(void *stream
, struct prefix
*pfx_match
,
2371 int (*fp
)(void *, const char *, ...);
2374 const char *vty_newline
;
2376 struct rfapi_descriptor
*rfd
;
2377 struct listnode
*node
;
2379 struct bgp
*bgp
= bgp_get_default();
2380 int printedheader
= 0;
2381 int routes_total
= 0;
2383 int prefixes_total
= 0;
2384 int prefixes_displayed
= 0;
2386 int nves_with_routes
= 0;
2387 int nves_displayed
= 0;
2388 int routes_displayed
= 0;
2389 int nhs_displayed
= 0;
2391 if (rfapiStream2Vty(stream
, &fp
, &vty
, &out
, &vty_newline
) == 0)
2394 fp(out
, "Unable to find default BGP instance\n");
2401 for (ALL_LIST_ELEMENTS_RO(&bgp
->rfapi
->descriptors
, node
, rfd
)) {
2407 if (rfd
->rib_prefix_count
)
2410 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
) {
2412 struct route_node
*rn
;
2417 for (rn
= route_top(rfd
->rib
[afi
]); rn
;
2418 rn
= route_next(rn
)) {
2420 struct skiplist
*sl
;
2421 char str_pfx
[PREFIX_STRLEN
];
2422 int printedprefix
= 0;
2433 nhs_total
+= skiplist_count(sl
);
2437 && !prefix_match(pfx_match
, &rn
->p
)
2438 && !prefix_match(&rn
->p
, pfx_match
))
2441 ++prefixes_displayed
;
2443 if (!printedheader
) {
2447 show_removed
? "Removed" : "Active");
2448 fp(out
, "%-15s %-15s\n", "Querying VN",
2451 " %-20s %-15s %-15s %4s %-8s %-8s\n",
2452 "Prefix", "Registered VN",
2453 "Registered UN", "Cost", "Lifetime",
2454 #if RFAPI_REGISTRATIONS_REPORT_AGE
2462 char str_vn
[BUFSIZ
];
2463 char str_un
[BUFSIZ
];
2468 fp(out
, "%-15s %-15s\n",
2469 rfapiRfapiIpAddr2Str(&rfd
->vn_addr
,
2471 rfapiRfapiIpAddr2Str(&rfd
->un_addr
,
2475 prefix2str(&rn
->p
, str_pfx
, sizeof(str_pfx
));
2476 // fp(out, " %s\n", buf); /* prefix */
2479 nhs_displayed
+= print_rib_sl(
2480 fp
, vty
, out
, sl
, show_removed
, str_pfx
,
2488 fp(out
, "Displayed %u NVEs, and %u out of %u %s prefixes",
2489 nves_displayed
, routes_displayed
, routes_total
,
2490 show_removed
? "removed" : "active");
2491 if (nhs_displayed
!= routes_displayed
2492 || nhs_total
!= routes_total
)
2493 fp(out
, " with %u out of %u next hops", nhs_displayed
,