diff options
author | Eric Dumazet <edumazet@google.com> | 2012-07-26 08:18:11 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-07-26 18:50:39 -0400 |
commit | c7109986db3c945f50ceed884a30e0fd8af3b89b (patch) | |
tree | c0852e90a7d06bdc95a54d6adad19d2a9e3d7d5e /net/ipv6/tcp_ipv6.c | |
parent | c6cffba4ffa26a8ffacd0bb9f3144e34f20da7de (diff) |
ipv6: Early TCP socket demux
This is the IPv6 missing bits for infrastructure added in commit
41063e9dd1195 (ipv4: Early TCP socket demux.)
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index f49476e2d884..221224e72507 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1674,6 +1674,43 @@ do_time_wait: | |||
1674 | goto discard_it; | 1674 | goto discard_it; |
1675 | } | 1675 | } |
1676 | 1676 | ||
1677 | static void tcp_v6_early_demux(struct sk_buff *skb) | ||
1678 | { | ||
1679 | const struct ipv6hdr *hdr; | ||
1680 | const struct tcphdr *th; | ||
1681 | struct sock *sk; | ||
1682 | |||
1683 | if (skb->pkt_type != PACKET_HOST) | ||
1684 | return; | ||
1685 | |||
1686 | if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct tcphdr))) | ||
1687 | return; | ||
1688 | |||
1689 | hdr = ipv6_hdr(skb); | ||
1690 | th = tcp_hdr(skb); | ||
1691 | |||
1692 | if (th->doff < sizeof(struct tcphdr) / 4) | ||
1693 | return; | ||
1694 | |||
1695 | sk = __inet6_lookup_established(dev_net(skb->dev), &tcp_hashinfo, | ||
1696 | &hdr->saddr, th->source, | ||
1697 | &hdr->daddr, ntohs(th->dest), | ||
1698 | inet6_iif(skb)); | ||
1699 | if (sk) { | ||
1700 | skb->sk = sk; | ||
1701 | skb->destructor = sock_edemux; | ||
1702 | if (sk->sk_state != TCP_TIME_WAIT) { | ||
1703 | struct dst_entry *dst = sk->sk_rx_dst; | ||
1704 | struct inet_sock *icsk = inet_sk(sk); | ||
1705 | if (dst) | ||
1706 | dst = dst_check(dst, 0); | ||
1707 | if (dst && | ||
1708 | icsk->rx_dst_ifindex == inet6_iif(skb)) | ||
1709 | skb_dst_set_noref(skb, dst); | ||
1710 | } | ||
1711 | } | ||
1712 | } | ||
1713 | |||
1677 | static struct timewait_sock_ops tcp6_timewait_sock_ops = { | 1714 | static struct timewait_sock_ops tcp6_timewait_sock_ops = { |
1678 | .twsk_obj_size = sizeof(struct tcp6_timewait_sock), | 1715 | .twsk_obj_size = sizeof(struct tcp6_timewait_sock), |
1679 | .twsk_unique = tcp_twsk_unique, | 1716 | .twsk_unique = tcp_twsk_unique, |
@@ -1984,6 +2021,7 @@ struct proto tcpv6_prot = { | |||
1984 | }; | 2021 | }; |
1985 | 2022 | ||
1986 | static const struct inet6_protocol tcpv6_protocol = { | 2023 | static const struct inet6_protocol tcpv6_protocol = { |
2024 | .early_demux = tcp_v6_early_demux, | ||
1987 | .handler = tcp_v6_rcv, | 2025 | .handler = tcp_v6_rcv, |
1988 | .err_handler = tcp_v6_err, | 2026 | .err_handler = tcp_v6_err, |
1989 | .gso_send_check = tcp_v6_gso_send_check, | 2027 | .gso_send_check = tcp_v6_gso_send_check, |