Включает ли число невыполненных запросов прослушивания количество полученных SYN-соединений в случае TCP в Linux? - PullRequest
7 голосов
/ 01 октября 2019

Я прочитал несколько постов и проверил код ядра Linux, например inet_listen() -> inet_csk_listen_start(), и кажется, что backlog аргумент listen() системного вызова влияет только на принятую очередь , но не в очереди получения SYN:

sk->sk_max_ack_backlog = backlog;

То есть символически accept-queue + syn-received-queue != backlog. Я не могу понять, что происходит. В этой статье говорится:

Максимально допустимая длина очередей Accept и SYN берется из параметра backlog, передаваемого в системный вызов listen (2) приложением.

Но на странице MAN нет ничего похожего .

Также в случае Linux: backlog подсказка, как упомянуто здесь илиэто действительно ограничивает очереди?

1 Ответ

4 голосов
/ 01 октября 2019

В случае ядра 4.3 вы указали что-то вроде:

tcp_v4_do_rcv() -> tcp_rcv_state_process() -> tcp_v4_conn_request() -> tcp_conn_request() -> inet_csk_reqsk_queue_is_full()

Здесь мы можем увидеть самые важные детали об очередях:

/* TW buckets are converted to open requests without
 * limitations, they conserve resources and peer is
 * evidently real one.
 */
if ((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;
}

/* Accept backlog is full. If we have already queued enough
 * of warm entries in syn queue, drop request. It is better than
 * clogging syn queue with openreqs with exponentially increasing
 * timeout.
 */
if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) {
    NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
    goto drop;
}

Обратите внимание на inet_csk_reqsk_queue_is_full():

static inline int inet_csk_reqsk_queue_is_full(const struct sock *sk)
{
    return inet_csk_reqsk_queue_len(sk) >= sk->sk_max_ack_backlog;
}

Наконец, он сравнивает текущую очередь icsk_accept_queueс размером sk_max_ack_backlog, который был ранее установлен inet_csk_listen_start(). Да, backlog влияет на входящую очередь в текущем случае.

Вы можете видеть, что и sk_acceptq_is_full(), и inet_csk_reqsk_queue_is_full() сравнивают один и тот же сокет sk_max_ack_backlog, который устанавливается черезlisten():

static inline bool sk_acceptq_is_full(const struct sock *sk)
{
    return sk->sk_ack_backlog > sk->sk_max_ack_backlog;
}

Полезные ссылки: 1 , 2

...