espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.44k stars 7.25k forks source link

[Feature Request] Enable DHCP-Server for ethernet (IDFGH-1883) #4086

Closed plasger-ebv closed 4 years ago

plasger-ebv commented 5 years ago

Hi,

currently the code in tcpip_adapter_dhcps_start() (in _stop() as well) prevents using the DHCP Server on any other interface than the WiFi Access Point. I would like to be able to use it via ethernet as well. Is that possible or is there a kind of "fundamental" reason why that code is there?

Alvin1Zhang commented 5 years ago

Thanks for raising the feature request. @plasger-ebv

david-cermak commented 4 years ago

Hi @plasger-ebv

It is now possible with the esp_netif to configure network interfaces in more flexible way.

You can check the below settings to enable the DHCP server on ethernet:

 const esp_netif_ip_info_t my_ap_ip = {
        .ip = { .addr = IP4TOADDR( 192, 168, 1, 1) },
        .gw = { .addr = IP4TOADDR( 192, 168, 1, 1) },
        .netmask = { .addr = IP4TOADDR( 255, 255, 255, 0) },

};

const esp_netif_inherent_config_t eth_behav_cfg = {
        .get_ip_event = IP_EVENT_ETH_GOT_IP,
        .lost_ip_event = 0,
        .flags = ESP_NETIF_DHCP_SERVER | ESP_NETIF_FLAG_AUTOUP,
        .ip_info = (esp_netif_ip_info_t*)& my_ap_ip,
        .if_key = "ETHDHCPS",
        .if_desc = "eth",
        .route_prio = 50
};

esp_netif_config_t my_eth_cfg = { .base = & eth_behav_cfg, .stack = ESP_NETIF_NETSTACK_DEFAULT_ETH };

esp_netif_t *esp_netif = esp_netif_new(& my_eth_cfg);

Replacing the default config here, keeping the rest of initialisation intact.

arnkmar commented 4 years ago

Hello @david-cermak

Unable to build any project. Issue from latest esp_netif.

C:/Installations/esp-idf-master-1811/components/esp_netif/lwip/esp_netif_lwip.c:815:38: error: macro "LWIP_DHCP_IP_ADDR_ERASE" passed 1 arguments, but takes just 0 LWIP_DHCP_IP_ADDR_ERASE(esp_netif); ^ C:/Installations/esp-idf-master-1811/components/esp_netif/lwip/esp_netif_lwip.c:815:5: error: 'LWIP_DHCP_IP_ADDR_ERASE' undeclared (first use in this function) LWIP_DHCP_IP_ADDR_ERASE(esp_netif);

david-cermak commented 4 years ago

Hi @arnkmar, you've probably missed the lwip submodule update.?

arnkmar commented 4 years ago

Hi @david-cermak

Your comment helped me to fix the issue. Thanks!

david-cermak commented 4 years ago

Posting a version of the code that was actually tested and works as ethernet on ESP32 running a DHCP server:

void app_main(void)
{
    // Initialize TCP/IP network interface (should be called only once in application)
    esp_netif_init();
    // Create default event loop that running in background
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    const esp_netif_inherent_config_t eth_behav_cfg = {
            .get_ip_event = IP_EVENT_ETH_GOT_IP,
            .lost_ip_event = 0,
            .flags = ESP_NETIF_DHCP_SERVER | ESP_NETIF_FLAG_AUTOUP,
            .ip_info = (esp_netif_ip_info_t*)& soft_ap_ip,
            .if_key = "ETH_DHCPS",
            .if_desc = "eth",
            .route_prio = 50
    };

    esp_netif_config_t eth_as_dhcps_cfg = { .base = &eth_behav_cfg, .stack = ESP_NETIF_NETSTACK_DEFAULT_ETH };

    esp_netif_t *eth_netif = esp_netif_new(&eth_as_dhcps_cfg);

    // Set handlers to process TCP/IP stuffs
    esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_START, esp_netif_action_start, eth_netif);
    esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_STOP, esp_netif_action_stop, eth_netif);

    // Register user defined event handers
    ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &eth_event_handler, NULL));
    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));

    eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
    eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
    phy_config.phy_addr = CONFIG_EXAMPLE_ETH_PHY_ADDR;
    phy_config.reset_gpio_num = CONFIG_EXAMPLE_ETH_PHY_RST_GPIO;
#if CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET
    mac_config.smi_mdc_gpio_num = CONFIG_EXAMPLE_ETH_MDC_GPIO;
    mac_config.smi_mdio_gpio_num = CONFIG_EXAMPLE_ETH_MDIO_GPIO;
    esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config);
#if CONFIG_EXAMPLE_ETH_PHY_IP101
    esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config);
#elif CONFIG_EXAMPLE_ETH_PHY_RTL8201
    esp_eth_phy_t *phy = esp_eth_phy_new_rtl8201(&phy_config);
