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.
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)
_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"