summaryrefslogtreecommitdiffstats
path: root/sys/netinet/raw_ip.c
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 /sys/netinet/raw_ip.c
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.
Diffstat (limited to 'sys/netinet/raw_ip.c')
-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