paclema / esp32_lwip_nat_example

4 stars 2 forks source link

Setting DNS IP from STA to AP side doesn't work on latest Espressif ESP32 framework #7

Open georgie3 opened 2 months ago

georgie3 commented 2 months ago

The DNS offer code and some other parts don't work with recent versions of the Espressif ESP32 framework: ver 3.0.0+ for Arduino IDE or ESP-IDF ver 5.1+. This is due to deprecated/removed features.

Here are suggested fixes using Arduino IDE:

1) Replace existing code to "Give DNS servers to AP side" (lines 130-156), since code with tcpipadapter* appears to have been deprecated / removed from ESP-IDF. Can use the following:

    // This function is not in any header file, taken from code associated with WiFi.h (AP.cpp)
    esp_netif_t* get_esp_interface_netif(esp_interface_t interface);
    esp_netif_t* esp_netif_ap = get_esp_interface_netif(ESP_IF_WIFI_AP);   // Get the esp_netif reference for AP
    Serial.printf("AP esp_netif is %p\n", esp_netif_ap);
    if (esp_netif_ap != nullptr) {
        // Note this assumes IPv4
        ip_addr_t dnsip = {};
        WiFi.dnsIP(0).to_ip_addr_t(&dnsip);  // Get the main DNS server address from STA
        u32_t addr = dnsip.u_addr.ip4.addr;  // Convert to unsigned int, already in network byte order
        if (addr == 0) {
            addr = htonl(0x08080808);       // Use Google as fallback
        }
        Serial.printf("Giving DNS IP %s to AP\n", IPAddress(addr).toString().c_str());

        esp_netif_dns_info_t dns = {};
        dns.ip.u_addr.ip4.addr = addr;
        dns.ip.type = IPADDR_TYPE_V4;
        dhcps_offer_t dhcps_dns_value = OFFER_DNS;
        ESP_ERROR_CHECK(esp_netif_dhcps_stop(esp_netif_ap));
        ESP_ERROR_CHECK(esp_netif_dhcps_option(esp_netif_ap, ESP_NETIF_OP_SET, ESP_NETIF_DOMAIN_NAME_SERVER, &dhcps_dns_value, sizeof(dhcps_dns_value)));
        ESP_ERROR_CHECK(esp_netif_set_dns_info(esp_netif_ap, ESP_NETIF_DNS_MAIN, &dns));  // Only one DNS supported, not BACKUP or FALLBACK
        ESP_ERROR_CHECK(esp_netif_dhcps_start(esp_netif_ap));
    }

2) Remove all code in loop() function, it is non-critical. Replace with delay(1000);

3) Note to fully migrate the code away from deprecated APIs to the new Espressif APIs you will need to use 'esp_netif' style calls as in this example: https://github.com/espressif/esp-idf/tree/master/examples/wifi/softap_sta

In my testing the code here is significantly faster than using the new APIs for everything, ~10 Mbps down vs. 6 Mbps. Not sure why. All this took me several days to figure out!

paclema commented 2 months ago

Thank you @georgie3 for sharing your extensive research! It is also interesting that the new API calls make such an impact in the performance

gsicilia82 commented 5 days ago

@georgie3 What kind of code are you using to reach 10Mbps down speed? With latest Tasmota platform, I reach ~2.5Mbps on speedtest.net

[env:esp32]
platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.08.10/platform-espressif32.zip
platform_packages = 
framework = arduino

With older release, I get ~3.5MBps

platform = https://github.com/tasmota/platform-espressif32/releases/download/v.2.0.5/platform-espressif32-v.2.0.5.zip

BTW: Espressif has released a full compatible Arduino Code for WiFiExtender functionality based on latest Core3.x.x: https://github.com/espressif/arduino-esp32/blob/master/libraries/WiFi/examples/WiFiExtender/WiFiExtender.ino

It works well with Tasmota Arduino Core releases. Maybe, it is not necessary anymore to recompile Arduino by your own (if not yet using directly Tasmota releases). If recompile from Arduino Core (with enabled NAPT option) would be necessary, I would pretend to see a hint inside Espressifs example code.