]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
tcp: Save address type in inet_bind2_bucket.
authorKuniyuki Iwashima <kuniyu@amazon.com>
Tue, 19 Dec 2023 00:18:25 +0000 (09:18 +0900)
committerDavid S. Miller <davem@davemloft.net>
Fri, 22 Dec 2023 22:15:34 +0000 (22:15 +0000)
inet_bind2_bucket_addr_match() and inet_bind2_bucket_match_addr_any()
are called for each bhash2 bucket to check conflicts.  Thus, we call
ipv6_addr_any() and ipv6_addr_v4mapped() over and over during bind().

Let's avoid calling them by saving the address type in inet_bind2_bucket.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/inet_hashtables.h
net/ipv4/inet_hashtables.c

index 171cc235d0451f7597b7fd5b6ce3215e4a8e681c..260e673ede2222be7fb713c33b6b11ee34eeab0b 100644 (file)
@@ -96,6 +96,7 @@ struct inet_bind2_bucket {
        int                     l3mdev;
        unsigned short          port;
 #if IS_ENABLED(CONFIG_IPV6)
+       unsigned short          addr_type;
        struct in6_addr         v6_rcv_saddr;
 #define rcv_saddr              v6_rcv_saddr.s6_addr32[3]
 #else
index 15594424e9f5afd05d49c21c5fd1d488961fa33e..4e39e3f905b43b9545fc38eba633345d162567d7 100644 (file)
@@ -110,10 +110,14 @@ static void inet_bind2_bucket_init(struct inet_bind2_bucket *tb,
        tb->l3mdev    = l3mdev;
        tb->port      = port;
 #if IS_ENABLED(CONFIG_IPV6)
-       if (sk->sk_family == AF_INET6)
+       BUILD_BUG_ON(USHRT_MAX < (IPV6_ADDR_ANY | IPV6_ADDR_MAPPED));
+       if (sk->sk_family == AF_INET6) {
+               tb->addr_type = ipv6_addr_type(&sk->sk_v6_rcv_saddr);
                tb->v6_rcv_saddr = sk->sk_v6_rcv_saddr;
-       else
+       } else {
+               tb->addr_type = IPV6_ADDR_MAPPED;
                ipv6_addr_set_v4mapped(sk->sk_rcv_saddr, &tb->v6_rcv_saddr);
+       }
 #else
        tb->rcv_saddr = sk->sk_rcv_saddr;
 #endif
@@ -153,7 +157,7 @@ static bool inet_bind2_bucket_addr_match(const struct inet_bind2_bucket *tb2,
        if (sk->sk_family == AF_INET6)
                return ipv6_addr_equal(&tb2->v6_rcv_saddr, &sk->sk_v6_rcv_saddr);
 
-       if (!ipv6_addr_v4mapped(&tb2->v6_rcv_saddr))
+       if (tb2->addr_type != IPV6_ADDR_MAPPED)
                return false;
 #endif
        return tb2->rcv_saddr == sk->sk_rcv_saddr;
@@ -830,21 +834,14 @@ bool inet_bind2_bucket_match_addr_any(const struct inet_bind2_bucket *tb, const
                return false;
 
 #if IS_ENABLED(CONFIG_IPV6)
-       if (sk->sk_family == AF_INET6) {
-               if (ipv6_addr_any(&tb->v6_rcv_saddr))
-                       return true;
-
-               if (!ipv6_addr_v4mapped(&tb->v6_rcv_saddr))
-                       return false;
-
-               return ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr) &&
-                       tb->rcv_saddr == 0;
-       }
-
-       if (ipv6_addr_any(&tb->v6_rcv_saddr))
+       if (tb->addr_type == IPV6_ADDR_ANY)
                return true;
 
-       if (!ipv6_addr_v4mapped(&tb->v6_rcv_saddr))
+       if (tb->addr_type != IPV6_ADDR_MAPPED)
+               return false;
+
+       if (sk->sk_family == AF_INET6 &&
+           !ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr))
                return false;
 #endif
        return tb->rcv_saddr == 0;