espressif / esp-lwip

Fork of lwIP (https://savannah.nongnu.org/projects/lwip/) with ESP-IDF specific patches
Other
79 stars 126 forks source link

Is it possible to use the NAPT feature for another MCU other than the ESP32/ESP8266? (IDFGH-9562) #51

Closed anhnt-dev closed 1 year ago

anhnt-dev commented 1 year ago

Is it possible if I uses this lwip version (with NAPT feature supported) to make a WiFi repeater with a WiFi module support SPI interface communicate with STM32 host MCU? This WiFi module also supports run STA and AP concurrency.

david-cermak commented 1 year ago

Yes, it is possible. I'd suggest using 2.1.3-esp branch, since the current default (2.1.2-esp) contains many Espressif patches and it might be quite difficult to even build it without ESP-IDF. While the 2.1.3-esp could be normally built and run without IDF (as used in the tests), and if macro ESP_LWIP set to 0, the actual code should correspond to the official lwip 2.1.3-rel (note that you can build with ESP_LWIP=0, but I'm afraid the NAPT module needs ESP_LWIP=1).

This WiFi module also supports run STA and AP concurrency.

From lwip's perspective, these are two separate network interfaces, so it should normally work.

anhnt-dev commented 1 year ago

thank @david-cermak very much for your response, so in theory, I just need to add STA & AP interface by netif_add() and then enable ip_napt_enable(), DNS, ... and then it should work?

david-cermak commented 1 year ago

Yes, this should work. Plus, you'd have to define the input and output packet paths for your STM32 (which is done via netif_add()).

You can start with these simple test cases: 1) Setup STA:

https://github.com/espressif/esp-lwip/blob/280c3d61d9422c570469a21330903762a7727f98/test/unit/core/test_ip4_route.c#L360-L365

2) Setup AP:

https://github.com/espressif/esp-lwip/blob/280c3d61d9422c570469a21330903762a7727f98/test/unit/core/test_ip4_route.c#L367-L372

3) Enable NAPT:

https://github.com/espressif/esp-lwip/blob/280c3d61d9422c570469a21330903762a7727f98/test/unit/core/test_ip4_route.c#L373

Then, we just send a packet to one interface and expect it to be NAT'ed on the other one. After making this to work, you can employ DNS, DHCP etc. (DHCP server for the AP? -- this part is not in esp-lwip)

anhnt-dev commented 1 year ago

That's great, I will try and respond soon. Thanks @david-cermak.

anhnt-dev commented 1 year ago

Hi @david-cermak , I'm trying to import2.1.3-esp to my project. Unfortunately, NAPT still needs ESP_LWIP=1. For now, I can successfully build my project with new lwip, DHCP client, and Iperf worked fine. But I have a problem with the DHCP server, which worked with lwip 2.1.2 official version. Am I missing something?

anhnt-dev commented 1 year ago

I found a root cause of DHCP server didn't work in my code. In my firmware, I used netif_find to search netif interface by name and then use it for netif->input(), but in 2.1.3-esp have to check name[2] must != 0, why we need to check that although netif->name only contains 2 characters? https://github.com/espressif/esp-lwip/blob/d5e56d06658ae11292be1baea56204f7120b6fa7/src/core/netif.c#L1737-L1740

anhnt-dev commented 1 year ago

Some updates about NAPT mode, seem to work for me. For now, I have a SoftAP interface with IP 10.10.0.1 and STA connected to a wifi network with gateway IP 192.168.1.1. When the client connected to SoftAP (assigned 10.10.0.2), I'm able to ping gateway 192.168.1.1. So the question is, what are the next steps I need to make the client can connect to the internet? Might I need to implement DNS to make it work?

david-cermak commented 1 year ago

NAPT still needs ESP_LWIP=1.

I think you can still enable this flag only for that file, while keeping it disabled for the entire component.

I have a problem with the DHCP server

This is still the same as in 2.1.2-esp, the DHCP server is NOT in lwip, you can only find it in IDF, in the lwip port layer

why we need to check that although netif->name only contains 2 characters?

the argument to netif_find() is a human readable name of the interface, such as en0. It was a bug fixed in 2f8886794. internally, the netif struct uses only two char name, but has also num to uniquely identify interfaces (so you can have en0, en1, ...)

what are the next steps I need to make the client can connect to the internet?

you should be able to access internet, already, provided you connect via a remote IP address (rather than hostname) and of course if the STA address is valid and connected to your ISP/router. Next steps should be: 1) Use DHCP client for your STA 2) Use DHCP server for your AP 3) Setup DNS server on the AP interface

anhnt-dev commented 1 year ago

