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
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.
24 * Purpose: maintain per-nve ribs and generate change lists
29 #include "lib/zebra.h"
30 #include "lib/prefix.h"
31 #include "lib/table.h"
33 #include "lib/memory.h"
35 #include "lib/skiplist.h"
36 #include "lib/workqueue.h"
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"
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"
55 #define DEBUG_PROCESS_PENDING_NODE 0
56 #define DEBUG_PENDING_DELETE_ROUTE 0
58 #define DEBUG_RIB_SL_RD 0
63 rfapiRibShowRibSl (void *stream
, struct prefix
*pfx
, struct skiplist
*sl
);
69 * Model of the set of routes currently in the NVE's RIB.
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
76 * skiplist.cmp = vnc_prefix_cmp
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
84 * This skiplist at "aggregate"
85 * contains the routes recently
91 * Sparse list of prefixes that need to be updated. Each node
92 * will have the complete set of routes for the prefix.
94 * node->info ptr to "struct list" (lib/linklist.h)
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.
102 * .data = ptr to struct rfapi_info
103 * list.cmp = NULL (sorted manually)
104 * list.del = rfapi_info_free
106 * Special case: if node->info is 1, it means
107 * "delete all routes at this prefix".
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
115 * ptlist is rewritten anew each time
116 * rfapiRibUpdatePendingNode() is called
118 * THE ptlist VALUES ARE REFERENCES TO THE
119 * rfapi_info STRUCTS IN THE node->info LIST.
123 * iterate over RIB to count responses, compare with running counters
126 rfapiRibCheckCounts (
127 int checkstats
, /* validate rfd & global counts */
128 unsigned int offset
) /* number of ri's held separately */
130 struct rfapi_descriptor
*rfd
;
131 struct listnode
*node
;
133 struct bgp
*bgp
= bgp_get_default ();
135 uint32_t t_pfx_active
= 0;
136 uint32_t t_pfx_deleted
= 0;
138 uint32_t t_ri_active
= 0;
139 uint32_t t_ri_deleted
= 0;
140 uint32_t t_ri_pend
= 0;
142 unsigned int alloc_count
;
147 for (ALL_LIST_ELEMENTS_RO (&bgp
->rfapi
->descriptors
, node
, rfd
))
151 uint32_t pfx_active
= 0;
152 uint32_t pfx_deleted
= 0;
154 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
)
157 struct route_node
*rn
;
159 for (rn
= route_top (rfd
->rib
[afi
]); rn
; rn
= route_next (rn
))
162 struct skiplist
*sl
= rn
->info
;
163 struct skiplist
*dsl
= rn
->aggregate
;
164 uint32_t ri_active
= 0;
165 uint32_t ri_deleted
= 0;
169 ri_active
= skiplist_count (sl
);
171 t_ri_active
+= ri_active
;
178 ri_deleted
= skiplist_count (dsl
);
179 t_ri_deleted
+= ri_deleted
;
184 for (rn
= route_top (rfd
->rib_pending
[afi
]); rn
;
185 rn
= route_next (rn
))
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;
195 ri_pend_uniq
= skiplist_count (sl
);
198 if (l
&& (l
!= (void *) 1))
200 ri_pend_cost
= l
->count
;
201 t_ri_pend
+= l
->count
;
204 assert (ri_pend_uniq
== ri_pend_cost
);
210 if (pfx_active
!= rfd
->rib_prefix_count
)
212 vnc_zlog_debug_verbose ("%s: rfd %p actual pfx count %u != running %u",
213 __func__
, rfd
, pfx_active
, rfd
->rib_prefix_count
);
219 if (checkstats
&& bgp
&& bgp
->rfapi
)
221 if (t_pfx_active
!= bgp
->rfapi
->rib_prefix_count_total
)
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
);
231 * Check against memory allocation count
233 alloc_count
= mtype_stats_alloc (MTYPE_RFAPI_INFO
);
234 assert (t_ri_active
+ t_ri_deleted
+ t_ri_pend
+ offset
== alloc_count
);
237 static struct rfapi_info
*
240 return XCALLOC (MTYPE_RFAPI_INFO
, sizeof (struct rfapi_info
));
244 rfapiFreeRfapiUnOptionChain (struct rfapi_un_option
*p
)
248 struct rfapi_un_option
*next
;
251 XFREE (MTYPE_RFAPI_UN_OPTION
, p
);
257 rfapiFreeRfapiVnOptionChain (struct rfapi_vn_option
*p
)
261 struct rfapi_vn_option
*next
;
264 XFREE (MTYPE_RFAPI_VN_OPTION
, p
);
271 rfapi_info_free (struct rfapi_info
*goner
)
275 if (goner
->tea_options
)
277 rfapiFreeBgpTeaOptionChain (goner
->tea_options
);
278 goner
->tea_options
= NULL
;
280 if (goner
->un_options
)
282 rfapiFreeRfapiUnOptionChain (goner
->un_options
);
283 goner
->un_options
= NULL
;
285 if (goner
->vn_options
)
287 rfapiFreeRfapiVnOptionChain (goner
->vn_options
);
288 goner
->vn_options
= NULL
;
292 struct rfapi_rib_tcb
*tcb
;
294 tcb
= ((struct thread
*) goner
->timer
)->arg
;
295 thread_cancel ((struct thread
*) goner
->timer
);
296 XFREE (MTYPE_RFAPI_RECENT_DELETE
, tcb
);
299 XFREE (MTYPE_RFAPI_INFO
, goner
);
304 * Timer control block for recently-deleted and expired routes
308 struct rfapi_descriptor
*rfd
;
310 struct rfapi_info
*ri
;
311 struct route_node
*rn
;
313 #define RFAPI_RIB_TCB_FLAG_DELETED 0x00000001
317 * remove route from rib
320 rfapiRibExpireTimer (struct thread
*t
)
322 struct rfapi_rib_tcb
*tcb
= t
->arg
;
324 RFAPI_RIB_CHECK_COUNTS (1, 0);
327 * Forget reference to thread. Otherwise rfapi_info_free() will
328 * attempt to free thread pointer as an option chain
330 tcb
->ri
->timer
= NULL
;
332 /* "deleted" skiplist frees ri, "active" doesn't */
333 assert (!skiplist_delete (tcb
->sl
, &tcb
->ri
->rk
, NULL
));
337 * XXX in this case, skiplist has no delete function: we must
338 * therefore delete rfapi_info explicitly.
340 rfapi_info_free (tcb
->ri
);
343 if (skiplist_empty (tcb
->sl
))
345 if (CHECK_FLAG (tcb
->flags
, RFAPI_RIB_TCB_FLAG_DELETED
))
346 tcb
->rn
->aggregate
= NULL
;
349 struct bgp
*bgp
= bgp_get_default ();
350 tcb
->rn
->info
= NULL
;
351 RFAPI_RIB_PREFIX_COUNT_DECR (tcb
->rfd
, bgp
->rfapi
);
353 skiplist_free (tcb
->sl
);
354 route_unlock_node (tcb
->rn
);
357 XFREE (MTYPE_RFAPI_RECENT_DELETE
, tcb
);
359 RFAPI_RIB_CHECK_COUNTS (1, 0);
366 struct rfapi_descriptor
*rfd
,
367 struct rfapi_info
*ri
,
368 struct route_node
*rn
, /* route node attached to */
371 struct thread
*t
= ri
->timer
;
372 struct rfapi_rib_tcb
*tcb
= NULL
;
373 char buf_prefix
[BUFSIZ
];
384 XCALLOC (MTYPE_RFAPI_RECENT_DELETE
, sizeof (struct rfapi_rib_tcb
));
391 tcb
->sl
= (struct skiplist
*) rn
->aggregate
;
392 SET_FLAG (tcb
->flags
, RFAPI_RIB_TCB_FLAG_DELETED
);
396 tcb
->sl
= (struct skiplist
*) rn
->info
;
397 UNSET_FLAG (tcb
->flags
, RFAPI_RIB_TCB_FLAG_DELETED
);
400 prefix2str (&rn
->p
, buf_prefix
, BUFSIZ
);
401 vnc_zlog_debug_verbose ("%s: rfd %p pfx %s life %u", __func__
, rfd
, buf_prefix
,
403 ri
->timer
= thread_add_timer (bm
->master
, rfapiRibExpireTimer
,
409 * Compares two <struct rfapi_rib_key>s
412 rfapi_rib_key_cmp (void *k1
, void *k2
)
414 struct rfapi_rib_key
*a
= (struct rfapi_rib_key
*) k1
;
415 struct rfapi_rib_key
*b
= (struct rfapi_rib_key
*) k2
;
421 ret
= vnc_prefix_cmp (&a
->vn
, &b
->vn
);
425 ret
= vnc_prefix_cmp(&a
->rd
, &b
->rd
);
429 ret
= vnc_prefix_cmp (&a
->aux_prefix
, &b
->aux_prefix
);
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.
442 * This function could be modified to compare option chains more
443 * thoroughly, but it's not clear that the extra compuation would
447 bgp_tea_options_cmp (struct bgp_tea_options
*a
, struct bgp_tea_options
*b
)
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
)))
462 if (!a
->next
!= !b
->next
)
464 return (a
->next
- b
->next
);
467 return bgp_tea_options_cmp (a
->next
, b
->next
);
473 rfapi_info_cmp (struct rfapi_info
*a
, struct rfapi_info
*b
)
480 if ((rc
= rfapi_rib_key_cmp (&a
->rk
, &b
->rk
)))
483 if ((rc
= vnc_prefix_cmp (&a
->un
, &b
->un
)))
486 if (a
->cost
!= b
->cost
)
487 return (a
->cost
- b
->cost
);
489 if (a
->lifetime
!= b
->lifetime
)
490 return (a
->lifetime
- b
->lifetime
);
492 if ((rc
= bgp_tea_options_cmp (a
->tea_options
, b
->tea_options
)))
499 rfapiRibClear (struct rfapi_descriptor
*rfd
)
501 struct bgp
*bgp
= bgp_get_default ();
505 vnc_zlog_debug_verbose ("%s: rfd=%p", __func__
, rfd
);
508 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
)
510 struct route_node
*pn
;
511 struct route_node
*rn
;
513 if (rfd
->rib_pending
[afi
])
515 for (pn
= route_top (rfd
->rib_pending
[afi
]); pn
;
516 pn
= route_next (pn
))
521 * free references into the rfapi_info structures before
522 * freeing the structures themselves
524 skiplist_free ((struct skiplist
*) (pn
->aggregate
));
525 pn
->aggregate
= NULL
;
526 route_unlock_node (pn
); /* skiplist deleted */
529 * free the rfapi_info structures
533 if (pn
->info
!= (void *) 1)
535 list_delete ((struct list
*) (pn
->info
));
538 route_unlock_node (pn
); /* linklist or 1 deleted */
544 for (rn
= route_top (rfd
->rib
[afi
]); rn
; rn
= route_next (rn
))
549 struct rfapi_info
*ri
;
552 skiplist_first ((struct skiplist
*) rn
->info
, NULL
,
556 rfapi_info_free (ri
);
557 skiplist_delete_first ((struct skiplist
*) rn
->info
);
559 skiplist_free ((struct skiplist
*) rn
->info
);
561 route_unlock_node (rn
);
562 RFAPI_RIB_PREFIX_COUNT_DECR (rfd
, bgp
->rfapi
);
567 struct rfapi_info
*ri_del
;
569 /* delete skiplist & contents */
570 while (!skiplist_first ((struct skiplist
*) (rn
->aggregate
),
571 NULL
, (void **) &ri_del
))
574 /* sl->del takes care of ri_del */
575 skiplist_delete_first (
576 (struct skiplist
*) (rn
->aggregate
));
578 skiplist_free ((struct skiplist
*) (rn
->aggregate
));
580 rn
->aggregate
= NULL
;
581 route_unlock_node (rn
);
586 if (rfd
->updated_responses_queue
)
588 work_queue_free (rfd
->updated_responses_queue
);
589 rfd
->updated_responses_queue
= NULL
;
594 * Release all dynamically-allocated memory that is part of an HD's RIB
597 rfapiRibFree (struct rfapi_descriptor
*rfd
)
603 * NB rfd is typically detached from master list, so is not included
604 * in the count performed by RFAPI_RIB_CHECK_COUNTS
608 * Free routes attached to radix trees
612 /* Now the uncounted rfapi_info's are freed, so the check should succeed */
613 RFAPI_RIB_CHECK_COUNTS (1, 0);
618 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
)
620 route_table_finish (rfd
->rib_pending
[afi
]);
621 rfd
->rib_pending
[afi
] = NULL
;
623 route_table_finish (rfd
->rib
[afi
]);
624 rfd
->rib
[afi
] = NULL
;
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
;
633 * Copies struct bgp_info to struct rfapi_info, except for rk fields and un
638 struct rfapi_info
*ri
,
641 struct bgp_attr_encap_subtlv
*pEncap
;
643 ri
->cost
= rfapiRfpCost (bi
->attr
);
644 ri
->lifetime
= lifetime
;
646 /* This loop based on rfapiRouteInfo2NextHopEntry() */
647 for (pEncap
= bi
->attr
->extra
->vnc_subtlvs
; pEncap
; pEncap
= pEncap
->next
)
649 struct bgp_tea_options
*hop
;
651 switch (pEncap
->type
)
653 case BGP_VNC_SUBTLV_TYPE_LIFETIME
:
654 /* use configured lifetime, not attr lifetime */
657 case BGP_VNC_SUBTLV_TYPE_RFPOPTION
:
658 hop
= XCALLOC (MTYPE_BGP_TEA_OPTIONS
,
659 sizeof (struct bgp_tea_options
));
661 hop
->type
= pEncap
->value
[0];
662 hop
->length
= pEncap
->value
[1];
663 hop
->value
= XCALLOC (MTYPE_BGP_TEA_OPTIONS_VALUE
,
666 memcpy (hop
->value
, pEncap
->value
+ 2, pEncap
->length
- 2);
667 if (hop
->length
> pEncap
->length
- 2)
669 zlog_warn ("%s: VNC subtlv length mismatch: "
670 "RFP option says %d, attr says %d "
672 __func__
, hop
->length
, pEncap
->length
- 2);
673 hop
->length
= pEncap
->length
- 2;
675 hop
->next
= ri
->tea_options
;
676 ri
->tea_options
= hop
;
684 rfapi_un_options_free (ri
->un_options
); /* maybe free old version */
685 ri
->un_options
= rfapi_encap_tlv_to_un_option (bi
->attr
);
691 decode_rd_type(bi
->extra
->vnc
.import
.rd
.val
) == RD_TYPE_VNC_ETH
)
695 struct rfapi_vn_option
*vo
;
697 vo
= XCALLOC (MTYPE_RFAPI_VN_OPTION
, sizeof (struct rfapi_vn_option
));
700 vo
->type
= RFAPI_VN_OPTION_TYPE_L2ADDR
;
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,
706 if (bi
->attr
&& bi
->attr
->extra
)
708 (void) rfapiEcommunityGetLNI (bi
->attr
->extra
->ecommunity
,
709 &vo
->v
.l2addr
.logical_net_id
);
712 /* local_nve_id comes from RD */
713 vo
->v
.l2addr
.local_nve_id
= bi
->extra
->vnc
.import
.rd
.val
[1];
715 /* label comes from MP_REACH_NLRI label */
716 vo
->v
.l2addr
.label
= decode_label (bi
->extra
->tag
);
718 rfapi_vn_options_free (ri
->vn_options
); /* maybe free old version */
723 * If there is an auxiliary IP address (L2 can have it), copy it
725 if (bi
&& bi
->extra
&& bi
->extra
->vnc
.import
.aux_prefix
.family
)
727 ri
->rk
.aux_prefix
= bi
->extra
->vnc
.import
.aux_prefix
;
734 * Install route into NVE RIB model so as to be consistent with
735 * caller's response to rfapi_query().
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:
741 * 1. If there were prior duplicates of this route in this same
742 * query response, don't include the route.
746 * 0 OK to include route in response
747 * !0 do not include route in response
751 struct route_node
*rfd_rib_node
, /* NULL = don't preload or filter */
752 struct prefix
*pfx_vn
,
753 struct prefix
*pfx_un
,
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
;
767 afi
= family2afi(rfd_rib_node
->p
.family
);
769 rfd
= (struct rfapi_descriptor
*)(rfd_rib_node
->table
->info
);
771 memset((void *)&rk
, 0, sizeof(rk
));
773 rk
.rd
= bi
->extra
->vnc
.import
.rd
;
776 * If there is an auxiliary IP address (L2 can have it), copy it
778 if (bi
->extra
->vnc
.import
.aux_prefix
.family
)
780 rk
.aux_prefix
= bi
->extra
->vnc
.import
.aux_prefix
;
784 * is this route already in NVE's RIB?
786 slRibPt
= (struct skiplist
*) rfd_rib_node
->info
;
788 if (slRibPt
&& !skiplist_search (slRibPt
, &rk
, (void **) &ori
))
791 if ((ori
->rsp_counter
== rfd
->rsp_counter
) &&
792 (ori
->last_sent_time
== rfd
->rsp_time
))
794 return -1; /* duplicate in this response */
797 /* found: update contents of existing route in RIB */
799 rfapiRibBi2Ri(bi
, ori
, lifetime
);
803 /* not found: add new route to RIB */
804 ori
= rfapi_info_new ();
807 rfapiRibBi2Ri(bi
, ori
, lifetime
);
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
);
816 skiplist_insert (slRibPt
, &ori
->rk
, ori
);
819 ori
->last_sent_time
= rfapi_time (NULL
);
824 RFAPI_RIB_CHECK_COUNTS (0, 0);
825 rfapiRibStartTimer (rfd
, ori
, rfd_rib_node
, 0);
826 RFAPI_RIB_CHECK_COUNTS (0, 0);
829 * Update last sent time for prefix
831 trn
= route_node_get (rfd
->rsp_times
[afi
], &rfd_rib_node
->p
); /* locks trn */
832 trn
->info
= (void *) (uintptr_t) bgp_clock ();
834 route_unlock_node (trn
);
840 * Frees rfapi_info items at node
842 * Adjust 'rib' and 'rib_pending' as follows:
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
849 * For each item at rib node:
850 * if not present in pending node, move RIB item to "delete list"
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
856 * For each remaining item at pending rib node, add or replace item
859 * Construct NHL as concatenation of pending list + delete list
864 process_pending_node (
866 struct rfapi_descriptor
*rfd
,
868 struct route_node
*pn
, /* pending node */
869 struct rfapi_next_hop_entry
**head
,
870 struct rfapi_next_hop_entry
**tail
)
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;
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;
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
);
897 if (AFI_ETHER
!= afi
)
899 rfapiQprefix2Rprefix (&pn
->p
, &hp
);
902 RFAPI_RIB_CHECK_COUNTS (1, 0);
905 * Find corresponding RIB node
907 rn
= route_node_get (rfd
->rib
[afi
], &pn
->p
); /* locks rn */
910 * RIB skiplist has key=rfapi_addr={vn,un}, val = rfapi_info,
911 * skiplist.del = NULL
913 slRibPt
= (struct skiplist
*) rn
->info
;
915 rib_node_started_nonempty
= 1;
917 slPendPt
= (struct skiplist
*) (pn
->aggregate
);
918 lPendCost
= (struct list
*) (pn
->info
);
920 #if DEBUG_PROCESS_PENDING_NODE
923 count_rib_initial
= skiplist_count (slRibPt
);
926 count_pend_vn_initial
= skiplist_count (slPendPt
);
928 if (lPendCost
&& lPendCost
!= (struct list
*) 1)
929 count_pend_cost_initial
= lPendCost
->count
;
934 * Handle special case: delete all routes at prefix
936 if (lPendCost
== (struct list
*) 1)
938 vnc_zlog_debug_verbose ("%s: lPendCost=1 => delete all", __func__
);
939 if (slRibPt
&& !skiplist_empty (slRibPt
))
941 delete_list
= list_new ();
942 while (0 == skiplist_first (slRibPt
, NULL
, (void **) &ri
))
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
;
956 struct rfapi_rib_tcb
*tcb
;
958 tcb
= ((struct thread
*) ri
->timer
)->arg
;
959 thread_cancel (ri
->timer
);
960 XFREE (MTYPE_RFAPI_RECENT_DELETE
, tcb
);
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
,
971 skiplist_delete_first (slRibPt
);
974 assert (skiplist_empty (slRibPt
));
976 skiplist_free (slRibPt
);
977 rn
->info
= slRibPt
= NULL
;
978 route_unlock_node (rn
);
980 lPendCost
= pn
->info
= NULL
;
981 route_unlock_node (pn
);
987 skiplist_free (slRibPt
);
989 route_unlock_node (rn
);
994 { /* TBD I think we can toss this block */
995 skiplist_free (slPendPt
);
996 pn
->aggregate
= NULL
;
997 route_unlock_node (pn
);
1001 route_unlock_node (pn
);
1003 route_unlock_node (rn
); /* route_node_get() */
1005 if (rib_node_started_nonempty
)
1007 RFAPI_RIB_PREFIX_COUNT_DECR (rfd
, bgp
->rfapi
);
1010 RFAPI_RIB_CHECK_COUNTS (1, 0);
1015 vnc_zlog_debug_verbose ("%s: lPendCost->count=%d, slRibPt->count=%d",
1017 (lPendCost
? (int) lPendCost
->count
: -1),
1018 (slRibPt
? (int) slRibPt
->count
: -1));
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
1028 void *cursor
= NULL
;
1029 struct rfapi_info
*ori
;
1032 * Iterate over RIB List
1035 while (!skiplist_next (slRibPt
, NULL
, (void **) &ori
, &cursor
))
1038 if (skiplist_search (slPendPt
, &ori
->rk
, (void **) &ri
))
1041 * Not in Pending list, so it should be deleted
1044 delete_list
= list_new ();
1045 listnode_add (delete_list
, ori
);
1046 rfapiFreeBgpTeaOptionChain (ori
->tea_options
);
1047 ori
->tea_options
= NULL
;
1050 struct rfapi_rib_tcb
*tcb
;
1052 tcb
= ((struct thread
*) ori
->timer
)->arg
;
1053 thread_cancel (ori
->timer
);
1054 XFREE (MTYPE_RFAPI_RECENT_DELETE
, tcb
);
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",
1069 * Found in pending list. If same lifetime, cost, options,
1070 * then remove from pending list because the route
1073 if (!rfapi_info_cmp (ori
, ri
))
1075 skiplist_delete (slPendPt
, &ri
->rk
, NULL
);
1079 /* linear walk: might need optimization */
1080 listnode_delete (lPendCost
, ri
); /* XXX doesn't free data! bug? */
1081 rfapi_info_free (ri
); /* grr... */
1084 #if DEBUG_PROCESS_PENDING_NODE
1085 vnc_zlog_debug_verbose ("%s: slRibPt ri %p matched in pending list, %s",
1087 (same
? "same info" : "different info"));
1092 * Go back and delete items from RIB
1096 for (ALL_LIST_ELEMENTS_RO (delete_list
, node
, ri
))
1098 vnc_zlog_debug_verbose ("%s: deleting ri %p from slRibPt", __func__
, ri
);
1099 assert (!skiplist_delete (slRibPt
, &ri
->rk
, NULL
));
1101 if (skiplist_empty (slRibPt
))
1103 skiplist_free (slRibPt
);
1104 slRibPt
= rn
->info
= NULL
;
1105 route_unlock_node (rn
);
1110 RFAPI_RIB_CHECK_COUNTS (0, (delete_list
? delete_list
->count
: 0));
1113 * Iterate over routes at Pending Node
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
1120 for (ALL_LIST_ELEMENTS_RO (lPendCost
, node
, ri
))
1123 struct rfapi_info
*ori
;
1125 if (slRibPt
&& !skiplist_search (slRibPt
, &ri
->rk
, (void **) &ori
))
1128 /* found: update contents of existing route in RIB */
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
);
1136 rfapiFreeRfapiVnOptionChain (ori
->vn_options
);
1137 ori
->vn_options
= rfapiVnOptionsDup (ri
->vn_options
);
1139 rfapiFreeRfapiUnOptionChain (ori
->un_options
);
1140 ori
->un_options
= rfapiUnOptionsDup (ri
->un_options
);
1142 vnc_zlog_debug_verbose
1143 ("%s: matched lPendCost item %p in slRibPt, rewrote",
1150 char buf_rd
[BUFSIZ
];
1152 /* not found: add new route to RIB */
1153 ori
= rfapi_info_new ();
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
);
1165 slRibPt
= skiplist_new (0, rfapi_rib_key_cmp
, NULL
);
1167 route_lock_node (rn
);
1169 skiplist_insert (slRibPt
, &ori
->rk
, ori
);
1172 prefix_rd2str(&ori
->rk
.rd
, buf_rd
, sizeof(buf_rd
));
1177 vnc_zlog_debug_verbose ("%s: nomatch lPendCost item %p in slRibPt, added (rd=%s)",
1178 __func__
, ri
, buf_rd
);
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));
1193 * Construct NHL as concatenation of pending list + delete list
1197 RFAPI_RIB_CHECK_COUNTS (0, (delete_list
? delete_list
->count
: 0));
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
);
1209 for (ALL_LIST_ELEMENTS (lPendCost
, node
, nnode
, ri
))
1212 struct rfapi_next_hop_entry
*new;
1213 struct route_node
*trn
;
1216 XCALLOC (MTYPE_RFAPI_NEXTHOP
,
1217 sizeof (struct rfapi_next_hop_entry
));
1220 if (ri
->rk
.aux_prefix
.family
)
1222 rfapiQprefix2Rprefix (&ri
->rk
.aux_prefix
, &new->prefix
);
1227 if (AFI_ETHER
== afi
)
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;
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
);
1241 ri
->tea_options
= NULL
; /* option chain was transferred to NHL */
1243 new->vn_options
= ri
->vn_options
;
1244 ri
->vn_options
= NULL
; /* option chain was transferred to NHL */
1246 new->un_options
= ri
->un_options
;
1247 ri
->un_options
= NULL
; /* option chain was transferred to NHL */
1250 (*tail
)->next
= new;
1256 sendingsomeroutes
= 1;
1258 ++rfd
->stat_count_nh_reachable
;
1259 ++bgp
->rfapi
->stat
.count_updated_response_updates
;
1262 * update this NVE's timestamp for this prefix
1264 trn
= route_node_get (rfd
->rsp_times
[afi
], &pn
->p
); /* locks trn */
1265 trn
->info
= (void *) (uintptr_t) bgp_clock ();
1267 route_unlock_node (trn
);
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
);
1276 RFAPI_RIB_CHECK_COUNTS (0, (delete_list
? delete_list
->count
: 0));
1286 vnc_zlog_debug_verbose ("%s: For prefix %s (d)", __func__
, buf_prefix
);
1289 vnc_zlog_debug_verbose ("%s: delete_list has %d elements",
1290 __func__
, delete_list
->count
);
1292 RFAPI_RIB_CHECK_COUNTS (0, delete_list
->count
);
1293 if (!CHECK_FLAG (bgp
->rfapi_cfg
->flags
,
1294 BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE
))
1297 for (ALL_LIST_ELEMENTS (delete_list
, node
, nnode
, ri
))
1300 struct rfapi_next_hop_entry
*new;
1301 struct rfapi_info
*ri_del
;
1303 RFAPI_RIB_CHECK_COUNTS (0, delete_list
->count
);
1304 new = XCALLOC (MTYPE_RFAPI_NEXTHOP
,
1305 sizeof (struct rfapi_next_hop_entry
));
1308 if (ri
->rk
.aux_prefix
.family
)
1310 rfapiQprefix2Rprefix (&ri
->rk
.aux_prefix
, &new->prefix
);
1315 if (AFI_ETHER
== afi
)
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;
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
);
1328 new->vn_options
= ri
->vn_options
;
1329 ri
->vn_options
= NULL
; /* option chain was transferred to NHL */
1331 new->un_options
= ri
->un_options
;
1332 ri
->un_options
= NULL
; /* option chain was transferred to NHL */
1335 (*tail
)->next
= new;
1341 ++rfd
->stat_count_nh_removal
;
1342 ++bgp
->rfapi
->stat
.count_updated_response_deletes
;
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
);
1349 RFAPI_RIB_CHECK_COUNTS (0, delete_list
->count
);
1351 * Update/add to list of recent deletions at this prefix
1355 rn
->aggregate
= skiplist_new (0, rfapi_rib_key_cmp
,
1358 route_lock_node (rn
);
1360 RFAPI_RIB_CHECK_COUNTS (0, delete_list
->count
);
1362 /* sanity check lifetime */
1363 if (ri
->lifetime
> RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY
)
1364 ri
->lifetime
= RFAPI_LIFETIME_INFINITE_WITHDRAW_DELAY
;
1366 RFAPI_RIB_CHECK_COUNTS (0, delete_list
->count
);
1367 /* cancel normal expire timer */
1370 struct rfapi_rib_tcb
*tcb
;
1372 tcb
= ((struct thread
*) ri
->timer
)->arg
;
1373 thread_cancel ((struct thread
*) ri
->timer
);
1374 XFREE (MTYPE_RFAPI_RECENT_DELETE
, tcb
);
1377 RFAPI_RIB_CHECK_COUNTS (0, delete_list
->count
);
1380 * Look in "recently-deleted" list
1382 if (skiplist_search ((struct skiplist
*) (rn
->aggregate
),
1383 &ri
->rk
, (void **) &ri_del
))
1388 RFAPI_RIB_CHECK_COUNTS (0, delete_list
->count
);
1390 * NOT in "recently-deleted" list
1392 list_delete_node (delete_list
, node
); /* does not free ri */
1393 rc
= skiplist_insert ((struct skiplist
*) (rn
->aggregate
),
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
);
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",
1414 * IN "recently-deleted" list
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
);
1426 vnc_zlog_debug_verbose ("%s: response removal disabled, omitting removals",
1430 delete_list
->del
= (void (*)(void *)) rfapi_info_free
;
1431 list_delete (delete_list
);
1434 RFAPI_RIB_CHECK_COUNTS (0, 0);
1437 * Reset pending lists. The final route_unlock_node() will probably
1438 * cause the pending node to be released.
1442 skiplist_free (slPendPt
);
1443 pn
->aggregate
= NULL
;
1444 route_unlock_node (pn
);
1448 list_delete (lPendCost
);
1450 route_unlock_node (pn
);
1452 RFAPI_RIB_CHECK_COUNTS (0, 0);
1454 if (rib_node_started_nonempty
)
1458 RFAPI_RIB_PREFIX_COUNT_DECR (rfd
, bgp
->rfapi
);
1465 RFAPI_RIB_PREFIX_COUNT_INCR (rfd
, bgp
->rfapi
);
1469 if (sendingsomeroutes
)
1470 rfapiMonitorTimersRestart (rfd
, &pn
->p
);
1472 route_unlock_node (rn
); /* route_node_get() */
1474 RFAPI_RIB_CHECK_COUNTS (1, 0);
1478 * regardless of targets, construct a single callback by doing
1479 * only one traversal of the pending RIB
1486 rib_do_callback_onepass (struct rfapi_descriptor
*rfd
, afi_t afi
)
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
;
1494 vnc_zlog_debug_verbose ("%s: rfd=%p, afi=%d", __func__
, rfd
, afi
);
1497 if (!rfd
->rib_pending
[afi
])
1500 assert (bgp
->rfapi
);
1502 for (rn
= route_top (rfd
->rib_pending
[afi
]); rn
; rn
= route_next (rn
))
1504 process_pending_node (bgp
, rfd
, afi
, rn
, &head
, &tail
);
1509 rfapi_response_cb_t
*f
;
1512 vnc_zlog_debug_verbose ("%s: response callback NHL follows:", __func__
);
1513 rfapiPrintNhl (NULL
, head
);
1516 if (rfd
->response_cb
)
1517 f
= rfd
->response_cb
;
1519 f
= bgp
->rfapi
->rfp_methods
.response_cb
;
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
;
1529 static wq_item_status
1530 rfapiRibDoQueuedCallback (struct work_queue
*wq
, void *data
)
1532 struct rfapi_descriptor
*rfd
;
1534 uint32_t queued_flag
;
1536 RFAPI_RIB_CHECK_COUNTS (1, 0);
1538 rfd
= ((struct rfapi_updated_responses_queue
*) data
)->rfd
;
1539 afi
= ((struct rfapi_updated_responses_queue
*) data
)->afi
;
1541 /* Make sure the HD wasn't closed after the work item was scheduled */
1542 if (rfapi_check (rfd
))
1545 rib_do_callback_onepass (rfd
, afi
);
1547 queued_flag
= RFAPI_QUEUED_FLAG (afi
);
1549 UNSET_FLAG (rfd
->flags
, queued_flag
);
1551 RFAPI_RIB_CHECK_COUNTS (1, 0);
1557 rfapiRibQueueItemDelete (struct work_queue
*wq
, void *data
)
1559 XFREE (MTYPE_RFAPI_UPDATED_RESPONSE_QUEUE
, data
);
1563 updated_responses_queue_init (struct rfapi_descriptor
*rfd
)
1565 if (rfd
->updated_responses_queue
)
1568 rfd
->updated_responses_queue
= work_queue_new (bm
->master
,
1569 "rfapi updated responses");
1570 assert (rfd
->updated_responses_queue
);
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;
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.
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
1588 * Based on rfapiNhlAddNodeRoutes()
1591 rfapiRibUpdatePendingNode (
1593 struct rfapi_descriptor
*rfd
,
1594 struct rfapi_import_table
*it
, /* needed for L2 */
1595 struct route_node
*it_node
,
1598 struct prefix
*prefix
;
1599 struct bgp_info
*bi
;
1600 struct route_node
*pn
;
1602 uint32_t queued_flag
;
1606 vnc_zlog_debug_verbose ("%s: entry", __func__
);
1608 if (CHECK_FLAG (bgp
->rfapi_cfg
->flags
, BGP_VNC_CONFIG_CALLBACK_DISABLE
))
1611 vnc_zlog_debug_verbose ("%s: callbacks are not disabled", __func__
);
1613 RFAPI_RIB_CHECK_COUNTS (1, 0);
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
);
1620 pn
= route_node_get (rfd
->rib_pending
[afi
], prefix
);
1623 vnc_zlog_debug_verbose ("%s: pn->info=%p, pn->aggregate=%p", __func__
, pn
->info
,
1629 * free references into the rfapi_info structures before
1630 * freeing the structures themselves
1632 skiplist_free ((struct skiplist
*) (pn
->aggregate
));
1633 pn
->aggregate
= NULL
;
1634 route_unlock_node (pn
); /* skiplist deleted */
1639 * free the rfapi_info structures
1643 if (pn
->info
!= (void *) 1)
1645 list_delete ((struct list
*) (pn
->info
));
1648 route_unlock_node (pn
); /* linklist or 1 deleted */
1652 * The BIs in the import table are already sorted by cost
1654 for (bi
= it_node
->info
; bi
; bi
= bi
->next
)
1657 struct rfapi_info
*ri
;
1658 struct prefix pfx_nh
;
1662 /* shouldn't happen */
1663 /* TBD increment error stats counter */
1668 /* shouldn't happen */
1669 /* TBD increment error stats counter */
1673 rfapiNexthop2Prefix (bi
->attr
, &pfx_nh
);
1676 * Omit route if nexthop is self
1679 (bgp
->rfapi_cfg
->flags
, BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP
))
1682 struct prefix pfx_vn
;
1684 rfapiRaddr2Qprefix (&rfd
->vn_addr
, &pfx_vn
);
1685 if (prefix_same (&pfx_vn
, &pfx_nh
))
1689 ri
= rfapi_info_new ();
1691 ri
->rk
.rd
= bi
->extra
->vnc
.import
.rd
;
1693 * If there is an auxiliary IP address (L2 can have it), copy it
1695 if (bi
->extra
->vnc
.import
.aux_prefix
.family
)
1697 ri
->rk
.aux_prefix
= bi
->extra
->vnc
.import
.aux_prefix
;
1700 if (rfapiGetUnAddrOfVpnBi (bi
, &ri
->un
))
1702 rfapi_info_free (ri
);
1708 pn
->aggregate
= skiplist_new (0, rfapi_rib_key_cmp
, NULL
);
1709 route_lock_node (pn
);
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.
1719 if (skiplist_insert ((struct skiplist
*) pn
->aggregate
, &ri
->rk
, ri
))
1725 rfapi_info_free (ri
);
1729 rfapiRibBi2Ri(bi
, ri
, lifetime
);
1733 pn
->info
= list_new ();
1734 ((struct list
*)(pn
->info
))->del
= (void (*)(void *))rfapi_info_free
;
1735 route_lock_node (pn
);
1738 listnode_add ((struct list
*) (pn
->info
), ri
);
1743 count
= ((struct list
*) (pn
->info
))->count
;
1749 assert (!pn
->aggregate
);
1750 pn
->info
= (void *) 1; /* magic value means this node has no routes */
1751 route_lock_node (pn
);
1754 route_unlock_node (pn
); /* route_node_get */
1756 queued_flag
= RFAPI_QUEUED_FLAG (afi
);
1758 if (!CHECK_FLAG (rfd
->flags
, queued_flag
))
1761 struct rfapi_updated_responses_queue
*urq
;
1763 urq
= XCALLOC (MTYPE_RFAPI_UPDATED_RESPONSE_QUEUE
,
1764 sizeof (struct rfapi_updated_responses_queue
));
1766 if (!rfd
->updated_responses_queue
)
1767 updated_responses_queue_init (rfd
);
1769 SET_FLAG (rfd
->flags
, queued_flag
);
1772 work_queue_add (rfd
->updated_responses_queue
, urq
);
1774 RFAPI_RIB_CHECK_COUNTS (1, 0);
1778 rfapiRibUpdatePendingNodeSubtree (
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 */
1786 if (it_node
->l_left
&& (it_node
->l_left
!= omit_subtree
))
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
);
1794 if (it_node
->l_right
&& (it_node
->l_right
!= omit_subtree
))
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
);
1806 * 0 allow prefix to be included in response
1807 * !0 don't allow prefix to be included in response
1810 rfapiRibFTDFilterRecentPrefix(
1811 struct rfapi_descriptor
*rfd
,
1812 struct route_node
*it_rn
, /* import table node */
1813 struct prefix
*pfx_target_original
) /* query target */
1815 struct bgp
*bgp
= rfd
->bgp
;
1816 afi_t afi
= family2afi(it_rn
->p
.family
);
1818 struct route_node
*trn
;
1821 * Not in FTD mode, so allow prefix
1823 if (bgp
->rfapi_cfg
->rfp_cfg
.download_type
!= RFAPI_RFP_DOWNLOAD_FULL
)
1828 * This matches behavior of now-obsolete rfapiRibFTDFilterRecent(),
1829 * but we need to decide if that is correct.
1831 if (it_rn
->p
.family
== AF_ETHERNET
)
1834 #if DEBUG_FTD_FILTER_RECENT
1836 char buf_pfx
[BUFSIZ
];
1838 prefix2str(&it_rn
->p
, buf_pfx
, BUFSIZ
);
1839 vnc_zlog_debug_verbose("%s: prefix %s", __func__
, buf_pfx
);
1844 * prefix covers target address, so allow prefix
1846 if (prefix_match (&it_rn
->p
, pfx_target_original
))
1848 #if DEBUG_FTD_FILTER_RECENT
1849 vnc_zlog_debug_verbose("%s: prefix covers target, allowed", __func__
);
1855 * check this NVE's timestamp for this prefix
1857 trn
= route_node_get (rfd
->rsp_times
[afi
], &it_rn
->p
); /* locks trn */
1858 prefix_time
= (time_t) trn
->info
;
1860 route_unlock_node (trn
);
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
);
1868 * haven't sent this prefix, which doesn't cover target address,
1869 * to NVE since ftd_advertisement_interval, so OK to send now.
1871 if (prefix_time
<= rfd
->ftd_last_allowed_time
)
1878 * Call when rfapi returns from rfapi_query() so the RIB reflects
1879 * the routes sent to the NVE before the first updated response
1881 * Also: remove duplicates from response. Caller should use returned
1882 * value of nexthop chain.
1884 struct rfapi_next_hop_entry
*
1887 struct rfapi_descriptor
*rfd
,
1888 struct rfapi_next_hop_entry
*response
,
1889 int use_eth_resolution
)
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
;
1897 vnc_zlog_debug_verbose ("%s: loading response=%p, use_eth_resolution=%d",
1898 __func__
, response
, use_eth_resolution
);
1900 new_last_sent_time
= rfapi_time (NULL
);
1902 for (nhp
= response
; nhp
; nhp
= nhp_next
)
1906 struct rfapi_rib_key rk
;
1908 struct rfapi_info
*ri
;
1910 struct route_node
*rn
;
1911 int rib_node_started_nonempty
= 0;
1912 struct route_node
*trn
;
1915 /* save in case we delete nhp */
1916 nhp_next
= nhp
->next
;
1918 if (nhp
->lifetime
== RFAPI_REMOVE_RESPONSE_LIFETIME
)
1921 * weird, shouldn't happen
1923 vnc_zlog_debug_verbose
1924 ("%s: got nhp->lifetime == RFAPI_REMOVE_RESPONSE_LIFETIME",
1930 if (use_eth_resolution
)
1932 /* get the prefix of the ethernet address in the L2 option */
1933 struct rfapi_l2address_option
*pL2o
;
1934 struct rfapi_vn_option
*vo
;
1937 * Look for VN option of type RFAPI_VN_OPTION_TYPE_L2ADDR
1939 for (pL2o
= NULL
, vo
= nhp
->vn_options
; vo
; vo
= vo
->next
)
1941 if (RFAPI_VN_OPTION_TYPE_L2ADDR
== vo
->type
)
1943 pL2o
= &vo
->v
.l2addr
;
1951 * not supposed to happen
1953 vnc_zlog_debug_verbose ("%s: missing L2 info", __func__
);
1958 rfapiL2o2Qprefix (pL2o
, &pfx
);
1962 rfapiRprefix2Qprefix (&nhp
->prefix
, &pfx
);
1963 afi
= family2afi (pfx
.family
);
1967 * TBD for ethernet, rib must know the right way to distinguish
1970 * Current approach: prefix is key to radix tree; then
1971 * each prefix has a set of routes with unique VN addrs
1975 * Look up prefix in RIB
1977 rn
= route_node_get (rfd
->rib
[afi
], &pfx
); /* locks rn */
1981 rib_node_started_nonempty
= 1;
1985 rn
->info
= skiplist_new (0, rfapi_rib_key_cmp
, NULL
);
1986 route_lock_node (rn
);
1990 * Look up route at prefix
1993 memset ((void *) &rk
, 0, sizeof (rk
));
1994 assert (!rfapiRaddr2Qprefix (&nhp
->vn_address
, &rk
.vn
));
1996 if (use_eth_resolution
)
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
))
2003 /* mark as "none" if nhp->prefix is 0/32 or 0/128 */
2004 rk
.aux_prefix
.family
= 0;
2010 char str_vn
[BUFSIZ
];
2011 char str_aux_prefix
[BUFSIZ
];
2014 str_aux_prefix
[0] = 0;
2016 prefix2str (&rk
.vn
, str_vn
, BUFSIZ
);
2017 prefix2str (&rk
.aux_prefix
, str_aux_prefix
, BUFSIZ
);
2019 if (!rk
.aux_prefix
.family
)
2023 vnc_zlog_debug_verbose ("%s: rk.vn=%s rk.aux_prefix=%s",
2025 (rk
.aux_prefix
.family
? str_aux_prefix
: "-"));
2027 vnc_zlog_debug_verbose ("%s: RIB skiplist for this prefix follows", __func__
);
2028 rfapiRibShowRibSl (NULL
, &rn
->p
, (struct skiplist
*) rn
->info
);
2032 if (!skiplist_search ((struct skiplist
*) rn
->info
, &rk
, (void **) &ri
))
2035 * Already have this route; make values match
2037 rfapiFreeRfapiUnOptionChain (ri
->un_options
);
2038 ri
->un_options
= NULL
;
2039 rfapiFreeRfapiVnOptionChain (ri
->vn_options
);
2040 ri
->vn_options
= NULL
;
2043 vnc_zlog_debug_verbose ("%s: found in RIB", __func__
);
2047 * Filter duplicate routes from initial response.
2048 * Check timestamps to avoid wraparound problems
2050 if ((ri
->rsp_counter
!= rfd
->rsp_counter
) ||
2051 (ri
->last_sent_time
!= new_last_sent_time
))
2055 vnc_zlog_debug_verbose ("%s: allowed due to counter/timestamp diff",
2066 vnc_zlog_debug_verbose ("%s: allowed due to not yet in RIB", __func__
);
2068 /* not found: add new route to RIB */
2069 ri
= rfapi_info_new ();
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
);
2085 rc
= skiplist_insert ((struct skiplist
*) rn
->info
, &ri
->rk
, ri
);
2089 if (!rib_node_started_nonempty
)
2091 RFAPI_RIB_PREFIX_COUNT_INCR (rfd
, bgp
->rfapi
);
2094 RFAPI_RIB_CHECK_COUNTS (0, 0);
2095 rfapiRibStartTimer (rfd
, ri
, rn
, 0);
2096 RFAPI_RIB_CHECK_COUNTS (0, 0);
2098 route_unlock_node (rn
);
2101 * update this NVE's timestamp for this prefix
2103 trn
= route_node_get (rfd
->rsp_times
[afi
], &pfx
); /* locks trn */
2104 trn
->info
= (void *) (uintptr_t) bgp_clock ();
2106 route_unlock_node (trn
);
2109 char str_pfx
[BUFSIZ
];
2110 char str_pfx_vn
[BUFSIZ
];
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
,
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
;
2137 XFREE (MTYPE_RFAPI_NEXTHOP
, nhp
);
2148 rfapiRibPendingDeleteRoute (
2150 struct rfapi_import_table
*it
,
2152 struct route_node
*it_node
)
2154 struct rfapi_descriptor
*rfd
;
2155 struct listnode
*node
;
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
);
2162 if (AFI_ETHER
== afi
)
2165 * ethernet import tables are per-LNI and each ethernet monitor
2166 * identifies the rfd that owns it.
2168 struct rfapi_monitor_eth
*m
;
2169 struct route_node
*rn
;
2170 struct skiplist
*sl
;
2175 * route-specific monitors
2177 if ((sl
= RFAPI_MONITOR_ETH (it_node
)))
2180 vnc_zlog_debug_verbose ("%s: route-specific skiplist: %p", __func__
, sl
);
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
))
2187 #if DEBUG_PENDING_DELETE_ROUTE
2188 vnc_zlog_debug_verbose ("%s: eth monitor rfd=%p", __func__
, m
->rfd
);
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
2194 if ((rn
= route_node_lookup (m
->rfd
->rib
[afi
], &it_node
->p
)))
2196 rfapiRibUpdatePendingNode (bgp
, m
->rfd
, it
, it_node
,
2197 m
->rfd
->response_lifetime
);
2198 route_unlock_node (rn
);
2204 * all-routes/FTD monitors
2206 for (m
= it
->eth0_queries
; m
; m
= m
->next
)
2208 #if DEBUG_PENDING_DELETE_ROUTE
2209 vnc_zlog_debug_verbose ("%s: eth0 monitor rfd=%p", __func__
, m
->rfd
);
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
2215 if ((rn
= route_node_lookup (m
->rfd
->rib
[afi
], &it_node
->p
)))
2217 rfapiRibUpdatePendingNode (bgp
, m
->rfd
, it
, it_node
,
2218 m
->rfd
->response_lifetime
);
2226 * Find RFDs that reference this import table
2228 for (ALL_LIST_ELEMENTS_RO (&bgp
->rfapi
->descriptors
, node
, rfd
))
2231 struct route_node
*rn
;
2233 vnc_zlog_debug_verbose ("%s: comparing rfd(%p)->import_table=%p to it=%p",
2234 __func__
, rfd
, rfd
->import_table
, it
);
2236 if (rfd
->import_table
!= it
)
2239 vnc_zlog_debug_verbose ("%s: matched rfd %p", __func__
, rfd
);
2242 * If we have sent a response to this NVE with this prefix
2243 * previously, we should send an updated response.
2245 if ((rn
= route_node_lookup (rfd
->rib
[afi
], &it_node
->p
)))
2247 rfapiRibUpdatePendingNode (bgp
, rfd
, it
, it_node
,
2248 rfd
->response_lifetime
);
2249 route_unlock_node (rn
);
2256 rfapiRibShowResponsesSummary (void *stream
)
2258 int (*fp
) (void *, const char *, ...);
2261 const char *vty_newline
;
2262 struct bgp
*bgp
= bgp_get_default ();
2265 int nves_with_nonempty_ribs
= 0;
2266 struct rfapi_descriptor
*rfd
;
2267 struct listnode
*node
;
2270 if (rfapiStream2Vty (stream
, &fp
, &vty
, &out
, &vty_newline
) == 0)
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
);
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
);
2288 fp (out
, "%-24s ", " (NVEs)");
2289 for (ALL_LIST_ELEMENTS_RO (&bgp
->rfapi
->descriptors
, node
, rfd
))
2292 if (rfd
->rib_prefix_count
)
2293 ++nves_with_nonempty_ribs
;
2295 fp (out
, "%-8s %-8u ", "Active:", nves_with_nonempty_ribs
);
2296 fp (out
, "%-8s %-8u", "Total:", nves
);
2297 fp (out
, "%s", VTY_NEWLINE
);
2302 rfapiRibShowResponsesSummaryClear (void)
2304 struct bgp
*bgp
= bgp_get_default ();
2306 bgp
->rfapi
->rib_prefix_count_total_max
= bgp
->rfapi
->rib_prefix_count_total
;
2311 int (*fp
) (void *, const char *, ...),
2314 struct skiplist
*sl
,
2319 struct rfapi_info
*ri
;
2322 int routes_displayed
= 0;
2325 for (rc
= skiplist_next (sl
, NULL
, (void **) &ri
, &cursor
);
2326 !rc
; rc
= skiplist_next (sl
, NULL
, (void **) &ri
, &cursor
))
2329 char str_vn
[BUFSIZ
];
2330 char str_un
[BUFSIZ
];
2331 char str_lifetime
[BUFSIZ
];
2332 char str_age
[BUFSIZ
];
2334 char str_rd
[BUFSIZ
];
2338 prefix2str (&ri
->rk
.vn
, str_vn
, BUFSIZ
);
2339 p
= index (str_vn
, '/');
2343 prefix2str (&ri
->un
, str_un
, BUFSIZ
);
2344 p
= index (str_un
, '/');
2348 rfapiFormatSeconds (ri
->lifetime
, str_lifetime
, BUFSIZ
);
2349 #if RFAPI_REGISTRATIONS_REPORT_AGE
2350 rfapiFormatAge (ri
->last_sent_time
, str_age
, BUFSIZ
);
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),
2361 str_rd
[0] = 0; /* start empty */
2364 prefix_rd2str(&ri
->rk
.rd
, str_rd
+1, BUFSIZ
-1);
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
);
2372 if (!*printedprefix
)
2375 return routes_displayed
;
2380 * This one is for debugging (set stream to NULL to send output to log)
2383 rfapiRibShowRibSl (void *stream
, struct prefix
*pfx
, struct skiplist
*sl
)
2385 int (*fp
) (void *, const char *, ...);
2388 const char *vty_newline
;
2390 int nhs_displayed
= 0;
2391 char str_pfx
[BUFSIZ
];
2392 int printedprefix
= 0;
2394 if (rfapiStream2Vty (stream
, &fp
, &vty
, &out
, &vty_newline
) == 0)
2397 prefix2str (pfx
, str_pfx
, BUFSIZ
);
2399 nhs_displayed
+= print_rib_sl (fp
, vty
, out
, sl
,
2400 0, str_pfx
, &printedprefix
);
2405 rfapiRibShowResponses (
2407 struct prefix
*pfx_match
,
2410 int (*fp
) (void *, const char *, ...);
2413 const char *vty_newline
;
2415 struct rfapi_descriptor
*rfd
;
2416 struct listnode
*node
;
2418 struct bgp
*bgp
= bgp_get_default ();
2419 int printedheader
= 0;
2420 int routes_total
= 0;
2422 int prefixes_total
= 0;
2423 int prefixes_displayed
= 0;
2425 int nves_with_routes
= 0;
2426 int nves_displayed
= 0;
2427 int routes_displayed
= 0;
2428 int nhs_displayed
= 0;
2430 if (rfapiStream2Vty (stream
, &fp
, &vty
, &out
, &vty_newline
) == 0)
2435 for (ALL_LIST_ELEMENTS_RO (&bgp
->rfapi
->descriptors
, node
, rfd
))
2442 if (rfd
->rib_prefix_count
)
2445 for (afi
= AFI_IP
; afi
< AFI_MAX
; ++afi
)
2448 struct route_node
*rn
;
2453 for (rn
= route_top (rfd
->rib
[afi
]); rn
; rn
= route_next (rn
))
2456 struct skiplist
*sl
;
2457 char str_pfx
[BUFSIZ
];
2458 int printedprefix
= 0;
2469 nhs_total
+= skiplist_count (sl
);
2472 if (pfx_match
&& !prefix_match (pfx_match
, &rn
->p
) &&
2473 !prefix_match (&rn
->p
, pfx_match
))
2476 ++prefixes_displayed
;
2482 fp (out
, "%s[%s]%s",
2484 show_removed
? "Removed" : "Active", VTY_NEWLINE
);
2485 fp (out
, "%-15s %-15s%s", "Querying VN", "Querying UN",
2487 fp (out
, " %-20s %-15s %-15s %4s %-8s %-8s%s",
2488 "Prefix", "Registered VN", "Registered UN", "Cost",
2490 #if RFAPI_REGISTRATIONS_REPORT_AGE
2499 char str_vn
[BUFSIZ
];
2500 char str_un
[BUFSIZ
];
2505 fp (out
, "%-15s %-15s%s",
2506 rfapiRfapiIpAddr2Str (&rfd
->vn_addr
, str_vn
, BUFSIZ
),
2507 rfapiRfapiIpAddr2Str (&rfd
->un_addr
, str_un
, BUFSIZ
),
2511 prefix2str (&rn
->p
, str_pfx
, BUFSIZ
);
2512 //fp(out, " %s%s", buf, VTY_NEWLINE); /* prefix */
2515 nhs_displayed
+= print_rib_sl (fp
, vty
, out
, sl
,
2516 show_removed
, str_pfx
,
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
);