net: arp: Fix dead lock caused by arp_mutex

Fix the dead lock between rx_q and tx_q thread.
When tx_q thread prepares to send ARP packet, it might get
the net_if_tx_lock in net_if_tx(), then in net_arp_prepare(),
it will try to get the arp_mutex.
At the same time, if the rx_q thread receives an ARP reply
packet, in arp_update(), it will get the arp_mutex first,
and flush the packets in arp pending_queue and try to get
the net_if_tx_lock. Then the dead lock occurs, two threads
stuck and all the packcets can't be freed.
In arp_update(), taking the net_if_tx_lock first then taking
the arp_mutex can fix this issue.

Signed-off-by: Maochen Wang <maochen.wang@nxp.com>
This commit is contained in:
Maochen Wang 2024-02-21 16:13:44 +08:00 committed by Alberto Escolar
parent f9dddc387e
commit 11a5904760

View file

@ -467,7 +467,7 @@ void net_arp_update(struct net_if *iface,
struct net_pkt *pkt;
NET_DBG("src %s", net_sprint_ipv4_addr(src));
net_if_tx_lock(iface);
k_mutex_lock(&arp_mutex, K_FOREVER);
entry = arp_entry_get_pending(iface, src);
@ -505,6 +505,7 @@ void net_arp_update(struct net_if *iface,
}
k_mutex_unlock(&arp_mutex);
net_if_tx_unlock(iface);
return;
}
@ -534,15 +535,14 @@ void net_arp_update(struct net_if *iface,
* the pkt are not counted twice and the packet filter
* callbacks are only called once.
*/
net_if_tx_lock(iface);
ret = net_if_l2(iface)->send(iface, pkt);
net_if_tx_unlock(iface);
if (ret < 0) {
net_pkt_unref(pkt);
}
}
k_mutex_unlock(&arp_mutex);
net_if_tx_unlock(iface);
}
static inline struct net_pkt *arp_prepare_reply(struct net_if *iface,