inet: implement lockless IP_MINTTL
authorEric Dumazet <edumazet@google.com>
Wed, 16 Aug 2023 08:15:47 +0000 (08:15 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 16 Aug 2023 10:09:18 +0000 (11:09 +0100)
inet->min_ttl is already read with READ_ONCE().

Implementing IP_MINTTL socket option set/read
without holding the socket lock is easy.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Soheil Hassas Yeganeh <soheil@google.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/ip_sockglue.c

index dbb2d23..61b2e7b 100644 (file)
@@ -1030,6 +1030,17 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
                        return -EINVAL;
                WRITE_ONCE(inet->uc_ttl, val);
                return 0;
+       case IP_MINTTL:
+               if (optlen < 1)
+                       return -EINVAL;
+               if (val < 0 || val > 255)
+                       return -EINVAL;
+
+               if (val)
+                       static_branch_enable(&ip4_min_ttl);
+
+               WRITE_ONCE(inet->min_ttl, val);
+               return 0;
        }
 
        err = 0;
@@ -1326,21 +1337,6 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
                err = xfrm_user_policy(sk, optname, optval, optlen);
                break;
 
-       case IP_MINTTL:
-               if (optlen < 1)
-                       goto e_inval;
-               if (val < 0 || val > 255)
-                       goto e_inval;
-
-               if (val)
-                       static_branch_enable(&ip4_min_ttl);
-
-               /* tcp_v4_err() and tcp_v4_rcv() might read min_ttl
-                * while we are changint it.
-                */
-               WRITE_ONCE(inet->min_ttl, val);
-               break;
-
        case IP_LOCAL_PORT_RANGE:
        {
                const __u16 lo = val;
@@ -1595,6 +1591,9 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
                if (val < 0)
                        val = READ_ONCE(sock_net(sk)->ipv4.sysctl_ip_default_ttl);
                goto copyval;
+       case IP_MINTTL:
+               val = READ_ONCE(inet->min_ttl);
+               goto copyval;
        }
 
        if (needs_rtnl)
@@ -1731,9 +1730,6 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
                len -= msg.msg_controllen;
                return copy_to_sockptr(optlen, &len, sizeof(int));
        }
-       case IP_MINTTL:
-               val = inet->min_ttl;
-               break;
        case IP_LOCAL_PORT_RANGE:
                val = inet->local_port_range.hi << 16 | inet->local_port_range.lo;
                break;