summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/raw_ip6.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2008-07-30 09:26:27 +0000
committerrwatson <rwatson@FreeBSD.org>2008-07-30 09:26:27 +0000
commit13b6ce6962eaf8de9b16589dde1fa06b5947d5f8 (patch)
treef8f359f7fc34d3a796eb842467eb89cc34d73994 /sys/netinet6/raw_ip6.c
parent0c146c189c9a742f1346ef7f1e073813fb958f2c (diff)
downloadFreeBSD-src-13b6ce6962eaf8de9b16589dde1fa06b5947d5f8.zip
FreeBSD-src-13b6ce6962eaf8de9b16589dde1fa06b5947d5f8.tar.gz
Adopt the slightly weaker consistency locking approach used in IPv4 raw
sockets for IPv6 raw sockets: separately lock the inpcb for determining the destination address for a connect()'d raw socket at the rip6_send() layer, and then re-acquire the inpcb lock in the rip6_output() layer to query other options on the socket. Previously, the global raw IP socket lock was used, which while correct and marginally more consistent, could add significantly to global raw IP socket lock contention. MFC after: 1 week
Diffstat (limited to 'sys/netinet6/raw_ip6.c')
-rw-r--r--sys/netinet6/raw_ip6.c10
1 files changed, 3 insertions, 7 deletions
diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c
index 4f02f32..9a35dc1 100644
--- a/sys/netinet6/raw_ip6.c
+++ b/sys/netinet6/raw_ip6.c
@@ -756,12 +756,10 @@ rip6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("rip6_send: inp == NULL"));
- INP_INFO_WLOCK(&ripcbinfo);
/* Always copy sockaddr to avoid overwrites. */
/* Unlocked read. */
if (so->so_state & SS_ISCONNECTED) {
if (nam) {
- INP_INFO_WUNLOCK(&ripcbinfo);
m_freem(m);
return (EISCONN);
}
@@ -769,17 +767,17 @@ rip6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
bzero(&tmp, sizeof(tmp));
tmp.sin6_family = AF_INET6;
tmp.sin6_len = sizeof(struct sockaddr_in6);
+ INP_RLOCK(inp);
bcopy(&inp->in6p_faddr, &tmp.sin6_addr,
- sizeof(struct in6_addr));
+ sizeof(struct in6_addr));
+ INP_RUNLOCK(inp);
dst = &tmp;
} else {
if (nam == NULL) {
- INP_INFO_WUNLOCK(&ripcbinfo);
m_freem(m);
return (ENOTCONN);
}
if (nam->sa_len != sizeof(struct sockaddr_in6)) {
- INP_INFO_WUNLOCK(&ripcbinfo);
m_freem(m);
return (EINVAL);
}
@@ -796,13 +794,11 @@ rip6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
"unspec. Assume AF_INET6\n");
dst->sin6_family = AF_INET6;
} else if (dst->sin6_family != AF_INET6) {
- INP_INFO_WUNLOCK(&ripcbinfo);
m_freem(m);
return(EAFNOSUPPORT);
}
}
ret = rip6_output(m, so, dst, control);
- INP_INFO_WUNLOCK(&ripcbinfo);
return (ret);
}
OpenPOWER on IntegriCloud