From owner-freebsd-net@FreeBSD.ORG Wed Nov 7 23:24:39 2012 Return-Path: Delivered-To: freebsd-net@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 4F20CB75; Wed, 7 Nov 2012 23:24:39 +0000 (UTC) (envelope-from melifaro@FreeBSD.org) Received: from mail.ipfw.ru (unknown [IPv6:2a01:4f8:120:6141::2]) by mx1.freebsd.org (Postfix) with ESMTP id D538F8FC0A; Wed, 7 Nov 2012 23:24:38 +0000 (UTC) Received: from v6.mpls.in ([2a02:978:2::5] helo=ws.su29.net) by mail.ipfw.ru with esmtpsa (TLSv1:CAMELLIA256-SHA:256) (Exim 4.76 (FreeBSD)) (envelope-from ) id 1TWF2U-000HvY-7R; Thu, 08 Nov 2012 03:28:06 +0400 Message-ID: <509AEDAC.10002@FreeBSD.org> Date: Thu, 08 Nov 2012 03:24:28 +0400 From: "Alexander V. Chernikov" User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:9.0) Gecko/20120121 Thunderbird/9.0 MIME-Version: 1.0 To: freebsd-net@FreeBSD.org, freebsd-hackers@FreeBSD.org Subject: [patch] reducing arp locking Content-Type: multipart/mixed; boundary="------------030808050000070300050904" X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 07 Nov 2012 23:24:39 -0000 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--