Реализация ядра TCP / IP - о длине очереди приема - PullRequest
1 голос
/ 17 апреля 2019

Недавно я изучал реализацию TCP / IP в ядре linux (версия 4.4), и был очень озадачен очередью принятия.Я знаю, что в struct inet_connection_sock есть очередь, которая называется очередь приема :

struct inet_connection_sock {
    ...
    /* @icsk_accept_queue:     FIFO of established children */
    struct request_sock_queue icsk_accept_queue;
    ...
}

, и в ней есть член qlen, я думаю, она используется для указаниядлина очереди.

struct request_sock_queue {
    ...
    /* length of the queue? */
    atomic_t        qlen;
    ...
};

Вот что, я думаю, я знаю: когда сокет LISTEN получает пакет SYN, в функции tcp_conn_request, inet_csk_reqsk_queue_hash_add вызываетсяпоместите вновь созданный носок NEW_SYN_RECV в таблицу ehash (не icsk_accept_queue)

void inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req,
                   unsigned long timeout)
{
    reqsk_queue_hash_req(req, timeout);  // add to ehash table
    inet_csk_reqsk_queue_added(sk);      // increment icsk_accept_queue.qlen
}

Но в этой функции inet_csk_reqsk_queue_added вызывается с шагом icsk_accept_queue.qlen.Мой вопрос, почему увеличение qlen, так как ничего не вставлено в icsk_accept_queue?Разве это не длина icsk_accept_queue?

Кроме того, tcp_conn_request называется inet_csk_reqsk_queue_add, чтобы добавить быстро открытый носок (если он включен) в icsk_accept_queue:

struct sock *inet_csk_reqsk_queue_add(struct sock *sk,
                      struct request_sock *req,
                      struct sock *child)
{
    struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue;

    spin_lock(&queue->rskq_lock);
    if (unlikely(sk->sk_state != TCP_LISTEN)) {
        inet_child_forget(sk, req, child);
        child = NULL;
    } else {
        req->sk = child;
        req->dl_next = NULL;
        if (queue->rskq_accept_head == NULL)
            queue->rskq_accept_head = req;
        else
            queue->rskq_accept_tail->dl_next = req;
        queue->rskq_accept_tail = req;
        sk_acceptq_added(sk);    // increment sk.sk_ack_backlog
    }
    spin_unlock(&queue->rskq_lock);
    return child;
}

Но эта функция в итоге увеличила sk.sk_ack_backlog (вызывая sk_acceptq_added) вместо icsk_accept_queue.qlen.Почему нет?

...