Hi, The arp mbuf queue la_mq has its own mutex, la_hold_total uses atomic operations. So they don't need the global arp mutex.
Pull them out of arp_mtx blocks to make clear what the scope of arp_mtx protection is. ok? bluhm Index: netinet/if_ether.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/if_ether.c,v retrieving revision 1.258 diff -u -p -r1.258 if_ether.c --- netinet/if_ether.c 8 Mar 2023 04:43:08 -0000 1.258 +++ netinet/if_ether.c 3 Apr 2023 11:47:57 -0000 @@ -203,6 +203,7 @@ arp_rtrequest(struct ifnet *ifp, int req log(LOG_DEBUG, "%s: pool get failed\n", __func__); break; } + mq_init(&la->la_mq, LA_HOLD_QUEUE, IPL_SOFTNET); mtx_enter(&arp_mtx); if (rt->rt_llinfo != NULL) { @@ -211,7 +212,6 @@ arp_rtrequest(struct ifnet *ifp, int req pool_put(&arp_pool, la); break; } - mq_init(&la->la_mq, LA_HOLD_QUEUE, IPL_SOFTNET); rt->rt_llinfo = (caddr_t)la; la->la_rt = rt; rt->rt_flags |= RTF_LLINFO; @@ -233,9 +233,9 @@ arp_rtrequest(struct ifnet *ifp, int req LIST_REMOVE(la, la_list); rt->rt_llinfo = NULL; rt->rt_flags &= ~RTF_LLINFO; - atomic_sub_int(&la_hold_total, mq_purge(&la->la_mq)); mtx_leave(&arp_mtx); + atomic_sub_int(&la_hold_total, mq_purge(&la->la_mq)); pool_put(&arp_pool, la); break; @@ -755,10 +755,11 @@ arpinvalidate(struct rtentry *rt) mtx_leave(&arp_mtx); return; } - atomic_sub_int(&la_hold_total, mq_purge(&la->la_mq)); sdl->sdl_alen = 0; la->la_asked = 0; mtx_leave(&arp_mtx); + + atomic_sub_int(&la_hold_total, mq_purge(&la->la_mq)); } /*