Hi, I would like to remove the kernel lock from nd6 resolve and use nd6 mutex instead.
Access rt_llinfo and check for NULL without checking RTF_LLINFO flag before. They are changed togehter with the arp or nd6 mutex. Access rt_llinfo either with nd6 mutex or exclusive netlock. Remove some needless NULL initializations. In nd6 resolve replace kernel lock with nd6 mutex. ok? bluhm Index: netinet/if_ether.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/if_ether.c,v retrieving revision 1.264 diff -u -p -r1.264 if_ether.c --- netinet/if_ether.c 7 May 2023 16:23:23 -0000 1.264 +++ netinet/if_ether.c 11 May 2023 19:00:19 -0000 @@ -388,10 +388,8 @@ arpresolve(struct ifnet *ifp, struct rte rt->rt_expire - arpt_keep / 8 < uptime) { mtx_enter(&arp_mtx); - if (ISSET(rt->rt_flags, RTF_LLINFO)) { - la = (struct llinfo_arp *)rt->rt_llinfo; - KASSERT(la != NULL); - + la = (struct llinfo_arp *)rt->rt_llinfo; + if (la != NULL) { if (la->la_refreshed + 30 < uptime) { la->la_refreshed = uptime; refresh = 1; @@ -412,12 +410,11 @@ arpresolve(struct ifnet *ifp, struct rte goto bad; mtx_enter(&arp_mtx); - if (!ISSET(rt->rt_flags, RTF_LLINFO)) { + la = (struct llinfo_arp *)rt->rt_llinfo; + if (la == NULL) { mtx_leave(&arp_mtx); goto bad; } - la = (struct llinfo_arp *)rt->rt_llinfo; - KASSERT(la != NULL); /* * There is an arptab entry, but no ethernet address Index: netinet6/nd6.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/nd6.c,v retrieving revision 1.278 diff -u -p -r1.278 nd6.c --- netinet6/nd6.c 8 May 2023 13:14:21 -0000 1.278 +++ netinet6/nd6.c 11 May 2023 20:39:58 -0000 @@ -306,7 +306,7 @@ nd6_llinfo_timer(struct rtentry *rt) struct sockaddr_in6 *dst = satosin6(rt_key(rt)); struct ifnet *ifp; - NET_ASSERT_LOCKED(); + NET_ASSERT_LOCKED_EXCLUSIVE(); if ((ifp = if_get(rt->rt_ifidx)) == NULL) return 1; @@ -527,6 +527,7 @@ nd6_lookup(const struct in6_addr *addr6, if (rt == NULL) { if (create && ifp) { struct rt_addrinfo info; + struct llinfo_nd6 *ln; struct ifaddr *ifa; int error; @@ -556,11 +557,11 @@ nd6_lookup(const struct in6_addr *addr6, rtableid); if (error) return (NULL); - if (rt->rt_llinfo != NULL) { - struct llinfo_nd6 *ln = - (struct llinfo_nd6 *)rt->rt_llinfo; + mtx_enter(&nd6_mtx); + ln = (struct llinfo_nd6 *)rt->rt_llinfo; + if (ln != NULL) ln->ln_state = ND6_LLINFO_NOSTATE; - } + mtx_leave(&nd6_mtx); } else return (NULL); } @@ -666,7 +667,7 @@ nd6_free(struct rtentry *rt) struct in6_addr in6 = satosin6(rt_key(rt))->sin6_addr; struct ifnet *ifp; - NET_ASSERT_LOCKED(); + NET_ASSERT_LOCKED_EXCLUSIVE(); ifp = if_get(rt->rt_ifidx); @@ -706,6 +707,8 @@ nd6_nud_hint(struct rtentry *rt) struct llinfo_nd6 *ln; struct ifnet *ifp; + NET_ASSERT_LOCKED_EXCLUSIVE(); + ifp = if_get(rt->rt_ifidx); if (ifp == NULL) return; @@ -741,7 +744,7 @@ void nd6_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt) { struct sockaddr *gate = rt->rt_gateway; - struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo; + struct llinfo_nd6 *ln; struct ifaddr *ifa; struct in6_ifaddr *ifa6; @@ -977,7 +980,7 @@ nd6_ioctl(u_long cmd, caddr_t data, stru struct in6_addr nb_addr = nbi->addr; /* make local for safety */ time_t expire; - NET_LOCK_SHARED(); + NET_LOCK(); /* * XXX: KAME specific hack for scoped addresses * XXXX: for other scopes than link-local? @@ -994,7 +997,7 @@ nd6_ioctl(u_long cmd, caddr_t data, stru if (rt == NULL || (ln = (struct llinfo_nd6 *)rt->rt_llinfo) == NULL) { rtfree(rt); - NET_UNLOCK_SHARED(); + NET_UNLOCK(); return (EINVAL); } expire = ln->ln_rt->rt_expire; @@ -1009,7 +1012,7 @@ nd6_ioctl(u_long cmd, caddr_t data, stru nbi->expire = expire; rtfree(rt); - NET_UNLOCK_SHARED(); + NET_UNLOCK(); return (0); } } @@ -1027,15 +1030,17 @@ void nd6_cache_lladdr(struct ifnet *ifp, const struct in6_addr *from, char *lladdr, int lladdrlen, int type, int code) { - struct rtentry *rt = NULL; - struct llinfo_nd6 *ln = NULL; + struct rtentry *rt; + struct llinfo_nd6 *ln; int is_newentry; - struct sockaddr_dl *sdl = NULL; + struct sockaddr_dl *sdl; int do_update; int olladdr; int llchange; int newstate = 0; + NET_ASSERT_LOCKED_EXCLUSIVE(); + if (!ifp) panic("%s: ifp == NULL", __func__); if (!from) @@ -1257,7 +1262,7 @@ nd6_resolve(struct ifnet *ifp, struct rt { struct sockaddr_dl *sdl; struct rtentry *rt; - struct llinfo_nd6 *ln = NULL; + struct llinfo_nd6 *ln; struct in6_addr saddr6; time_t uptime; int solicit = 0; @@ -1295,23 +1300,20 @@ nd6_resolve(struct ifnet *ifp, struct rt goto bad; } - KERNEL_LOCK(); - if (!ISSET(rt->rt_flags, RTF_LLINFO)) { - KERNEL_UNLOCK(); + mtx_enter(&nd6_mtx); + ln = (struct llinfo_nd6 *)rt->rt_llinfo; + if (ln == NULL) { + mtx_leave(&nd6_mtx); goto bad; } - ln = (struct llinfo_nd6 *)rt->rt_llinfo; - KASSERT(ln != NULL); /* * Move this entry to the head of the queue so that it is less likely * for this entry to be a target of forced garbage collection (see * nd6_rtrequest()). */ - mtx_enter(&nd6_mtx); TAILQ_REMOVE(&nd6_list, ln, ln_list); TAILQ_INSERT_HEAD(&nd6_list, ln, ln_list); - mtx_leave(&nd6_mtx); /* * The first time we send a packet to a neighbor whose entry is @@ -1332,7 +1334,7 @@ nd6_resolve(struct ifnet *ifp, struct rt * send the packet. */ if (ln->ln_state > ND6_LLINFO_INCOMPLETE) { - KERNEL_UNLOCK(); + mtx_leave(&nd6_mtx); sdl = satosdl(rt->rt_gateway); if (sdl->sdl_alen != ETHER_ADDR_LEN) { @@ -1378,7 +1380,7 @@ nd6_resolve(struct ifnet *ifp, struct rt saddr6 = ln->ln_saddr6; solicit = 1; } - KERNEL_UNLOCK(); + mtx_leave(&nd6_mtx); if (solicit) nd6_ns_output(ifp, NULL, &satosin6(dst)->sin6_addr, &saddr6, 0);