TCP

Допустим работа нашего http сервера начала налаживаться : мы принимаем udp , arp пакеты нормально. Выделяем память через pbuf_alloc и очищаем через pbuf_free.

Мы ведем статистику по регионам памяти и все вроде нормально. Но вот приходит первый tcp запрос к нашему http серверу и начинают работать регионы памяти TCP_PCB , TCP_PCB_LISTEN , TCP_SEG.

Резервирование памяти для работы tcp происходит здесь в файле memp_std.h , это проиходит еще на этапе компиляции:

LWIP_MEMPOOL(TCP_PCB,        MEMP_NUM_TCP_PCB,         sizeof(struct tcp_pcb),        "TCP_PCB")
LWIP_MEMPOOL(TCP_PCB_LISTEN, MEMP_NUM_TCP_PCB_LISTEN,  sizeof(struct tcp_pcb_listen), "TCP_PCB_LISTEN")
LWIP_MEMPOOL(TCP_SEG,        MEMP_NUM_TCP_SEG,         sizeof(struct tcp_seg),        "TCP_SEG")

Так как мы слушает только один TCP порт (80) , то размер региона [TCP_PCB_LISTEN ] можно сделать равным одному блоку памяти.

Так как соединение с нашим сервером будет только от одного клиента можно смело сделать регион [TCP_PCB] на один блок памяти.

По-поводу региона [TCP_SEG] , точно сказать сколько надо резервировать заранее сложно. Мы учитываем , что MSS 1460 TCP_WND 1460*2=2920 TCP_SND_BUF =2*MSS .

Тогда вроде получается , что при приеме данных может быть только один сегмент out-of-sequence(ooseq) (он попадает в [TCP_SEG]).

Количество unacked сегментов , то есть посланных сегментов и не подтвержденных другой стороной это может быть один пакет (SYN) .
После установки соединения unacked сегментов могут быть два , так как мы посылаем с размером окна равным 2 сегмента (2*1460=2920).
Дело в том ,что unacked тоже хранятся в [TCP_SEG] до подтверждения другой стороной.

unsent (не посланные) сегменты почему-то у нас по нулям.

В коде есть защита (на уровне компиляции) и нам рекомендуют MEMP_NUM_TCP_SEG минимум 8.

Для [PBUF_POOL] надо аналогично установить не меньше 8, так как [TCP_SEG] это ссылки , а содержание пакетов хранится в [PBUF_POOL] для принимаемых и в [MALLOC_256] , [MALLOC_512] ,.. для отправляемых сегментов.


И это уже не простой ответ на запрос udp, arp. Тут устанавливается соединение , в котором может быть неограниченное количество запросов / ответов на одно соединение. Да и соединение надо не забывать закрывать корректно.

В файле tcp.c есть функции с отладочной информацией (tcp_debug_print_pcbs), их можно задействовать .

tcp_tmr

Удивляемся , но у нас не вызывается функция tcp_tmr .Читаем " Called periodically to dispatch TCP timers , every 250 ms".

Функция tcp_tmr должна запускаться примерно через 250мс . Её назначение отслеживать состояние соединений tcp. Во-время соединения закрывать в том числе.

Лучше ее реализовать так : из прерывания таймера 1раз в 250мс выставляем флаг, что надо отработать tcp_tmr . Далее в основном потоке , где обрабатываем поступающие данные из ethernet канала по установленному флагу вызываем tcp_tmr. Получается примерно периодически 1/250мс , но точность здесь не нужна.

Регион памяти [TCP_PCB] предназначен для хранения информации о соединениях TCP.

Состояния TCP соединения

"CLOSED",
"LISTEN",
"SYN_SENT",
"SYN_RCVD",
"ESTABLISHED",
"FIN_WAIT_1",
"FIN_WAIT_2",
"CLOSE_WAIT",
"CLOSING",
"LAST_ACK",
"TIME_WAIT"

Пока соединение TCP не закрыто в регионе [TCP_PCB] должен висеть блок , выделенный под соединение через pbuf_alloc . Но браузер возможно не захочет его закрывать очень долго (см. заголовок Connection : keep_alive ) . Но нам не выгодно долго хранить соединение, а даже наоборот лучше сразу закрывать для экономии памяти.

В момент сразу после ответа на запрос ресурса с нашей http станицы мы получим примерно такой расход памяти :

avail: 04 used: 00 max: 00 err: 00  [RAW_PCB]
avail: 04 used: 02 max: 02 err: 00  [UDP_PCB]
avail: 05 used: 03 max: 04 err: 00  [TCP_PCB] 
// used 3 - это запрошено 3 http объекта
avail: 08 used: 01 max: 01 err: 00  [TCP_PCB_LISTEN] 
// used 1 - это слушаем порт 80
avail: 16 used: 00 max: 04 err: 00  [TCP_SEG]
avail: 05 used: 00 max: 00 err: 00  [REASSDATA]
avail: 15 used: 00 max: 00 err: 00  [FRAG_PBUF]
avail: 03 used: 03 max: 03 err: 00  [SYS_TIMEOUT]
avail: 16 used: 00 max: 02 err: 00  [PBUF_REF/ROM]
avail: 16 used: 01 max: 02 err: 00  [PBUF_POOL]
avail: 06 used: 00 max: 06 err: 00  [MALLOC_256]
avail: 02 used: 00 max: 00 err: 00  [MALLOC_512]
avail: 02 used: 00 max: 01 err: 00  [MALLOC_1512]

Через пару минут в результате работы tcp_tmr соединения tcp закрываются и память TCP_PCB очищается .