Index: sys/netinet/in.c
===================================================================
--- sys/netinet/in.c	(revision 242524)
+++ sys/netinet/in.c	(working copy)
@@ -1476,7 +1476,7 @@ in_lltable_lookup(struct lltable *llt, u_int flags
 	if (LLE_IS_VALID(lle)) {
 		if (flags & LLE_EXCLUSIVE)
 			LLE_WLOCK(lle);
-		else
+		else if (!(flags & LLE_UNLOCKED))
 			LLE_RLOCK(lle);
 	}
 done:
Index: sys/netinet/if_ether.c
===================================================================
--- sys/netinet/if_ether.c	(revision 242524)
+++ sys/netinet/if_ether.c	(working copy)
@@ -293,10 +293,10 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0,
 	struct sockaddr *dst, u_char *desten, struct llentry **lle)
 {
 	struct llentry *la = 0;
-	u_int flags = 0;
+	u_int flags = LLE_UNLOCKED;
 	struct mbuf *curr = NULL;
 	struct mbuf *next = NULL;
-	int error, renew;
+	int error, renew = 0;
 
 	*lle = NULL;
 	if (m != NULL) {
@@ -315,7 +315,41 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0,
 retry:
 	IF_AFDATA_RLOCK(ifp);
 	la = lla_lookup(LLTABLE(ifp), flags, dst);
+
+	/*
+	 * Fast path. Do not require rlock on llentry.
+	 */
+	if ((la != NULL) && (flags & LLE_UNLOCKED)) {
+		if ((la->la_flags & LLE_VALID) &&
+		    ((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime)) {
+			bcopy(&la->ll_addr, desten, ifp->if_addrlen);
+			/*
+			 * If entry has an expiry time and it is approaching,
+			 * see if we need to send an ARP request within this
+			 * arpt_down interval.
+			 */
+			if (!(la->la_flags & LLE_STATIC) &&
+			    time_uptime + la->la_preempt > la->la_expire) {
+				renew = 1;
+				la->la_preempt--;
+			}
+
+			IF_AFDATA_RUNLOCK(ifp);
+			if (renew != 0)
+				arprequest(ifp, NULL, &SIN(dst)->sin_addr, NULL);
+
+			return (0);
+		}
+
+		/* Revert to normal path for other cases */
+		flags &= ~LLE_UNLOCKED;
+		*lle = la;
+		LLE_RNLOCK(la);
+	}
+
+
 	IF_AFDATA_RUNLOCK(ifp);
+
 	if ((la == NULL) && ((flags & LLE_EXCLUSIVE) == 0)
 	    && ((ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0)) {
 		flags |= (LLE_CREATE | LLE_EXCLUSIVE);
@@ -332,25 +366,6 @@ retry:
 		return (EINVAL);
 	}
 
-	if ((la->la_flags & LLE_VALID) &&
-	    ((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime)) {
-		bcopy(&la->ll_addr, desten, ifp->if_addrlen);
-		/*
-		 * If entry has an expiry time and it is approaching,
-		 * see if we need to send an ARP request within this
-		 * arpt_down interval.
-		 */
-		if (!(la->la_flags & LLE_STATIC) &&
-		    time_uptime + la->la_preempt > la->la_expire) {
-			arprequest(ifp, NULL, &SIN(dst)->sin_addr, NULL);
-			la->la_preempt--;
-		}
-
-		*lle = la;
-		error = 0;
-		goto done;
-	}
-
 	if (la->la_flags & LLE_STATIC) {   /* should not happen! */
 		log(LOG_DEBUG, "arpresolve: ouch, empty static llinfo for %s\n",
 		    inet_ntoa(SIN(dst)->sin_addr));
Index: sys/net/if_llatbl.h
===================================================================
--- sys/net/if_llatbl.h	(revision 242524)
+++ sys/net/if_llatbl.h	(working copy)
@@ -178,6 +178,7 @@ MALLOC_DECLARE(M_LLTABLE);
 #define	LLE_EXCLUSIVE	0x2000	/* return lle xlocked  */
 #define	LLE_DELETE	0x4000	/* delete on a lookup - match LLE_IFADDR */
 #define	LLE_CREATE	0x8000	/* create on a lookup miss */
+#define	LLE_UNLOCKED	0x10000	/* return lle unlocked */
 
 #define LLATBL_HASH(key, mask) \
 	(((((((key >> 8) ^ key) >> 8) ^ key) >> 8) ^ key) & mask)