#elif CONFIG_EXAMPLE_ETH_PHY_LAN8720
    esp_eth_phy_t *phy = esp_eth_phy_new_lan8720(&phy_config);
#elif CONFIG_EXAMPLE_ETH_PHY_DP83848
    esp_eth_phy_t *phy = esp_eth_phy_new_dp83848(&phy_config);
#endif
#elif CONFIG_EXAMPLE_USE_DM9051
    gpio_install_isr_service(0);
    spi_device_handle_t spi_handle = NULL;
    spi_bus_config_t buscfg = {
        .miso_io_num = CONFIG_EXAMPLE_DM9051_MISO_GPIO,
        .mosi_io_num = CONFIG_EXAMPLE_DM9051_MOSI_GPIO,
        .sclk_io_num = CONFIG_EXAMPLE_DM9051_SCLK_GPIO,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
    };
    ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_EXAMPLE_DM9051_SPI_HOST, &buscfg, 1));
    spi_device_interface_config_t devcfg = {
        .command_bits = 1,
        .address_bits = 7,
        .mode = 0,
        .clock_speed_hz = CONFIG_EXAMPLE_DM9051_SPI_CLOCK_MHZ * 1000 * 1000,
        .spics_io_num = CONFIG_EXAMPLE_DM9051_CS_GPIO,
        .queue_size = 20
    };
    ESP_ERROR_CHECK(spi_bus_add_device(CONFIG_EXAMPLE_DM9051_SPI_HOST, &devcfg, &spi_handle));
    /* dm9051 ethernet driver is based on spi driver */
    eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle);
    dm9051_config.int_gpio_num = CONFIG_EXAMPLE_DM9051_INT_GPIO;
    esp_eth_mac_t *mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
    esp_eth_phy_t *phy = esp_eth_phy_new_dm9051(&phy_config);
#endif
    esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
    esp_eth_handle_t eth_handle = NULL;
    ESP_ERROR_CHECK(esp_eth_driver_install(&config, &eth_handle));
    /* attach Ethernet driver to TCP/IP stack */
    ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handle)));
    /* start Ethernet driver state machine */
    ESP_ERROR_CHECK(esp_eth_start(eth_handle));
}

In contrast to the version sketched here it uses its own event handlers only for START and STOP action (rather than calling esp_eth_set_default_handlers(), which might cause trouble when default ON-CONNECT action taken)

Alvin1Zhang commented 4 years ago

@plasger-ebv Thanks for reporting the issue, the issue has been fixed in https://github.com/espressif/esp-idf/commit/ffe043b1a81a0f9e1cc2cfa8873e21318ec89143, feel free to reopen if needed. Thanks.

Henrikastro commented 2 years ago

I don't know if I should be opening a new issue for this but when trying to get what @david-cermak wrote to compile I'm getting hit with the following error:

from ../main/ethernet_example_main.c:13: ../../../../components/esp_netif/include/esp_netif_defaults.h:166:49: error: initializer element is not constant

define ESP_NETIF_NETSTACK_DEFAULT_ETH _g_esp_netif_netstack_default_eth

                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

../../../../components/esp_netif/include/esp_netif_defaults.h:166:49: note: in definition of macro 'ESP_NETIFNETSTACK DEFAULT_ETH'

define ESP_NETIF_NETSTACK_DEFAULT_ETH _g_esp_netif_netstack_default_eth

                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

../../../../components/esp_netif/include/esp_netif_defaults.h:166:49: note: (near initialization for 'my_eth_cfg.stack' )

define ESP_NETIF_NETSTACK_DEFAULT_ETH _g_esp_netif_netstack_default_eth

                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

../../../../components/esp_netif/include/esp_netif_defaults.h:166:49: note: in definition of macro 'ESP_NETIFNETSTACK DEFAULT_ETH'

define ESP_NETIF_NETSTACK_DEFAULT_ETH _g_esp_netif_netstack_default_eth

                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

../main/ethernet_example_main.c:72:26: error: initializer element is not constant esp_netif_t *esp_netif = esp_netif_new(& my_eth_cfg);

do I need to update my esp-idf or something? I'm using version v4.3.3-30-g5be64c3111

Edit:

Not really sure what I did but I think I was using the first code suggestion that David did alongside the second one and maybe that was causing the issue? Not really sure but it's fixed now.

mickeyl commented 1 year ago

Thanks for all participating on that issue, it's great that it works now. May I ask about the DHCP server's lease configuration though? What's the standard configuration and how can we adjust it based on the code in https://github.com/espressif/esp-idf/issues/4086#issuecomment-559530841?

yunfusheng33 commented 2 months ago

May I ask, I want to simulate a network card through USB to achieve network connection? I am currently using a static IP to initialize the network. How can I use DHCP to automatically allocate the network?

mickeyl commented 2 months ago

Better to open a separate issue for this, since this is already closed.