txhash: fix sk->sk_txrehash default
authorKevin Yang <yyd@google.com>
Tue, 7 Feb 2023 02:08:20 +0000 (02:08 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 8 Feb 2023 09:07:11 +0000 (09:07 +0000)
This code fix a bug that sk->sk_txrehash gets its default enable
value from sysctl_txrehash only when the socket is a TCP listener.

We should have sysctl_txrehash to set the default sk->sk_txrehash,
no matter TCP, nor listerner/connector.

Tested by following packetdrill:
  0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
  +0 socket(..., SOCK_DGRAM, IPPROTO_UDP) = 4
  // SO_TXREHASH == 74, default to sysctl_txrehash == 1
  +0 getsockopt(3, SOL_SOCKET, 74, [1], [4]) = 0
  +0 getsockopt(4, SOL_SOCKET, 74, [1], [4]) = 0

Fixes: 26859240e4ee ("txhash: Add socket option to control TX hash rethink behavior")
Signed-off-by: Kevin Yang <yyd@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/core/sock.c
net/ipv4/af_inet.c
net/ipv4/inet_connection_sock.c
net/ipv6/af_inet6.c

index f954d58..6f27c24 100644 (file)
@@ -1531,6 +1531,8 @@ set_sndbuf:
                        ret = -EINVAL;
                        break;
                }
+               if ((u8)val == SOCK_TXREHASH_DEFAULT)
+                       val = READ_ONCE(sock_net(sk)->core.sysctl_txrehash);
                /* Paired with READ_ONCE() in tcp_rtx_synack() */
                WRITE_ONCE(sk->sk_txrehash, (u8)val);
                break;
@@ -3451,7 +3453,6 @@ void sock_init_data(struct socket *sock, struct sock *sk)
        sk->sk_pacing_rate = ~0UL;
        WRITE_ONCE(sk->sk_pacing_shift, 10);
        sk->sk_incoming_cpu = -1;
-       sk->sk_txrehash = SOCK_TXREHASH_DEFAULT;
 
        sk_rx_queue_clear(sk);
        /*
index 6c0ec27..cf11f10 100644 (file)
@@ -347,6 +347,7 @@ lookup_protocol:
        sk->sk_destruct    = inet_sock_destruct;
        sk->sk_protocol    = protocol;
        sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
+       sk->sk_txrehash = READ_ONCE(net->core.sysctl_txrehash);
 
        inet->uc_ttl    = -1;
        inet->mc_loop   = 1;
index d1f8375..f2c43f6 100644 (file)
@@ -1225,9 +1225,6 @@ int inet_csk_listen_start(struct sock *sk)
        sk->sk_ack_backlog = 0;
        inet_csk_delack_init(sk);
 
-       if (sk->sk_txrehash == SOCK_TXREHASH_DEFAULT)
-               sk->sk_txrehash = READ_ONCE(sock_net(sk)->core.sysctl_txrehash);
-
        /* There is race window here: we announce ourselves listening,
         * but this transition is still not validated by get_port().
         * It is OK, because this socket enters to hash table only
index fee9163..8479347 100644 (file)
@@ -222,6 +222,7 @@ lookup_protocol:
        np->pmtudisc    = IPV6_PMTUDISC_WANT;
        np->repflow     = net->ipv6.sysctl.flowlabel_reflect & FLOWLABEL_REFLECT_ESTABLISHED;
        sk->sk_ipv6only = net->ipv6.sysctl.bindv6only;
+       sk->sk_txrehash = READ_ONCE(net->core.sysctl_txrehash);
 
        /* Init the ipv4 part of the socket since we can have sockets
         * using v6 API for ipv4.