UDP

Программируем под Atollic True Studio на STM32. Делаем RNDIS адаптер. По сути это сетевая карта.

Фишка в том , что по умолчанию в LWIP запросы по UDP не отрабатываются, то есть на все запросы мы не отвечаем (for_us = 0). Нам надо указать какой порт мы хотим отрабатывать, то есть провести инициализацию.

Чтобы включить отработку запросов по udp делаем примерно так (udp_new , udp_bind , udp_recv) , один раз при инициализации :

struct udp_pcb *pcb = udp_new();

err = udp_bind(pcb, IP_ADDR_ANY, c->port);

udp_recv(pcb, udp_recv_proc, NULL);
// назначает коллбек функцию 
// для обработки пришедшего пакета на наш порт

Когда мы втыкает такое устройство как сетевой адаптер куда-нибудь в ПК, ОС ПК делает запрос на порт 67 к предполагаемому серверу DHCP , который в этой сети должет быть. Потому , что ОС должна решить вопрос с выделением IP новому сетевому устройству . Но поскольку это устройство сетевой адаптер, то ОС предполагает , что за ним есть сеть , а там скорее всего может быть DHCP сервер, который по мнению ОС и должен выделить нашему адаптеру IP , так как DHCP сервер для этого и предназначен. Таким образм решается вопрос , кто будет выделять IP адаптеру.

Инициализация отработки порта 67 для реализации dhcp сервера проходит по такому пути (это лог) :


0 : -------- > dhserv_init
0 : ------------ > udp_init
0 : ------------ < udp_init
0 : ------------ > dhserv_free
1 : ------------ < dhserv_free
1 : ------------ > udp_new
1 : ---------------- > memp_malloc_fn
1 : -------------------- > memp_overflow_check_all
1 : -------------------- < memp_overflow_check_all
1 :                    memp:2000365C memp_sizes[UDP_PCB] size=32 
2 : ---------------- < memp_malloc_fn
2 : ------------ < udp_new
2 : ------------ > udp_bind
2 : ------------ < udp_bind
2 : ------------ > udp_recv
2 : ------------ < udp_recv
2 : -------- < dhserv_init

Добавление прослушки определенного порта добавляет новый блок памяти в регион [UDP_PCB].

После создания обработчика upd пакетов (67 порта) с первым принимаемым udp пакетом влетаем в его обработку по стандартному пути :


