Несколько вопросов, касающихся поведения tcp при перегруженности
Приведенный ниже журнал tcpdump скопирован из теста, который я недавно выполнял. В начале все прошло очень гладко. Затем клиентская сторона, наконец, перегружена маршрутизатором, и тогда большое количество пакетов [# - 6176] отбрасывается (никогда не смотрите ACK для них). Затем в 6177 повторная передача запускается из-за тайм-аута таймера.
Итак, вот вопросы:
- Когда произойдет повторная передача, что произойдет с окном перегрузки на стороне отправителя (snd_cwnd)? ОС является ядром Linux 3.4.42. Как сказано, snd_cwnd будет уменьшен до 1, когда будет повторная передача. Если это так, почему пакет 6179, 6180 все еще может быть отправлен?
- почему 6179, 6180 не получил ACKed? Вместо этого 6178 может получить ACKed, значит пакеты могут пройти.
6174 2.881075 10.203.85.190 207.198.102.53 TCP 1426 58206 > 80 [ACK] Seq=6379071 Ack=1 Win=13824 Len=1358 TSval=4294945643 TSecr=2532115493
6175 2.881094 10.203.85.190 207.198.102.53 TCP 1426 58206 > 80 [ACK] Seq=6380429 Ack=1 Win=13824 Len=1358 TSval=4294945643 TSecr=2532115493
6176 2.881114 10.203.85.190 207.198.102.53 TCP 1426 58206 > 80 [ACK] Seq=6381787 Ack=1 Win=13824 Len=1358 TSval=4294945643 TSecr=2532115493
6177 3.227347 10.203.85.190 207.198.102.53 TCP 1426 [TCP Retransmission] 58206 > 80 [ACK] Seq=5887475 Ack=1 Win=13824 Len=1358 TSval=4294945685 TSecr=2532115493
6178 3.323055 207.198.102.53 10.203.85.190 TCP 68 http > 58206 [ACK] Seq=1 Ack=5888833 Win=980480 Len=0 TSval=2532115623 TSecr=4294945685
6179 3.326368 10.203.85.190 207.198.102.53 TCP 1426 58206 > 80 [ACK] Seq=6383145 Ack=1 Win=13824 Len=1358 TSval=4294945694 TSecr=2532115623
6180 3.326454 10.203.85.190 207.198.102.53 TCP 1426 58206 > 80 [ACK] Seq=6384503 Ack=1 Win=13824 Len=1358 TSval=4294945694 TSecr=2532115623
6181 3.727429 10.203.85.190 207.198.102.53 TCP 1426 [TCP Retransmission] 58206 > 80 [ACK] Seq=5888833 Ack=1 Win=13824 Len=1358 TSval=4294945735 TSecr=2532115623
6182 3.813101 207.198.102.53 10.203.85.190 TCP 68 80 > 58206 [ACK] Seq=1 Ack=5890191 Win=980480 Len=0 TSval=2532115746 TSecr=4294945735
6183 3.813606 10.203.85.190 207.198.102.53 TCP 1426 58206 > 80 [ACK] Seq=6385861 Ack=1 Win=13824 Len=1358 TSval=4294945743 TSecr=2532115746
6184 3.813822 10.203.85.190 207.198.102.53 TCP 1426 58206 > 80 [ACK] Seq=6387219 Ack=1 Win=13824 Len=1358 TSval=4294945743 TSecr=2532115746
6185 4.197341 10.203.85.190 207.198.102.53 TCP 1426 [TCP Retransmission] 58206 > 80 [ACK] Seq=5890191 Ack=1 Win=13824 Len=1358 TSval=4294945782 TSecr=2532115746
6186 4.294162 207.198.102.53 10.203.85.190 TCP 68 80 > 58206 [ACK] Seq=1 Ack=5891549 Win=980480 Len=0 TSval=2532115866 TSecr=4294945782
6187 4.297450 10.203.85.190 207.198.102.53 TCP 1426 58206 > 80 [ACK] Seq=6388577 Ack=1 Win=13824 Len=1358 TSval=4294945792 TSecr=2532115866
6188 4.297675 10.203.85.190 207.198.102.53 TCP 1426 58206 > 80 [ACK] Seq=6389935 Ack=1 Win=13824 Len=1358 TSval=4294945792 TSecr=2532115866
2 ответа
Это связано с F-RTO, см. RFC 5682.
В традиционном алгоритме (не F-RTO) это делается следующим образом:
Когда происходит таймаут повторной передачи, отправитель TCP входит в восстановление RTO, где окно перегрузки инициализируется для одного сегмента, а неподтвержденные сегменты повторно передаются с использованием алгоритма медленного запуска.
Вот как работает F-RTO:
Когда таймер повторной передачи истекает, отправитель F-RTO повторно передает первый неподтвержденный сегмент как обычно. Отклоняясь от обычной операции после тайм-аута, он затем пытается передать новые, ранее неотправленные данные (обычно два сегмента, если имеется достаточно данных, и окно перегрузки позволяет) для первого подтверждения, которое приходит после тайм-аута, учитывая, что подтверждение опережает окно.
Это объясняет, почему отправляются 6179 и 6180. Почему ACK для них не получен, я считаю, что это ошибка системного уровня, которую необходимо устранить.
Когда вы отправляете TCP-пакет, будет создан таймер повторной передачи (для каждого пакета); если ACK не появляется после истечения времени таймера, пакет будет передан повторно. Эта процедура будет выполняться несколько раз (в зависимости от операционной системы и настраивается), и, если все попытки будут неудачными, соединение не будет установлено. Для получения дополнительной информации о реализации TCP/IP в Linux я настоятельно рекомендую вам обратиться к:
Понимание внутренних сетей Linux
Для получения дополнительной информации о TCP обратитесь к: