| From foo@baz Fri Nov 7 11:36:50 PST 2014 |
| From: Sathya Perla <sathya.perla@emulex.com> |
| Date: Wed, 22 Oct 2014 21:42:01 +0530 |
| Subject: net: fix saving TX flow hash in sock for outgoing connections |
| |
| From: Sathya Perla <sathya.perla@emulex.com> |
| |
| [ Upstream commit 9e7ceb060754f134231f68cb29d5db31419fe1ed ] |
| |
| The commit "net: Save TX flow hash in sock and set in skbuf on xmit" |
| introduced the inet_set_txhash() and ip6_set_txhash() routines to calculate |
| and record flow hash(sk_txhash) in the socket structure. sk_txhash is used |
| to set skb->hash which is used to spread flows across multiple TXQs. |
| |
| But, the above routines are invoked before the source port of the connection |
| is created. Because of this all outgoing connections that just differ in the |
| source port get hashed into the same TXQ. |
| |
| This patch fixes this problem for IPv4/6 by invoking the the above routines |
| after the source port is available for the socket. |
| |
| Fixes: b73c3d0e4("net: Save TX flow hash in sock and set in skbuf on xmit") |
| |
| Signed-off-by: Sathya Perla <sathya.perla@emulex.com> |
| Acked-by: Eric Dumazet <edumazet@google.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/ipv4/tcp_ipv4.c | 4 ++-- |
| net/ipv6/tcp_ipv6.c | 4 ++-- |
| 2 files changed, 4 insertions(+), 4 deletions(-) |
| |
| --- a/net/ipv4/tcp_ipv4.c |
| +++ b/net/ipv4/tcp_ipv4.c |
| @@ -208,8 +208,6 @@ int tcp_v4_connect(struct sock *sk, stru |
| inet->inet_dport = usin->sin_port; |
| inet->inet_daddr = daddr; |
| |
| - inet_set_txhash(sk); |
| - |
| inet_csk(sk)->icsk_ext_hdr_len = 0; |
| if (inet_opt) |
| inet_csk(sk)->icsk_ext_hdr_len = inet_opt->opt.optlen; |
| @@ -226,6 +224,8 @@ int tcp_v4_connect(struct sock *sk, stru |
| if (err) |
| goto failure; |
| |
| + inet_set_txhash(sk); |
| + |
| rt = ip_route_newports(fl4, rt, orig_sport, orig_dport, |
| inet->inet_sport, inet->inet_dport, sk); |
| if (IS_ERR(rt)) { |
| --- a/net/ipv6/tcp_ipv6.c |
| +++ b/net/ipv6/tcp_ipv6.c |
| @@ -198,8 +198,6 @@ static int tcp_v6_connect(struct sock *s |
| sk->sk_v6_daddr = usin->sin6_addr; |
| np->flow_label = fl6.flowlabel; |
| |
| - ip6_set_txhash(sk); |
| - |
| /* |
| * TCP over IPv4 |
| */ |
| @@ -295,6 +293,8 @@ static int tcp_v6_connect(struct sock *s |
| if (err) |
| goto late_failure; |
| |
| + ip6_set_txhash(sk); |
| + |
| if (!tp->write_seq && likely(!tp->repair)) |
| tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32, |
| sk->sk_v6_daddr.s6_addr32, |