6215 : ---- > ethernet_input
6216 :        ethernet_input: dest:ff:ff:ff:ff:ff:ff, src:20:89:84:6a:96:aa, type:800
6216 : -------- > pbuf_header
6216 :            pbuf_header: old 2000A52C new 2000A53A (-14)
6216 : -------- < pbuf_header
6216 : -------- > ip_input
6217 : ------------ > pbuf_realloc
6217 :                pbuf_realloc 2000A51C new_len=336
6217 : ------------ < pbuf_realloc
6217 : ------------ > raw_input
6217 : ------------ < raw_input
6217 : ------------ > udp_input
6218 : ---------------- > pbuf_header
6218 :                    pbuf_header: old 2000A53A new 2000A54E (-20)
6218 : ---------------- < pbuf_header
6218 : ---------------- > pbuf_header
6218 :                    pbuf_header: old 2000A54E new 2000A556 (-8)
6219 : ---------------- < pbuf_header
6219 : ---------------- > udp_recv_proc
6219 : -------------------- > pbuf_alloc
6219 :                        layer=[PBUF_TRANSPORT] offset=54 type=[PBUF_POOL] 
6219 : ------------------------ > memp_malloc_fn
6220 : ---------------------------- > memp_overflow_check_all
6220 : ---------------------------- < memp_overflow_check_all
6220 :                            memp:20009EEC memp_sizes[PBUF_POOL] size=1540 
6221 : ------------------------ < memp_malloc_fn
6221 :                        pbuf_alloc: allocated pbuf 20009F00
6221 :                        pbuf_alloc:  ASSIGN p->payload 20009F48 offset=54 SIZEOF_STRUCT_PBUF=16
6222 :                        pbuf_alloc: p->tot_len=x204 [516] rem_len=x0  p->len=x204 p->ref=1
6222 : -------------------- < pbuf_alloc
6222 : -------------------- > udp_sendto
6222 : -------------------- < udp_sendto
6223 : -------------------- > udp_sendto_if
6223 : ------------------------ > pbuf_header
6223 :                            pbuf_header: old 20009F48 new 20009F40 (8)
6223 : ------------------------ < pbuf_header
6223 : ------------------------ > ip_output_if
6224 : ---------------------------- > pbuf_header
6224 :                                pbuf_header: old 20009F40 new 20009F2C (20)
6224 : ---------------------------- < pbuf_header
6224 : ---------------------------- > rndis_output_fn
6225 : -------------------------------- > etharp_output
6225 : ------------------------------------ > pbuf_header
6225 :                                        pbuf_header: old 20009F2C new 20009F1E (14)
6225 : ------------------------------------ < pbuf_header
6226 : ------------------------------------ > etharp_send_ip
6226 :                                        etharp_send_ip: sending packet 0x20009f00
6226 : ---------------------------------------- > rndis_linkoutput_fn
6227 : -------------------------------------------- > rndis_can_send
6227 : -------------------------------------------- < rndis_can_send
6227 : -------------------------------------------- > rndis_can_send
6228 : -------------------------------------------- < rndis_can_send
6228 : -------------------------------------------- > rndis_send
6228 :                                                 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x20 0x89 0x84 0x6A 0x96 0x03 0x08 0x00 0x45 0x00 0x02 0x20 0x00 0x00 0x00 0x00 0xFF 0x11 0xF2 0x23 0xC0 0xA8 0x07 0x01 0xFF 0xFF 0xFF 0xFF 0x00 0x43 0x00 0x44 0x02 0x0C 0x0F 0x32 0x02 0x01 0x06 0x00 0x79 0xAA 0x51 0x5A 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xC0 0xA8 0x07 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x20 0x89 0x84 0x6A 0x96 0xAA 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
6235 :                                                 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x63 0x82 0x53 0x63 0x35 0x01 0x05 0x36 0x04 0xC0 0xA8 0x07 0x01 0x33 0x04 0x00 0x01 0x51 0x80 0x01 0x04 0xFF 0xFF 0xFF 0x00 0x03 0x04 0xC0 0xA8 0x07 0x01 0x0F 0x03 0x73 0x74 0x6D 0xFF 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
6242 :                                                 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
6244 : -------------------------------------------- < rndis_send
6244 : ---------------------------------------- < rndis_linkoutput_fn
6245 : ------------------------------------ < etharp_send_ip
6245 : -------------------------------- < etharp_output
6246 : ---------------------------- < rndis_output_fn
6246 : ------------------------ < ip_output_if
6246 : -------------------- < udp_sendto_if
6246 : -------------------- > pbuf_free
6246 :                        pbuf_free: pbuf:20009F00 [PBUF_POOL]
6247 :                        pbuf_free: deallocating 20009F00 [PBUF_POOL]
6247 : ------------------------ > memp_overflow_check_all
6247 : ------------------------ < memp_overflow_check_all
6248 :                        memp_free memp:20009EEC [PBUF_POOL]
6248 : -------------------- < pbuf_free
6248 : -------------------- > pbuf_free
6248 :                        pbuf_free: pbuf:2000A51C [PBUF_POOL]
6248 :                        pbuf_free: deallocating 2000A51C [PBUF_POOL]
6249 : ------------------------ > memp_overflow_check_all
6249 : ------------------------ < memp_overflow_check_all
6249 :                        memp_free memp:2000A508 [PBUF_POOL]
6250 : -------------------- < pbuf_free
6250 : ---------------- < udp_recv_proc
6250 : ------------ < udp_input

6250 :            [UDP_PCB] memp 200035B4 size=32 num=4 free memp:20003624 free block:20003638
6251 :            	200035C8 [0] 	20003600 [0] 	20003638 [0] 
6251 :            	20003670 [1] :
6251 :            		next:0 local_port:67 

6251 :            [PBUF_POOL] memp 20004964 size=1540 num=16 free memp:2000A508 free block:2000A51C
6252 :            	20004978 [0] 	20004F94 [0] 	200055B0 [0] 	20005BCC [0] 	200061E8 [0] 	20006804 [0] 	20006E20 [0] 	2000743C [0] 	20007A58 [0] 	20008074 [0] 	20008690 [0] 	20008CAC [0] 	200092C8 [0] 	200098E4 [0] 	20009F00 [0] 	2000A51C [0] 
6253 : -------- < ip_input
6253 : ---- < ethernet_input

Не забываем после отработки udp пакета очистить блок памяти в регионе [PBUF_POOL] с содержанием принятого пакета.

Таким образом для обслуживания только одного порта (например 67) вполне достаточно выделить только один блок памяти в регионе [UDP_PCB] .
Делается это в файле memp_std.h (MEMP_NUM_UDP_PCB =1) :

LWIP_MEMPOOL( UDP_PCB,        MEMP_NUM_UDP_PCB,         sizeof(struct udp_pcb),        "UDP_PCB")