Current code treats all metaqueues as lists of route_node structures.
However, some queues contain other structures that need to be cleaned up
differently. Casting the elements of those queues to struct route_node
and dereferencing them leads to a crash. The crash may be seen when
executing bgp_multi_vrf_topo2.
Fix the code by using the proper list element types.
Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
(cherry picked from commit
0ef6eacc95c82014c04f13be3b641ff3983040ca)
struct in_addr vtep_ip);
extern void meta_queue_free(struct meta_queue *mq);
+extern void rib_meta_queue_free_vrf(struct meta_queue *mq,
+ struct zebra_vrf *zvrf);
extern int zebra_rib_labeled_unicast(struct route_entry *re);
extern struct route_table *rib_table_ipv6;
XFREE(MTYPE_WORK_QUEUE, mq);
}
+void rib_meta_queue_free_vrf(struct meta_queue *mq, struct zebra_vrf *zvrf)
+{
+ vrf_id_t vrf_id = zvrf->vrf->vrf_id;
+ unsigned int i;
+
+ for (i = 0; i < MQ_SIZE; i++) {
+ struct listnode *lnode, *nnode;
+ void *data;
+ bool del;
+
+ for (ALL_LIST_ELEMENTS(mq->subq[i], lnode, nnode, data)) {
+ del = false;
+
+ if (i == META_QUEUE_EVPN) {
+ struct wq_evpn_wrapper *w = data;
+
+ if (w->vrf_id == vrf_id) {
+ XFREE(MTYPE_WQ_WRAPPER, w);
+ del = true;
+ }
+ } else if (i ==
+ route_info[ZEBRA_ROUTE_NHG].meta_q_map) {
+ struct wq_nhg_wrapper *w = data;
+
+ if (w->type == WQ_NHG_WRAPPER_TYPE_CTX &&
+ w->u.ctx->vrf_id == vrf_id) {
+ nhg_ctx_free(&w->u.ctx);
+ XFREE(MTYPE_WQ_WRAPPER, w);
+ del = true;
+ } else if (w->type == WQ_NHG_WRAPPER_TYPE_NHG &&
+ w->u.nhe->vrf_id == vrf_id) {
+ zebra_nhg_free(w->u.nhe);
+ XFREE(MTYPE_WQ_WRAPPER, w);
+ del = true;
+ }
+ } else {
+ struct route_node *rnode = data;
+ rib_dest_t *dest = rib_dest_from_rnode(rnode);
+
+ if (dest && rib_dest_vrf(dest) == zvrf) {
+ route_unlock_node(rnode);
+ del = true;
+ }
+ }
+
+ if (del) {
+ list_delete_node(mq->subq[i], lnode);
+ mq->size--;
+ }
+ }
+ }
+}
+
/* initialise zebra rib work queue */
static void rib_queue_init(void)
{
struct interface *ifp;
afi_t afi;
safi_t safi;
- unsigned i;
assert(zvrf);
if (IS_ZEBRA_DEBUG_EVENT)
if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
/* clean-up work queues */
- for (i = 0; i < MQ_SIZE; i++) {
- struct listnode *lnode, *nnode;
- struct route_node *rnode;
- rib_dest_t *dest;
-
- for (ALL_LIST_ELEMENTS(zrouter.mq->subq[i], lnode, nnode,
- rnode)) {
- dest = rib_dest_from_rnode(rnode);
- if (dest && rib_dest_vrf(dest) == zvrf) {
- route_unlock_node(rnode);
- list_delete_node(zrouter.mq->subq[i], lnode);
- zrouter.mq->size--;
- }
- }
- }
+ rib_meta_queue_free_vrf(zrouter.mq, zvrf);
/* Cleanup (free) routing tables and NHT tables. */
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
struct route_table *table;
afi_t afi;
safi_t safi;
- unsigned i;
assert(zvrf);
if (IS_ZEBRA_DEBUG_EVENT)
zvrf_id(zvrf));
/* clean-up work queues */
- for (i = 0; i < MQ_SIZE; i++) {
- struct listnode *lnode, *nnode;
- struct route_node *rnode;
- rib_dest_t *dest;
-
- for (ALL_LIST_ELEMENTS(zrouter.mq->subq[i], lnode, nnode,
- rnode)) {
- dest = rib_dest_from_rnode(rnode);
- if (dest && rib_dest_vrf(dest) == zvrf) {
- route_unlock_node(rnode);
- list_delete_node(zrouter.mq->subq[i], lnode);
- zrouter.mq->size--;
- }
- }
- }
+ rib_meta_queue_free_vrf(zrouter.mq, zvrf);
/* Free Vxlan and MPLS. */
zebra_vxlan_close_tables(zvrf);