• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Некорректная отработка TCP Retransmission

Клон WeMos D1 mini, среди прочего отрабатывает код простого http сервера на ESP8266WebServer.

К нему обращается питоновский код с другого компа на линуксе, запросом GET.

Такое впечатление что на TCP пакет с запросом модуль не успевает ответить за время TCP_RTO_MIN (200 ms), и линукс шлет retransmission пакет.
Проблема в том, что модуль хоть и ACK оба пакета с запросом быстренько, но потом как-бы подвисает на 5секунд, и основной контент возвращает уже с задержкой.
При этом если тот же GET запрос делать через curl, который не вызывает retransmission (почему не знаю) то ответ модуля всегда приходит быстро, без задержек.
5 секунд это, насколько я понимаю, какой-то таймаут у TCP стека ESP8266.
Мне кажется что получение retransmission пакета запроса вводит TCP стек ESP8266 в ступор.

Нет ли у кого-то понимания, что там происходит и как бороться?
Прикладываю скриншот wiresharkesp8266-tcp-retr-issue.png

PS Какая там прошивка не знаю и как посмотреть не знаю. Программирую D1 mini через Ардуино ИДЕ.
 

pvvx

Активный участник сообщества
У вас вообще полная белиберда от ESP - на закрытие соединения он дает RST :) :)
Такое впечатление что на TCP пакет с запросом модуль не успевает ответить за время TCP_RTO_MIN (200 ms), и линукс шлет retransmission пакет.
Проблема в том, что модуль хоть и ACK оба пакета с запросом быстренько, но потом как-бы подвисает на 5секунд, и основной контент возвращает уже с задержкой.
При этом если тот же GET запрос делать через curl, который не вызывает retransmission (почему не знаю) то ответ модуля всегда приходит быстро, без задержек.
5 секунд это, насколько я понимаю, какой-то таймаут у TCP стека ESP8266.
Мне кажется что получение retransmission пакета запроса вводит TCP стек ESP8266 в ступор.
Не в ступор, а хуже.
Есть вариант, что ESP согласует соединение на одни и тот-же порты, а у компа или сервера или в сети это вызывает беду, т.к. когда правильный клиент, согласно RFC первым закрыл соединение, то оно у него сидит в состоянии TIME_WAIT в течении 120 сек (и по всей трассе аналогично). A ESP лепит опять по тем-же портам, т.к. проснулся и счетчик, замещающий рандом :), считает "свободный" порт с начала списка...
Это и остальное вы никогда не вылечите у ESP, т.к. для этого надо добавить от 200+ килобайт памяти и скорости CPU, даже на ваших вялых соединениях.
Для уточнения нужна вся история запросов. Иначе - гадание на .....
 

pvvx

Активный участник сообщества
Ущё - как в пакет с MSS 536 байт влезет заголовок?
Chrome офигеет. IE кидает запросы на канал для уточнения MSS и адаптирует заголовок HTTP под полученные данные. Но ESP не имеет такого сервиса :)
Даже если всё правильно описали в части socket и принимают полный WIN, но он у вас 2144 байта :) В него не лезет заголовок HTTP от современного браузера... А дальше козявки Arduino с разбором заголовка в буфере по дцать байт :)
Ранее, года 3 ещё назад с этим глючили большинство *nix, но им на это стали сильно указывать лет 5 назад и постепенно, частично, исправили и даже публиковали таблички у кого какой размер заголовка отрабатывает без багов :) Но забыли проверить побайтовую передачу... :) А уж в Arduino... :) Но ныне опять наплодились Ардуинщики, да напихали своей фигни, т.к. RFC они никогда не читали, и нужно снова исправлять... Во всяком случае у 90% *nix снова нарушен базовый rfc793, а уж у более мелких писателей - там вообще не знают что есть rкакие-то RFC...
Вечный круговорот - поправят, приходят новые и снова...
 

pvvx

Активный участник сообщества
И третье гадание – Espressif вставили в Lwip увеличение периода таймера опроса состояния буферов и соединений. Не на много – в тысячи раз от рекомендованного :) Это включается во всех “энерго-понижалках” для увеличения глюков и у LwIP и системы возникают запоры, до reboot по WDT и типа. Вместо рекомендованных 25 ms там увеличивают ход таймера до нескольких секунд, по которым в Lwip вызываются процедуры разборки с текущими буферами и состояниями pcb…

Отключите эту “энерго-понижалку – глюко-повышалку”.
 
Много интересных мыслей, спасибо. Надо обдумать.
C TIME_WAIT да, проблемка может выйти забористая.

Насчет заголовка не влезающего в MSS, запросы делаются между двумя автоматическими системами, без браузера. Заголовки всегда маленькие, весь пакет запроса 189 байт, заголовок ответа 147 байт.

