Hi, Some checks in nd6_resolve() do not require kernel lock. The analog code for ARP has been unlocked in if_ether.c revision 1.250 since 2022/06/27 20:47:10.
ok? bluhm Index: netinet6/nd6.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/nd6.c,v retrieving revision 1.273 diff -u -p -r1.273 nd6.c --- netinet6/nd6.c 2 May 2023 06:06:13 -0000 1.273 +++ netinet6/nd6.c 2 May 2023 18:44:23 -0000 @@ -1260,15 +1260,12 @@ nd6_resolve(struct ifnet *ifp, struct rt return (0); } - /* XXXSMP there is a MP race in nd6_resolve() */ - KERNEL_LOCK(); uptime = getuptime(); rt = rt_getll(rt0); if (ISSET(rt->rt_flags, RTF_REJECT) && (rt->rt_expire == 0 || rt->rt_expire > uptime)) { m_freem(m); - KERNEL_UNLOCK(); return (rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); } @@ -1291,6 +1288,11 @@ nd6_resolve(struct ifnet *ifp, struct rt goto bad; } + KERNEL_LOCK(); + if (!ISSET(rt->rt_flags, RTF_LLINFO)) { + KERNEL_UNLOCK(); + goto bad; + } ln = (struct llinfo_nd6 *)rt->rt_llinfo; KASSERT(ln != NULL); @@ -1321,6 +1323,8 @@ nd6_resolve(struct ifnet *ifp, struct rt * send the packet. */ if (ln->ln_state > ND6_LLINFO_INCOMPLETE) { + KERNEL_UNLOCK(); + sdl = satosdl(rt->rt_gateway); if (sdl->sdl_alen != ETHER_ADDR_LEN) { char addr[INET6_ADDRSTRLEN]; @@ -1332,7 +1336,6 @@ nd6_resolve(struct ifnet *ifp, struct rt } bcopy(LLADDR(sdl), desten, sdl->sdl_alen); - KERNEL_UNLOCK(); return (0); } @@ -1374,7 +1377,6 @@ nd6_resolve(struct ifnet *ifp, struct rt bad: m_freem(m); - KERNEL_UNLOCK(); return (EINVAL); }