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 | |
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.
-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); } /* |