Commit 9e7ceb06 authored by Sathya Perla's avatar Sathya Perla Committed by David S. Miller

net: fix saving TX flow hash in sock for outgoing connections

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: b73c3d0e("net: Save TX flow hash in sock and set in skbuf on xmit")
Signed-off-by: default avatarSathya Perla <sathya.perla@emulex.com>
Acked-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 789f2023
...@@ -206,8 +206,6 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ...@@ -206,8 +206,6 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
inet->inet_dport = usin->sin_port; inet->inet_dport = usin->sin_port;
inet->inet_daddr = daddr; inet->inet_daddr = daddr;
inet_set_txhash(sk);
inet_csk(sk)->icsk_ext_hdr_len = 0; inet_csk(sk)->icsk_ext_hdr_len = 0;
if (inet_opt) if (inet_opt)
inet_csk(sk)->icsk_ext_hdr_len = inet_opt->opt.optlen; inet_csk(sk)->icsk_ext_hdr_len = inet_opt->opt.optlen;
...@@ -224,6 +222,8 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ...@@ -224,6 +222,8 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if (err) if (err)
goto failure; goto failure;
inet_set_txhash(sk);
rt = ip_route_newports(fl4, rt, orig_sport, orig_dport, rt = ip_route_newports(fl4, rt, orig_sport, orig_dport,
inet->inet_sport, inet->inet_dport, sk); inet->inet_sport, inet->inet_dport, sk);
if (IS_ERR(rt)) { if (IS_ERR(rt)) {
......
...@@ -200,8 +200,6 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, ...@@ -200,8 +200,6 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
sk->sk_v6_daddr = usin->sin6_addr; sk->sk_v6_daddr = usin->sin6_addr;
np->flow_label = fl6.flowlabel; np->flow_label = fl6.flowlabel;
ip6_set_txhash(sk);
/* /*
* TCP over IPv4 * TCP over IPv4
*/ */
...@@ -297,6 +295,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, ...@@ -297,6 +295,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
if (err) if (err)
goto late_failure; goto late_failure;
ip6_set_txhash(sk);
if (!tp->write_seq && likely(!tp->repair)) if (!tp->write_seq && likely(!tp->repair))
tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32, tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32,
sk->sk_v6_daddr.s6_addr32, sk->sk_v6_daddr.s6_addr32,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment