commit ea0632e9eeee22c2150c5592810799482feb9b12 Author: Mark Johnston Date: Tue Jan 15 22:44:13 2019 -0500 Tentative fix for lle race. diff --git a/sys/netinet/in.c b/sys/netinet/in.c index 094ee7c9eb3a..b5c477ccd76e 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -1382,15 +1382,13 @@ in_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3add IF_AFDATA_LOCK_ASSERT(llt->llt_ifp); KASSERT(l3addr->sa_family == AF_INET, ("sin_family %d", l3addr->sa_family)); - lle = in_lltable_find_dst(llt, sin->sin_addr); + KASSERT((flags & (LLE_UNLOCKED | LLE_EXCLUSIVE)) != + (LLE_UNLOCKED | LLE_EXCLUSIVE), + ("wrong lle request flags: %#x", flags)); + lle = in_lltable_find_dst(llt, sin->sin_addr); if (lle == NULL) return (NULL); - - KASSERT((flags & (LLE_UNLOCKED|LLE_EXCLUSIVE)) != - (LLE_UNLOCKED|LLE_EXCLUSIVE),("wrong lle request flags: 0x%X", - flags)); - if (flags & LLE_UNLOCKED) return (lle); @@ -1398,7 +1396,13 @@ in_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3add LLE_WLOCK(lle); else LLE_RLOCK(lle); - + if (__predict_false((lle->la_flags & LLE_LINKED) == 0)) { + if (flags & LLE_EXCLUSIVE) + LLE_WUNLOCK(lle); + else + LLE_RUNLOCK(lle); + return (NULL); + } return (lle); } diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 0f34397a15f7..9b11261cd7eb 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -2325,16 +2325,13 @@ in6_lltable_lookup(struct lltable *llt, u_int flags, IF_AFDATA_LOCK_ASSERT(llt->llt_ifp); KASSERT(l3addr->sa_family == AF_INET6, ("sin_family %d", l3addr->sa_family)); + KASSERT((flags & (LLE_UNLOCKED | LLE_EXCLUSIVE)) != + (LLE_UNLOCKED | LLE_EXCLUSIVE), + ("wrong lle request flags: %#x", flags)); lle = in6_lltable_find_dst(llt, &sin6->sin6_addr); - if (lle == NULL) return (NULL); - - KASSERT((flags & (LLE_UNLOCKED|LLE_EXCLUSIVE)) != - (LLE_UNLOCKED|LLE_EXCLUSIVE),("wrong lle request flags: 0x%X", - flags)); - if (flags & LLE_UNLOCKED) return (lle); @@ -2342,6 +2339,13 @@ in6_lltable_lookup(struct lltable *llt, u_int flags, LLE_WLOCK(lle); else LLE_RLOCK(lle); + if (__predict_false((lle->la_flags & LLE_LINKED) == 0)) { + if (flags & LLE_EXCLUSIVE) + LLE_WUNLOCK(lle); + else + LLE_RUNLOCK(lle); + return (NULL); + } return (lle); }