Subject: Re: Compare length of req sock queue with sk_max_ack_backlog

From: Eric Dumazet <[email-masked]>
Date: Thu, 01 Feb 2018 20:19:26 -0800

On Fri, 2018-02-02 at 09:55 +0800, Tonghao Zhang wrote:
> On Thu, Feb 1, 2018 at 10:00 PM, Eric Dumazet <[email-masked]> wrote:
> > On Thu, 2018-02-01 at 20:34 +0800, Tonghao Zhang wrote:
> > > Hi Eric
> > > One question for you, In the patch ef547f2ac16 ("tcp: remove
> > > max_qlen_log"),  why we compared the length of req sock queue with
> > > sk_max_ack_backlog. If we remove the max_qlen_log, we should check the
> > > length of req sock queue with tcp_max_syn_backlog, right ?
> > > 
> > > With this patch, the option "/proc/sys/net/ipv4/tcp_max_syn_backlog"
> > > will be unsed anymore, right ?
> > 
> > Not right.
> > 
> > Please "git grep -n sysctl_max_syn_backlog" to convince it is still
> > used.
> > 
> 
> In the tcp_conn_request(), we call the  inet_csk_reqsk_queue_is_full()
> to check the length of req sock queue. But
> inet_csk_reqsk_queue_is_full()
> compares it with sk_max_ack_backlog.
> 
> inet_csk_reqsk_queue_is_full
>          inet_csk_reqsk_queue_len(sk) >= sk->sk_max_ack_backlog;
> 
> 
> inet_csk_reqsk_queue_len
>          reqsk_queue_len(&inet_csk(sk)->icsk_accept_queue);
> 
> If we set sysctl_max_syn_backlog to 1024 via
> /proc/sys/net/ipv4/tcp_max_syn_backlog, and
> backlog(sk_max_ack_backlog) to 128 via listen() , tcp_conn_request
> will drop the packets when
> length of req sock queue > 128, but not 1024.
> 
> tcp_conn_request
>         if ((net->ipv4.sysctl_tcp_syncookies == 2 ||
>              inet_csk_reqsk_queue_is_full(sk)) && !isn) {
>                 want_cookie = tcp_syn_flood_action(sk, skb, rsk_ops->slab_name);
>                 if (!want_cookie)
>                         goto drop;  // drop the packets
>         }

It seems to work as intended and documented in the changelog.

A socket listen backlog is determined at the time listen() system call
is issued, using the standard somaxconn as safe guard, for all socket
types.

We want to get rid of tcp_max_syn_backlog eventually, since TCP
listeners can use listen(fd, 10000000) these days if they want,
it is a matter of provisioning the needed memory.

Old mechanism was not allowing a listener to reduce or increase its
backlog dynamically (listener was using a private hash table, sized at
the time of first listen() and not resized later)

Having a global sysctl to magically change behavior on all TCP
listeners is not very practical, unless you had dedicated hosts to deal
with one service.