net: refactor bind_bucket fastreuse into helper
authorTim Froidcoeur <tim.froidcoeur@tessares.net>
Tue, 11 Aug 2020 18:33:23 +0000 (20:33 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 11 Aug 2020 22:49:08 +0000 (15:49 -0700)
Refactor the fastreuse update code in inet_csk_get_port into a small
helper function that can be called from other places.

Acked-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Tim Froidcoeur <tim.froidcoeur@tessares.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/inet_connection_sock.h
net/ipv4/inet_connection_sock.c

index 1e209ce..aa8893c 100644 (file)
@@ -304,6 +304,10 @@ void inet_csk_listen_stop(struct sock *sk);
 
 void inet_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr);
 
+/* update the fast reuse flag when adding a socket */
+void inet_csk_update_fastreuse(struct inet_bind_bucket *tb,
+                              struct sock *sk);
+
 struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu);
 
 #define TCP_PINGPONG_THRESH    3
index d1a3913..b457dd2 100644 (file)
@@ -296,6 +296,57 @@ static inline int sk_reuseport_match(struct inet_bind_bucket *tb,
                                    ipv6_only_sock(sk), true, false);
 }
 
+void inet_csk_update_fastreuse(struct inet_bind_bucket *tb,
+                              struct sock *sk)
+{
+       kuid_t uid = sock_i_uid(sk);
+       bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN;
+
+       if (hlist_empty(&tb->owners)) {
+               tb->fastreuse = reuse;
+               if (sk->sk_reuseport) {
+                       tb->fastreuseport = FASTREUSEPORT_ANY;
+                       tb->fastuid = uid;
+                       tb->fast_rcv_saddr = sk->sk_rcv_saddr;
+                       tb->fast_ipv6_only = ipv6_only_sock(sk);
+                       tb->fast_sk_family = sk->sk_family;
+#if IS_ENABLED(CONFIG_IPV6)
+                       tb->fast_v6_rcv_saddr = sk->sk_v6_rcv_saddr;
+#endif
+               } else {
+                       tb->fastreuseport = 0;
+               }
+       } else {
+               if (!reuse)
+                       tb->fastreuse = 0;
+               if (sk->sk_reuseport) {
+                       /* We didn't match or we don't have fastreuseport set on
+                        * the tb, but we have sk_reuseport set on this socket
+                        * and we know that there are no bind conflicts with
+                        * this socket in this tb, so reset our tb's reuseport
+                        * settings so that any subsequent sockets that match
+                        * our current socket will be put on the fast path.
+                        *
+                        * If we reset we need to set FASTREUSEPORT_STRICT so we
+                        * do extra checking for all subsequent sk_reuseport
+                        * socks.
+                        */
+                       if (!sk_reuseport_match(tb, sk)) {
+                               tb->fastreuseport = FASTREUSEPORT_STRICT;
+                               tb->fastuid = uid;
+                               tb->fast_rcv_saddr = sk->sk_rcv_saddr;
+                               tb->fast_ipv6_only = ipv6_only_sock(sk);
+                               tb->fast_sk_family = sk->sk_family;
+#if IS_ENABLED(CONFIG_IPV6)
+                               tb->fast_v6_rcv_saddr = sk->sk_v6_rcv_saddr;
+#endif
+                       }
+               } else {
+                       tb->fastreuseport = 0;
+               }
+       }
+}
+
 /* Obtain a reference to a local port for the given sock,
  * if snum is zero it means select any available local port.
  * We try to allocate an odd port (and leave even ports for connect())
@@ -308,7 +359,6 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
        struct inet_bind_hashbucket *head;
        struct net *net = sock_net(sk);
        struct inet_bind_bucket *tb = NULL;
-       kuid_t uid = sock_i_uid(sk);
        int l3mdev;
 
        l3mdev = inet_sk_bound_l3mdev(sk);
@@ -345,49 +395,8 @@ tb_found:
                        goto fail_unlock;
        }
 success:
-       if (hlist_empty(&tb->owners)) {
-               tb->fastreuse = reuse;
-               if (sk->sk_reuseport) {
-                       tb->fastreuseport = FASTREUSEPORT_ANY;
-                       tb->fastuid = uid;
-                       tb->fast_rcv_saddr = sk->sk_rcv_saddr;
-                       tb->fast_ipv6_only = ipv6_only_sock(sk);
-                       tb->fast_sk_family = sk->sk_family;
-#if IS_ENABLED(CONFIG_IPV6)
-                       tb->fast_v6_rcv_saddr = sk->sk_v6_rcv_saddr;
-#endif
-               } else {
-                       tb->fastreuseport = 0;
-               }
-       } else {
-               if (!reuse)
-                       tb->fastreuse = 0;
-               if (sk->sk_reuseport) {
-                       /* We didn't match or we don't have fastreuseport set on
-                        * the tb, but we have sk_reuseport set on this socket
-                        * and we know that there are no bind conflicts with
-                        * this socket in this tb, so reset our tb's reuseport
-                        * settings so that any subsequent sockets that match
-                        * our current socket will be put on the fast path.
-                        *
-                        * If we reset we need to set FASTREUSEPORT_STRICT so we
-                        * do extra checking for all subsequent sk_reuseport
-                        * socks.
-                        */
-                       if (!sk_reuseport_match(tb, sk)) {
-                               tb->fastreuseport = FASTREUSEPORT_STRICT;
-                               tb->fastuid = uid;
-                               tb->fast_rcv_saddr = sk->sk_rcv_saddr;
-                               tb->fast_ipv6_only = ipv6_only_sock(sk);
-                               tb->fast_sk_family = sk->sk_family;
-#if IS_ENABLED(CONFIG_IPV6)
-                               tb->fast_v6_rcv_saddr = sk->sk_v6_rcv_saddr;
-#endif
-                       }
-               } else {
-                       tb->fastreuseport = 0;
-               }
-       }
+       inet_csk_update_fastreuse(tb, sk);
+
        if (!inet_csk(sk)->icsk_bind_hash)
                inet_bind_hash(sk, tb, port);
        WARN_ON(inet_csk(sk)->icsk_bind_hash != tb);