On Tue, Apr 25, 2023 at 11:44:34AM +0200, Alexander Bluhm wrote:
> Hi,
>
> Mutex arp_mtx protects the llinfo_arp la_... fields. So kernel
> lock is only needed for changing the route rt_flags.
>
> Of course there is a race between checking and setting rt_flags.
> But the other checks of the RTF_REJECT flags were without kernel
> lock before. This does not cause trouble, the worst thing that may
> happen is to wait another exprire time for ARP retry. My diff does
> not make it worse, reading rt_flags and rt_expire is done without
> lock anyway.
>
> The kernel lock is needed to change rt_flags. Testing without
> KERNEL_LOCK() caused crashes.
>
Hi,
I'm interesting is the system stable with the diff below? If so, we
could avoid kernel lock in the arpresolve().
Index: sys/netinet/if_ether.c
===================================================================
RCS file: /cvs/src/sys/netinet/if_ether.c,v
retrieving revision 1.263
diff -u -p -r1.263 if_ether.c
--- sys/netinet/if_ether.c 25 Apr 2023 16:24:25 -0000 1.263
+++ sys/netinet/if_ether.c 25 Apr 2023 20:55:08 -0000
@@ -462,14 +462,20 @@ arpresolve(struct ifnet *ifp, struct rte
mtx_leave(&arp_mtx);
if (reject == RTF_REJECT && !ISSET(rt->rt_flags, RTF_REJECT)) {
- KERNEL_LOCK();
- SET(rt->rt_flags, RTF_REJECT);
- KERNEL_UNLOCK();
+ u_int flags;
+
+ do {
+ flags = rt->rt_flags;
+ } while (atomic_cas_uint(&rt->rt_flags, flags,
+ flags | RTF_REJECT) != flags);
}
if (reject == ~RTF_REJECT && ISSET(rt->rt_flags, RTF_REJECT)) {
- KERNEL_LOCK();
- CLR(rt->rt_flags, RTF_REJECT);
- KERNEL_UNLOCK();
+ u_int flags;
+
+ do {
+ flags = rt->rt_flags;
+ } while (atomic_cas_uint(&rt->rt_flags, flags,
+ flags & ~RTF_REJECT) != flags);
}
if (refresh)
arprequest(ifp, &satosin(rt->rt_ifa->ifa_addr)->sin_addr.s_addr,