Я пытаюсь устранить неполадки в моем домашнем интернет-соединении, которое часто зависает при больших загрузках. Я считаю, что смог дублировать проблему между моим домашним компьютером и экземпляром Amazon EC2 с захватом пакетов на обоих концах. Вот то же поведение, которое я наблюдал на двух отдельных зависаниях:

  • Я начинаю TCP-загрузку файла размером 20 МБ на свой домашний компьютер с сервера EC2 (домашний компьютер - клиент TCP, сервер EC2 - сервер TCP).
  • Исходный TCP SYN имеет опцию MSS 1418 байт. Никакие другие сегменты от клиента не имеют опции MSS (SYN /ACK от сервера имеет опцию MSS 1460).
  • Когда начинается большая часть передачи, пакеты с сервера составляют 2878 байтов. Эти пакеты принимаются на клиенте в виде двух 1472-байтовых пакетов (я назову их передней и задней половиной), каждый из которых содержит сегмент TCP с половиной данных.
  • В какой-то момент передняя половина пакета с сервера теряется. Клиент начинает повторять ACK с опцией SACK.
  • После получения первого ACK с опцией SACK сервер начинает отправку 1472-байтовых пакетов (вместо 2878-байтовых пакетов).
  • После нескольких дублированных ACK сервер выполняет быструю повторную передачу, повторно отправляя 1472-байтовый пакет, то есть не 2878-байтовый пакет, который он первоначально отправил. Этот повторно отправленный пакет не отображается на клиенте.
  • По истечении времени ожидания сервер пытается выполнить повторную передачу еще несколько раз, снова отправляя пакет размером 1472 байта. Ни один из этих повторно отправленных пакетов не появляется на клиенте.

У меня есть несколько вопросов. Прежде всего, почему сервер отправляет 2878-байтовые пакеты для начала? Разве он не должен учитывать опцию MSS в пакете SYN?

Во-вторых, где эти 2878 байтовых сегментов разделены на два 1472 байтовых сегмента?

В-третьих, где и почему отбрасываются все ретранслируемые пакеты?

В-четвертых, можно ли как-то предотвратить это со стороны клиента?

Интересно, что оказывается, что соединение может быть восстановлено, если потеряна половина пакета. Моя (возможно, фиктивная) теория состоит в том, что что-то на маршруте съедает ретранслируемые передние полупакеты, потому что они не соответствуют их первоначальному размеру. Кроме того, та же передача, проходящая через UDP (с OpenVPN), не зависает (я знаю, что это означает, что я мог бы проксировать весь свой трафик таким образом, но это не тот ответ, который я ищу).

Вот захват пакетов для дома и сервера.

Продолжение: @DavidSchwartz предлагает в комментариях, что TSO может объяснить аномалии размера сегмента, и похоже, что это правильно. Отключение TSO на сервере ограничивает размер сегмента 1472 байта. К сожалению, передача по-прежнему зависает, поскольку повторно переданные пакеты не принимаются.

Я также попытался отключить параметры TCP SACK, отметки времени и масштабирование окна, а также уменьшить размер окна до 8192 байт. Передача все еще висит. Клиент получает пакеты, отправленные до и после повторно переданных пакетов, но не сами повторно переданные пакеты.

1 ответ1

1

Я знаю, что это очень старый пост, но пока оба ответа не касались отключения опций. Отключив масштабирование окон и SACK, вы значительно улучшили TCP. Это само по себе вызовет проблемы пропускной способности. Тем не менее, вы упомянули, что после истечения времени ожидания сервер повторно передает еще несколько раз. Это проблема. RTO начал экспоненциальную откат. Это означает, что другой конец соединения полностью недоступен в течение длительного периода времени. Эта проблема является серьезной, а не проблемой TCP, потому что TCP делает то, для чего он предназначен. Но, скорее всего, проблема с аппаратным обеспечением сетевого устройства, такого как маршрутизатор.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .