А на днях, анализируя сетевые метрики одной машины, обнаружил, что мое представление о счетчиках
TCP*ZeroWindowAdv оказалось неверным.Сегодня будем исправляться.
⚙️ Итак, TCP перед отправкой сегмента добавляет заголовок, в котором рассчитывается размер окна.
Напомню, размер окна определяет, сколько данных можно отправить получателю без подтверждения — так называемые in-flight данные, "в полете" то есть.
tcp_select_window(sk) — функция ядра, которая определяет размер окна и отвечает за увеличение счетчиков
TCP*ZeroWindowAdv:static u16 tcp_select_window(struct sock *sk)
{
...
u32 old_win = tp->rcv_wnd;
u32 cur_win = tcp_receive_window(tp);
u32 new_win = __tcp_select_window(sk);
if (new_win < cur_win) {
...
if (new_win == 0)
NET_INC_STATS(sock_net(sk),
LINUX_MIB_TCPWANTZEROWINDOWADV);
new_win = ALIGN(cur_win, 1 << tp->rx_opt.rcv_wscale);
}
...
/* If we advertise zero window, disable fast path. */
if (new_win == 0) {
if (old_win)
NET_INC_STATS(sock_net(sk),
LINUX_MIB_TCPTOZEROWINDOWADV);
} else if (old_win == 0) {
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPFROMZEROWINDOWADV);
}
...
}
Видно, что:
1. Рост
TCP*ZeroWindowAdv зависят только от состояния локального буфера приёма, то есть от того, сколько в нём свободного места.❌Ранее я ошибочно полагал, что TCPToZeroWindowAdv растёт, если мы получаем уведомление о Zero Window от удаленной стороны, но это не так.
2. Рост
TCPWantZeroWindowAdv возможен без увеличения TCPToZeroWindowAdv, так как последний требует дополнительной проверки размера окна через выравнивание (ALIGN)📍 Переформулируем, что это за показатели и для чего они нужны.
●
TCPWantZeroWindowAdv увеличивается, когда локальная сторона не успевает вычитывать данные, и размер окна стремится к нулю. Однако Zero Window не обязательно будет направлен удалённой стороне. То есть сетевой стек планирует (Want) объявить Zero Window;
●
TCPToZeroWindowAdv увеличивается, если после пересчёта размер окна остаётся нулевым, и тогда флаг добавляется в заголовок, что приводит к приостановке передачи данных. И это скверная ситуация.То есть мы "идем" в нулевое окно - ToZero.
●
TCPFromZeroWindowAdv увеличивается, если окно ранее было равно нулю (old_win == 0), но теперь его размер стал больше, что позволяет возобновить передачу данных.FromZero звучит как "уходим от нулевого окна". Ну или мне так проще запомнить)
_________________________________________________________________
Все таки прав был Мюллер: "Верить в наше время нельзя никому. Исходникам можно."