summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2008-07-26 21:12:00 +0000
committermav <mav@FreeBSD.org>2008-07-26 21:12:00 +0000
commit0023432ccb7d63af134efbd3fd6d31194cf5e73a (patch)
treea6f5961393a2355c43dd79f4e2e071d165210fcc
parentc85943e33bb3ab8bad591d4c718ec2870992a844 (diff)
downloadFreeBSD-src-0023432ccb7d63af134efbd3fd6d31194cf5e73a.zip
FreeBSD-src-0023432ccb7d63af134efbd3fd6d31194cf5e73a.tar.gz
According to in_pcb.h protocol binding information has double locking.
It allows access it while list travercing holding only global pcbinfo lock. This relaxed locking noticably increses receive socket lookup performance.
-rw-r--r--sys/netinet/raw_ip.c46
1 files changed, 22 insertions, 24 deletions
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index a648555..ebb8408 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -246,28 +246,27 @@ rip_input(struct mbuf *m, int off)
ripsrc.sin_family = AF_INET;
ripsrc.sin_addr = ip->ip_src;
last = NULL;
- INP_INFO_RLOCK(&ripcbinfo);
hash = INP_PCBHASH_RAW(proto, ip->ip_src.s_addr,
ip->ip_dst.s_addr, ripcbinfo.ipi_hashmask);
+ INP_INFO_RLOCK(&ripcbinfo);
LIST_FOREACH(inp, &ripcbinfo.ipi_hashbase[hash], inp_hash) {
- INP_RLOCK(inp);
- if (inp->inp_ip_p != proto) {
- docontinue1:
- INP_RUNLOCK(inp);
+ if (inp->inp_ip_p != proto)
continue;
- }
#ifdef INET6
if ((inp->inp_vflag & INP_IPV4) == 0)
- goto docontinue1;
+ continue;
#endif
if (inp->inp_laddr.s_addr != ip->ip_dst.s_addr)
- goto docontinue1;
+ continue;
if (inp->inp_faddr.s_addr != ip->ip_src.s_addr)
- goto docontinue1;
+ continue;
+ INP_RLOCK(inp);
if (jailed(inp->inp_socket->so_cred) &&
(htonl(prison_getip(inp->inp_socket->so_cred)) !=
- ip->ip_dst.s_addr))
- goto docontinue1;
+ ip->ip_dst.s_addr)) {
+ INP_RUNLOCK(inp);
+ continue;
+ }
if (last) {
struct mbuf *n;
@@ -280,26 +279,25 @@ rip_input(struct mbuf *m, int off)
last = inp;
}
LIST_FOREACH(inp, &ripcbinfo.ipi_hashbase[0], inp_hash) {
- INP_RLOCK(inp);
- if (inp->inp_ip_p && inp->inp_ip_p != proto) {
- docontinue:
- INP_RUNLOCK(inp);
+ if (inp->inp_ip_p && inp->inp_ip_p != proto)
continue;
- }
#ifdef INET6
if ((inp->inp_vflag & INP_IPV4) == 0)
- goto docontinue;
+ continue;
#endif
if (inp->inp_laddr.s_addr &&
inp->inp_laddr.s_addr != ip->ip_dst.s_addr)
- goto docontinue;
+ continue;
if (inp->inp_faddr.s_addr &&
inp->inp_faddr.s_addr != ip->ip_src.s_addr)
- goto docontinue;
- if (jailed(inp->inp_socket->so_cred))
- if (htonl(prison_getip(inp->inp_socket->so_cred)) !=
- ip->ip_dst.s_addr)
- goto docontinue;
+ continue;
+ INP_RLOCK(inp);
+ if (jailed(inp->inp_socket->so_cred) &&
+ (htonl(prison_getip(inp->inp_socket->so_cred)) !=
+ ip->ip_dst.s_addr)) {
+ INP_RUNLOCK(inp);
+ continue;
+ }
if (last) {
struct mbuf *n;
@@ -311,6 +309,7 @@ rip_input(struct mbuf *m, int off)
}
last = inp;
}
+ INP_INFO_RUNLOCK(&ripcbinfo);
if (last != NULL) {
if (rip_append(last, ip, m, &ripsrc) != 0)
ipstat.ips_delivered--;
@@ -320,7 +319,6 @@ rip_input(struct mbuf *m, int off)
ipstat.ips_noproto++;
ipstat.ips_delivered--;
}
- INP_INFO_RUNLOCK(&ripcbinfo);
}
/*
OpenPOWER on IntegriCloud