diff options
author | mav <mav@FreeBSD.org> | 2008-07-26 21:12:00 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2008-07-26 21:12:00 +0000 |
commit | 0023432ccb7d63af134efbd3fd6d31194cf5e73a (patch) | |
tree | a6f5961393a2355c43dd79f4e2e071d165210fcc /sys/netinet/raw_ip.c | |
parent | c85943e33bb3ab8bad591d4c718ec2870992a844 (diff) | |
download | FreeBSD-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.c | 46 |
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); } /* |