>>
GET /get/status HTTP/1.1
Accept-Encoding: identity
Host: X.X.X.106:9980
User-Agent: Python-urllib/3.6
Connection: close
<<
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 212
Connection: close

HTTP в качестве протокола обмена был выбран в связи с легкостью отладки. Но уже возникают сомнения, ESP8266WebServer не шибко удобен/надёжен.

Не подскажите, как мне узнать текущую прошивку модуля?
Стоит ли попробовать перешить на последнюю? Я сунулся было по описанию, а там виндус требуется для утилиты xtcom_util.

И третье гадание – Espressif вставили в Lwip увеличение периода таймера опроса состояния буферов и соединений. Не на много – в тысячи раз от рекомендованного :) Это включается во всех “энерго-понижалках” для увеличения глюков и у LwIP и системы возникают запоры, до reboot по WDT и типа. Вместо рекомендованных 25 ms там увеличивают ход таймера до нескольких секунд, по которым в Lwip вызываются процедуры разборки с текущими буферами и состояниями pcb…

Отключите эту “энерго-понижалку – глюко-повышалку”.
 

pvvx

Активный участник сообщества
Режим MODEM для WiFi обычно включен по умолчанию.

Все интеллектуальные “зеленые” режимы работают по анализу кол-ва пакетов за время. У вас всего один запрос на период beacon (102.4 ms по умолчанию), что говорит о том, что режим энергосбережения будет включен. А если он включился, и тем более LIGH_SLEEP, то CPU будет отключен на периоды между beacon, как и любые прерывания…
 

pvvx

Активный участник сообщества
Но это ещё ладно (всякие MODEM/LIGHT_SLEEP), а главное то, что когда автомат будет отключать режим понижения потребления и всякие DTIM( n ) он не будет восстанавливать период отработки таймера для Lwip (стека обработки TCP/IP и т.д.).
 

pvvx

Активный участник сообщества
Такое впечатление что на TCP пакет с запросом модуль не успевает ответить за время TCP_RTO_MIN (200 ms), и линукс шлет retransmission пакет.
В честь чего он шлет retransmission ?
Пауза по ping в сетях IP определена как раз как 2*60 сек (2msl timeout) (и не случайно равна TIME_WAIT).
Таймер 2MSL заставляет клиента ждать в течение времени, достаточного для потери ACK (один MSL)

Скорее всего retransmission возник от непонимания что происходит со стеком TCP. А какие причины - по краткому логу в картинке сказать сложно
 

pvvx

Активный участник сообщества
Из сего вытекает, что не получен ACK по предыдущим пакетам в WIN в течение TCP_RTO_MIN. А отсылка ACK производится не самим сокетом, а драйвером TCP стека – в даyном случае LwIP.
Но при опции WiFi Sleep “MODEM” или “LIGH_SLEEP” обращение к LwIP, т.е. передача ему управления для счета всяких задержек происходит с периодом гораздо большим чем TCP_RTO_MIN.
Espressif считает что ESP не обязан быть совместимым с Linux и прочими нормам сетей IP. Для ESP требуется своя сеть и серверы.
 

pvvx

Активный участник сообщества
Не подскажите, как мне узнать текущую прошивку модуля?
Стоит ли попробовать перешить на последнюю? Я сунулся было по описанию, а там виндус требуется для утилиты xtcom_util.
Узнавать версию не имеет никакого смысла. Если в другой версии что-то изменено, что прокатит в этой ситуации, то остальное всё равно не совместимо с IP и тем более TCP. Т.е. всё равно будут глюки и бардак в сети от ESP, т.к. у ESP не хватает ресурсов для выполнения базовых RFC в части IPv4 и тем более TCP.
ESP32/8266 - это игрушка для ознакомления с основами WiFi. На большее она не рассчитана.
 

pvvx

Активный участник сообщества
Ещё интересная ситуация с TCP_RTO_MIN для WiFi (забудем о ESP).

Если оно равно 200 ms, то у WiFi период beacon по умолчанию 102.4 ms. Большинство “зеленых” алгоритмов работает по кол-ву пакетов. Например если за время периода паузы beacon проходит 1 или 2 пакета, то происходит переход к DTIM( n ), где n обычно от 2-х. А это от 204.8 ms. И за это время + согласование с AP выхода из этого режима никаких пакетов не передается. AP должна буферизировать проступившие запросы (что в реальности не всегда на дешевых роутерах – просто отбросит и оставит последний)… Т.е. в сети будут обязательные retransmission у неверно настроенного клиента с TCP_RTO_MIN в 200 ms со всеми WiFi устройствами. Лишний засор сети :)
 

pvvx

Активный участник сообщества
С UDP-шниками тут вообще смех и грех.
 
Сверху Снизу