Несколько вопросов, касающихся поведения tcp при перегруженности

Приведенный ниже журнал tcpdump скопирован из теста, который я недавно выполнял. В начале все прошло очень гладко. Затем клиентская сторона, наконец, перегружена маршрутизатором, и тогда большое количество пакетов [# - 6176] отбрасывается (никогда не смотрите ACK для них). Затем в 6177 повторная передача запускается из-за тайм-аута таймера.

Итак, вот вопросы:

  1. Когда произойдет повторная передача, что произойдет с окном перегрузки на стороне отправителя (snd_cwnd)? ОС является ядром Linux 3.4.42. Как сказано, snd_cwnd будет уменьшен до 1, когда будет повторная передача. Если это так, почему пакет 6179, 6180 все еще может быть отправлен?
  2. почему 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 обратитесь к:

TCP/IP Иллюстрированный

Другие вопросы по тегам