Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 08 Nov 2012 03:24:28 +0400
From:      "Alexander V. Chernikov" <melifaro@FreeBSD.org>
To:        freebsd-net@FreeBSD.org, freebsd-hackers@FreeBSD.org
Subject:   [patch] reducing arp locking
Message-ID:  <509AEDAC.10002@FreeBSD.org>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------030808050000070300050904
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Hello list!

Currently we need to acquire 2 read locks to perform simple 6-byte 
copying from arp record to packet ethernet header.

It seems that acquiring lle lock for fast path (main traffic flow) is 
not necessary even with current code.

My tests shows ~10% improvement with this patch applied.

If nobody objects I plan to commit this change at the end of next week.


--------------030808050000070300050904
Content-Type: text/plain;
 name="no_arp_lle_lock.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="no_arp_lle_lock.diff"

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)

--------------030808050000070300050904--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?509AEDAC.10002>