History

net: ipv6: fix TCP early demux

IPv6 needs a cookie in dst_check() call. We need to add rx_dst_cookie and provide a family independent sk_rx_dst_set(sk, skb) method to properly support IPv6 TCP early demux.

Eric Dumazet committed 14 years ago

Commit 5d299f31 parent b5497ee7 files · +41 −16Browse files

Unified · Split

7 files
  1. include/linux/ipv6.h +1 −0
  2. include/net/inet_connection_sock.h +1 −0
  3. include/net/inet_sock.h +0 −9
  4. net/ipv4/tcp_input.c +3 −1
  5. net/ipv4/tcp_ipv4.c +10 −3
  6. net/ipv4/tcp_minisocks.c +1 −1
  7. net/ipv6/tcp_ipv6.c +25 −2
include/linux/ipv6.h+1−0
@@ -369,6 +369,7 @@ struct ipv6_pinfo { · 368 unmodified lines
369369 __u8 rcv_tclass;
370370
371371 __u32 dst_cookie;
372+ __u32 rx_dst_cookie;
372373
373374 struct ipv6_mc_socklist __rcu *ipv6_mc_list;
374375 struct ipv6_ac_socklist *ipv6_ac_list;
include/net/inet_connection_sock.h+1−0
@@ -39,6 +39,7 @@ struct inet_connection_sock_af_ops { · 38 unmodified lines
3939 int (*queue_xmit)(struct sk_buff *skb, struct flowi *fl);
4040 void (*send_check)(struct sock *sk, struct sk_buff *skb);
4141 int (*rebuild_header)(struct sock *sk);
42+ void (*sk_rx_dst_set)(struct sock *sk, const struct sk_buff *skb);
4243 int (*conn_request)(struct sock *sk, struct sk_buff *skb);
4344 struct sock *(*syn_recv_sock)(struct sock *sk, struct sk_buff *skb,
4445 struct request_sock *req,
include/net/inet_sock.h+0−9
@@ -249,13 +249,4 @@ static inline __u8 inet_sk_flowi_flags(const struct sock *sk) · 248 unmodified lines
249249 return flags;
250250 }
251251
252−static inline void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb)
253−{
254− struct dst_entry *dst = skb_dst(skb);
255−
256− dst_hold(dst);
257− sk->sk_rx_dst = dst;
258− inet_sk(sk)->rx_dst_ifindex = skb->skb_iif;
259−}
260−
261252 #endif /* _INET_SOCK_H */
net/ipv4/tcp_input.c+3−1
@@ -5392,6 +5392,8 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, · 5391 unmodified lines
53925392 {
53935393 struct tcp_sock *tp = tcp_sk(sk);
53945394
5395+ if (unlikely(sk->sk_rx_dst == NULL))
5396+ inet_csk(sk)->icsk_af_ops->sk_rx_dst_set(sk, skb);
53955397 /*
53965398 * Header prediction.
53975399 * The code loosely follows the one in the famous
@@ -5605,7 +5607,7 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb) · 207 unmodified lines
56055607 tcp_set_state(sk, TCP_ESTABLISHED);
56065608
56075609 if (skb != NULL) {
5608− inet_sk_rx_dst_set(sk, skb);
5610+ icsk->icsk_af_ops->sk_rx_dst_set(sk, skb);
56095611 security_inet_conn_established(sk, skb);
56105612 }
56115613
net/ipv4/tcp_ipv4.c+10−3
@@ -1627,9 +1627,6 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) · 1626 unmodified lines
16271627 sk->sk_rx_dst = NULL;
16281628 }
16291629 }
1630− if (unlikely(sk->sk_rx_dst == NULL))
1631− inet_sk_rx_dst_set(sk, skb);
1632−
16331630 if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) {
16341631 rsk = sk;
16351632 goto reset;
@@ -1872,10 +1869,20 @@ static struct timewait_sock_ops tcp_timewait_sock_ops = { · 236 unmodified lines
18721869 .twsk_destructor= tcp_twsk_destructor,
18731870 };
18741871
1872+static void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb)
1873+{
1874+ struct dst_entry *dst = skb_dst(skb);
1875+
1876+ dst_hold(dst);
1877+ sk->sk_rx_dst = dst;
1878+ inet_sk(sk)->rx_dst_ifindex = skb->skb_iif;
1879+}
1880+
18751881 const struct inet_connection_sock_af_ops ipv4_specific = {
18761882 .queue_xmit = ip_queue_xmit,
18771883 .send_check = tcp_v4_send_check,
18781884 .rebuild_header = inet_sk_rebuild_header,
1885+ .sk_rx_dst_set = inet_sk_rx_dst_set,
18791886 .conn_request = tcp_v4_conn_request,
18801887 .syn_recv_sock = tcp_v4_syn_recv_sock,
18811888 .net_header_len = sizeof(struct iphdr),
net/ipv4/tcp_minisocks.c+1−1
@@ -387,7 +387,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, · 386 unmodified lines
387387 struct tcp_sock *oldtp = tcp_sk(sk);
388388 struct tcp_cookie_values *oldcvp = oldtp->cookie_values;
389389
390− inet_sk_rx_dst_set(newsk, skb);
390+ newicsk->icsk_af_ops->sk_rx_dst_set(newsk, skb);
391391
392392 /* TCP Cookie Transactions require space for the cookie pair,
393393 * as it differs for each connection. There is no need to
net/ipv6/tcp_ipv6.c+25−2
@@ -1447,7 +1447,17 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) · 1446 unmodified lines
14471447 opt_skb = skb_clone(skb, sk_gfp_atomic(sk, GFP_ATOMIC));
14481448
14491449 if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
1450+ struct dst_entry *dst = sk->sk_rx_dst;
1451+
14501452 sock_rps_save_rxhash(sk, skb);
1453+ if (dst) {
1454+ if (inet_sk(sk)->rx_dst_ifindex != skb->skb_iif ||
1455+ dst->ops->check(dst, np->rx_dst_cookie) == NULL) {
1456+ dst_release(dst);
1457+ sk->sk_rx_dst = NULL;
1458+ }
1459+ }
1460+
14511461 if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len))
14521462 goto reset;
14531463 if (opt_skb)
@@ -1705,9 +1715,9 @@ static void tcp_v6_early_demux(struct sk_buff *skb) · 251 unmodified lines
17051715 struct dst_entry *dst = sk->sk_rx_dst;
17061716 struct inet_sock *icsk = inet_sk(sk);
17071717 if (dst)
1708− dst = dst_check(dst, 0);
1718+ dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie);
17091719 if (dst &&
1710− icsk->rx_dst_ifindex == inet6_iif(skb))
1720+ icsk->rx_dst_ifindex == skb->skb_iif)
17111721 skb_dst_set_noref(skb, dst);
17121722 }
17131723 }
@@ -1719,10 +1729,23 @@ static struct timewait_sock_ops tcp6_timewait_sock_ops = { · 5 unmodified lines
17191729 .twsk_destructor= tcp_twsk_destructor,
17201730 };
17211731
1732+static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb)
1733+{
1734+ struct dst_entry *dst = skb_dst(skb);
1735+ const struct rt6_info *rt = (const struct rt6_info *)dst;
1736+
1737+ dst_hold(dst);
1738+ sk->sk_rx_dst = dst;
1739+ inet_sk(sk)->rx_dst_ifindex = skb->skb_iif;
1740+ if (rt->rt6i_node)
1741+ inet6_sk(sk)->rx_dst_cookie = rt->rt6i_node->fn_sernum;
1742+}
1743+
17221744 static const struct inet_connection_sock_af_ops ipv6_specific = {
17231745 .queue_xmit = inet6_csk_xmit,
17241746 .send_check = tcp_v6_send_check,
17251747 .rebuild_header = inet6_sk_rebuild_header,
1748+ .sk_rx_dst_set = inet6_sk_rx_dst_set,
17261749 .conn_request = tcp_v6_conn_request,
17271750 .syn_recv_sock = tcp_v6_syn_recv_sock,
17281751 .net_header_len = sizeof(struct ipv6hdr),