I still can't connect to the internet. Although SoftAP & STA interface worked in single (tested with iperf tool), when I enable ip_napt_enable() and turn on NAPT_DEBUG, here are the log when I try ping to router WiFi _NAPT table: src dest sport dport mport
+-----------------------+-----------------------+-------+-------+-------+ not found ip_napt_insert(): TCP=0, UDP=0, ICMP=1 ip_napt_add NAPT table: src dest sport dport mport
+-----------------------+-----------------------+-------+-------+-------+ | 192 | 168 | 69 | 10 | 192 | 168 | 1 | 1 | 158 | 158 | 158 | ip_napt_find looking up in table dest: 192.168.1.1, port: 158, mport: 158 NAPT table: src dest sport dport mport
+-----------------------+-----------------------+-------+-------+-------+ | 192 | 168 | 69 | 10 | 192 | 168 | 1 | 1 | 158 | 158 | 158 | found ip_napt_find looking up in table src: 192.168.69.10, port: 158, mport: 0 NAPT table: src dest sport dport mport
+-----------------------+-----------------------+-------+-------+-------+ | 192 | 168 | 69 | 10 | 192 | 168 | 1 | 1 | 158 | 158 | 158 | found ip_naptfree

I also try to do the same thing on ESP32, it worked fine, and here are NAPT logs, they appear immediately after I connect the device to SoftAP: _NAPT table: src dest sport dport mport
+-----------------------+-----------------------+-------+-------+-------+ | 192 | 168 | 4 | 2 | 8 | 8 | 8 | 8 | 13724 | 53 | 55203 | | 192 | 168 | 4 | 2 | 8 | 8 | 8 | 8 | 12726 | 53 | 59386 | | 192 | 168 | 4 | 2 | 8 | 8 | 8 | 8 | 48939 | 53 | 52039 | | 192 | 168 | 4 | 2 | 8 | 8 | 8 | 8 | 20071 | 53 | 60972 | | 192 | 168 | 4 | 2 | 157 | 240 | 199 | 34 | 41186 | 443 | 49392 | | 192 | 168 | 4 | 2 | 172 | 217 | 24 | 99 | 40764 | 80 | 54097 | | 192 | 168 | 4 | 2 | 8 | 8 | 8 | 8 | 34700 | 53 | 56399 | | 192 | 168 | 4 | 2 | 142 | 250 | 204 | 36 | 45856 | 443 | 54343 | | 192 | 168 | 4 | 2 | 8 | 8 | 8 | 8 | 1522 | 53 | 54849 | | 192 | 168 | 4 | 2 | 8 | 8 | 8 | 8 | 9289 | 53 | 51385 | ip_napt_find looking up in table src: 192.168.4.2, port: 43334, mport: 0 NAPT table: src dest sport dport mport
+-----------------------+-----------------------+-------+-------+-------+ | 192 | 168 | 4 | 2 | 8 | 8 | 8 | 8 | 13724 | 53 | 55203 | | 192 | 168 | 4 | 2 | 8 | 8 | 8 | 8 | 12726 | 53 | 59386 | | 192 | 168 | 4 | 2 | 8 | 8 | 8 | 8 | 48939 | 53 | 52039 | | 192 | 168 | 4 | 2 | 8 | 8 | 8 | 8 | 20071 | 53 | 60972 | | 192 | 168 | 4 | 2 | 157 | 240 | 199 | 34 | 41186 | 443 | 49392 | | 192 | 168 | 4 | 2 | 172 | 217 | 24 | 99 | 40764 | 80 | 54097 | | 192 | 168 | 4 | 2 | 8 | 8 | 8 | 8 | 34700 | 53 | 56399 | | 192 | 168 | 4 | 2 | 142 | 250 | 204 | 36 | 45856 | 443 | 54343 | | 192 | 168 | 4 | 2 | 8 | 8 | 8 | 8 | 1522 | 53 | 54849 | | 192 | 168 | 4 | 2 | 8 | 8 | 8 | 8 | 9289 | 53 | 51385 | not found ip_napt_insert(): TCP=4, UDP=7, ICMP=0 ip_naptadd

david-cermak commented 1 year ago

One reason why the same works on ESP32 and doesn't on STM32 could be the default interface. IDF defines some rules and priorities for interfaces by default, so if we have both station and softAP up and running, the default_netif is always the STA interface. So whenever we're trying to reach an unknown address (say 8.8.8.8) and we have IP_FORWARD=1, then lwip tries to route that packet via the STA to the internet.

What's your default_netif on STM32? Could you try to ping the 8.8.8.8 directly from the device, would it work? You can also enable netif and ip4 debugging in lwip to see more.

anhnt-dev commented 1 year ago

@david-cermak you was right, I changed netif_set_default(&sta_if); and it worked. But throughput is quite low because STA and SoftAP use the same SPI interface. Do you know the tips to improve throughput via lwIP? Can we do anything to improve?

david-cermak commented 1 year ago

you can check IDF docs on lwIP performance https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/lwip.html#performance-optimization this is mostly relevant to ESP chips, but those config options typically represent an lwIP option. If we want to optimize for maximum TCP throughput it usually means to increase buffers, window sizes and adjust RTOs.

But please check what is the bottleneck first. If it's the SPI, then all the above wouldn't help. (perhaps increasing RTO might a little, as it would reduce unnecessary re-transmits when the L2 still busy)

anhnt-dev commented 1 year ago

after some optimization, the throughput is good. Thank @david-cermak very much for your support.