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>