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 | |
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>
-rw-r--r-- | include/net/inet6_hashtables.h | 13 | ||||
-rw-r--r-- | include/net/protocol.h | 2 | ||||
-rw-r--r-- | net/ipv4/ip_input.c | 1 | ||||
-rw-r--r-- | net/ipv6/ip6_input.c | 13 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 38 |
5 files changed, 59 insertions, 8 deletions
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h index 00cbb4384c79..9e34c877a770 100644 --- a/include/net/inet6_hashtables.h +++ b/include/net/inet6_hashtables.h | |||
@@ -96,14 +96,15 @@ static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo, | |||
96 | const __be16 sport, | 96 | const __be16 sport, |
97 | const __be16 dport) | 97 | const __be16 dport) |
98 | { | 98 | { |
99 | struct sock *sk; | 99 | struct sock *sk = skb_steal_sock(skb); |
100 | 100 | ||
101 | if (unlikely(sk = skb_steal_sock(skb))) | 101 | if (sk) |
102 | return sk; | 102 | return sk; |
103 | else return __inet6_lookup(dev_net(skb_dst(skb)->dev), hashinfo, | 103 | |
104 | &ipv6_hdr(skb)->saddr, sport, | 104 | return __inet6_lookup(dev_net(skb_dst(skb)->dev), hashinfo, |
105 | &ipv6_hdr(skb)->daddr, ntohs(dport), | 105 | &ipv6_hdr(skb)->saddr, sport, |
106 | inet6_iif(skb)); | 106 | &ipv6_hdr(skb)->daddr, ntohs(dport), |
107 | inet6_iif(skb)); | ||
107 | } | 108 | } |
108 | 109 | ||
109 | extern struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, | 110 | extern struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, |
diff --git a/include/net/protocol.h b/include/net/protocol.h index 057f2d315567..929528c73fe8 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h | |||
@@ -52,6 +52,8 @@ struct net_protocol { | |||
52 | 52 | ||
53 | #if IS_ENABLED(CONFIG_IPV6) | 53 | #if IS_ENABLED(CONFIG_IPV6) |
54 | struct inet6_protocol { | 54 | struct inet6_protocol { |
55 | void (*early_demux)(struct sk_buff *skb); | ||
56 | |||
55 | int (*handler)(struct sk_buff *skb); | 57 | int (*handler)(struct sk_buff *skb); |
56 | 58 | ||
57 | void (*err_handler)(struct sk_buff *skb, | 59 | void (*err_handler)(struct sk_buff *skb, |
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index bda8cac2ae91..981ff1eef28c 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c | |||
@@ -314,6 +314,7 @@ drop: | |||
314 | } | 314 | } |
315 | 315 | ||
316 | int sysctl_ip_early_demux __read_mostly = 1; | 316 | int sysctl_ip_early_demux __read_mostly = 1; |
317 | EXPORT_SYMBOL(sysctl_ip_early_demux); | ||
317 | 318 | ||
318 | static int ip_rcv_finish(struct sk_buff *skb) | 319 | static int ip_rcv_finish(struct sk_buff *skb) |
319 | { | 320 | { |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 5ab923e51af3..47975e363fcd 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -47,9 +47,18 @@ | |||
47 | 47 | ||
48 | 48 | ||
49 | 49 | ||
50 | inline int ip6_rcv_finish( struct sk_buff *skb) | 50 | int ip6_rcv_finish(struct sk_buff *skb) |
51 | { | 51 | { |
52 | if (skb_dst(skb) == NULL) | 52 | if (sysctl_ip_early_demux && !skb_dst(skb)) { |
53 | const struct inet6_protocol *ipprot; | ||
54 | |||
55 | rcu_read_lock(); | ||
56 | ipprot = rcu_dereference(inet6_protos[ipv6_hdr(skb)->nexthdr]); | ||
57 | if (ipprot && ipprot->early_demux) | ||
58 | ipprot->early_demux(skb); | ||
59 | rcu_read_unlock(); | ||
60 | } | ||
61 | if (!skb_dst(skb)) | ||
53 | ip6_route_input(skb); | 62 | ip6_route_input(skb); |
54 | 63 | ||
55 | return dst_input(skb); | 64 | return dst_input(skb); |
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, |