On Fri, 2016-12-09 at 19:47 -0800, Eric Dumazet wrote:

> 
> Hmm... Is your ephemeral port range includes the port your load
> balancing app is using ?

I suspect that you might have processes doing bind( port = 0) that are
trapped into the bind_conflict() scan ?

With 100,000 + timewaits there, this possibly hurts.

Can you try the following loop breaker ?

diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 
d5d3ead0a6c31e42e8843d30f8c643324a91b8e9..74f0f5ee6a02c624edb0263b9ddd27813f68d0a5
 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -51,7 +51,7 @@ int inet_csk_bind_conflict(const struct sock *sk,
        int reuse = sk->sk_reuse;
        int reuseport = sk->sk_reuseport;
        kuid_t uid = sock_i_uid((struct sock *)sk);
-
+       unsigned int max_count;
        /*
         * Unlike other sk lookup places we do not check
         * for sk_net here, since _all_ the socks listed
@@ -59,6 +59,7 @@ int inet_csk_bind_conflict(const struct sock *sk,
         * one this bucket belongs to.
         */
 
+       max_count = relax ? ~0U : 100;
        sk_for_each_bound(sk2, &tb->owners) {
                if (sk != sk2 &&
                    !inet_v6_ipv6only(sk2) &&
@@ -84,6 +85,8 @@ int inet_csk_bind_conflict(const struct sock *sk,
                                        break;
                        }
                }
+               if (--max_count == 0)
+                       return 1;
        }
        return sk2 != NULL;
 }
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 
1c86c478f578b49373e61a4c397f23f3dc7f3fc6..4f63d06e0d601da94eb3f2b35a988abd060e156c
 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -35,12 +35,14 @@ int inet6_csk_bind_conflict(const struct sock *sk,
        int reuse = sk->sk_reuse;
        int reuseport = sk->sk_reuseport;
        kuid_t uid = sock_i_uid((struct sock *)sk);
+       unsigned int max_count;
 
        /* We must walk the whole port owner list in this case. -DaveM */
        /*
         * See comment in inet_csk_bind_conflict about sock lookup
         * vs net namespaces issues.
         */
+       max_count = relax ? ~0U : 100;
        sk_for_each_bound(sk2, &tb->owners) {
                if (sk != sk2 &&
                    (!sk->sk_bound_dev_if ||
@@ -61,6 +63,8 @@ int inet6_csk_bind_conflict(const struct sock *sk,
                            ipv6_rcv_saddr_equal(sk, sk2, true))
                                break;
                }
+               if (--max_count == 0)
+                       return 1;
        }
 
        return sk2 != NULL;



Reply via email to