From c418eecf839b527f61f05a4b2b1e8128df8933e0 Mon Sep 17 00:00:00 2001 From: Jimmy Hedman Date: Mon, 31 Jul 2023 00:20:55 +0200 Subject: [PATCH] Enable IPv6 for ESP32 Arduino, wifi and ethernet (#4865) --- .../ethernet/ethernet_component.cpp | 46 +++++++++++++++++++ .../components/ethernet/ethernet_component.h | 7 +++ esphome/components/network/__init__.py | 18 +++++--- .../wifi/wifi_component_esp32_arduino.cpp | 10 ++++ 4 files changed, 75 insertions(+), 6 deletions(-) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 3b5804abdd..d9004a913b 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -118,6 +118,10 @@ void EthernetComponent::setup() { ESPHL_ERROR_CHECK(err, "ETH event handler register error"); err = esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &EthernetComponent::got_ip_event_handler, nullptr); ESPHL_ERROR_CHECK(err, "GOT IP event handler register error"); +#if LWIP_IPV6 + err = esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &EthernetComponent::got_ip6_event_handler, nullptr); + ESPHL_ERROR_CHECK(err, "GOT IP6 event handler register error"); +#endif /* LWIP_IPV6 */ /* start Ethernet driver state machine */ err = esp_eth_start(this->eth_handle_); @@ -160,6 +164,20 @@ void EthernetComponent::loop() { this->state_ = EthernetComponentState::CONNECTING; this->start_connect_(); } +#if LWIP_IPV6 + else if (this->got_ipv6_) { + esp_ip6_addr_t ip6_addr; + if (esp_netif_get_ip6_global(this->eth_netif_, &ip6_addr) == 0 && + esp_netif_ip6_get_addr_type(&ip6_addr) == ESP_IP6_ADDR_IS_GLOBAL) { + ESP_LOGCONFIG(TAG, "IPv6 Addr (Global): " IPV6STR, IPV62STR(ip6_addr)); + } else { + esp_netif_get_ip6_linklocal(this->eth_netif_, &ip6_addr); + ESP_LOGCONFIG(TAG, " IPv6: " IPV6STR, IPV62STR(ip6_addr)); + } + + this->got_ipv6_ = false; + } +#endif /* LWIP_IPV6 */ break; } } @@ -254,6 +272,15 @@ void EthernetComponent::got_ip_event_handler(void *arg, esp_event_base_t event_b ESP_LOGV(TAG, "[Ethernet event] ETH Got IP (num=%" PRId32 ")", event_id); } +#if LWIP_IPV6 +void EthernetComponent::got_ip6_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, + void *event_data) { + ESP_LOGV(TAG, "[Ethernet event] ETH Got IP6 (num=%d)", event_id); + global_eth_component->got_ipv6_ = true; + global_eth_component->ipv6_count_ += 1; +} +#endif /* LWIP_IPV6 */ + void EthernetComponent::start_connect_() { this->connect_begin_ = millis(); this->status_set_warning(); @@ -316,6 +343,12 @@ void EthernetComponent::start_connect_() { if (err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED) { ESPHL_ERROR_CHECK(err, "DHCPC start error"); } +#if LWIP_IPV6 + err = esp_netif_create_ip6_linklocal(this->eth_netif_); + if (err != ESP_OK) { + ESPHL_ERROR_CHECK(err, "IPv6 local failed"); + } +#endif /* LWIP_IPV6 */ } this->connect_begin_ = millis(); @@ -343,6 +376,19 @@ void EthernetComponent::dump_connect_params_() { ESP_LOGCONFIG(TAG, " DNS2: %s", network::IPAddress(dns_ip2->addr).str().c_str()); #endif +#if LWIP_IPV6 + if (this->ipv6_count_ > 0) { + esp_ip6_addr_t ip6_addr; + esp_netif_get_ip6_linklocal(this->eth_netif_, &ip6_addr); + ESP_LOGCONFIG(TAG, " IPv6: " IPV6STR, IPV62STR(ip6_addr)); + + if (esp_netif_get_ip6_global(this->eth_netif_, &ip6_addr) == 0 && + esp_netif_ip6_get_addr_type(&ip6_addr) == ESP_IP6_ADDR_IS_GLOBAL) { + ESP_LOGCONFIG(TAG, "IPv6 Addr (Global): " IPV6STR, IPV62STR(ip6_addr)); + } + } +#endif /* LWIP_IPV6 */ + esp_err_t err; uint8_t mac[6]; diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index f6b67f3f82..1bd4786b44 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -65,6 +65,9 @@ class EthernetComponent : public Component { protected: static void eth_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data); static void got_ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data); +#if LWIP_IPV6 + static void got_ip6_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data); +#endif /* LWIP_IPV6 */ void start_connect_(); void dump_connect_params_(); @@ -83,6 +86,10 @@ class EthernetComponent : public Component { bool started_{false}; bool connected_{false}; +#if LWIP_IPV6 + bool got_ipv6_{false}; + uint8_t ipv6_count_{0}; +#endif /* LWIP_IPV6 */ EthernetComponentState state_{EthernetComponentState::STOPPED}; uint32_t connect_begin_; esp_netif_t *eth_netif_{nullptr}; diff --git a/esphome/components/network/__init__.py b/esphome/components/network/__init__.py index 96cfc51ff5..cd29734f42 100644 --- a/esphome/components/network/__init__.py +++ b/esphome/components/network/__init__.py @@ -1,3 +1,4 @@ +from esphome.core import CORE import esphome.codegen as cg import esphome.config_validation as cv from esphome.components.esp32 import add_idf_sdkconfig_option @@ -14,8 +15,8 @@ IPAddress = network_ns.class_("IPAddress") CONFIG_SCHEMA = cv.Schema( { - cv.SplitDefault(CONF_ENABLE_IPV6, esp32_idf=False): cv.All( - cv.only_with_esp_idf, cv.boolean + cv.SplitDefault(CONF_ENABLE_IPV6, esp32=False): cv.All( + cv.only_on_esp32, cv.boolean ), } ) @@ -23,7 +24,12 @@ CONFIG_SCHEMA = cv.Schema( async def to_code(config): if CONF_ENABLE_IPV6 in config: - add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", config[CONF_ENABLE_IPV6]) - add_idf_sdkconfig_option( - "CONFIG_LWIP_IPV6_AUTOCONFIG", config[CONF_ENABLE_IPV6] - ) + if CORE.using_esp_idf: + add_idf_sdkconfig_option("CONFIG_LWIP_IPV6", config[CONF_ENABLE_IPV6]) + add_idf_sdkconfig_option( + "CONFIG_LWIP_IPV6_AUTOCONFIG", config[CONF_ENABLE_IPV6] + ) + else: + if config[CONF_ENABLE_IPV6]: + cg.add_build_flag("-DCONFIG_LWIP_IPV6") + cg.add_build_flag("-DCONFIG_LWIP_IPV6_AUTOCONFIG") diff --git a/esphome/components/wifi/wifi_component_esp32_arduino.cpp b/esphome/components/wifi/wifi_component_esp32_arduino.cpp index 3628eca78d..995e5e587e 100644 --- a/esphome/components/wifi/wifi_component_esp32_arduino.cpp +++ b/esphome/components/wifi/wifi_component_esp32_arduino.cpp @@ -485,6 +485,9 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ buf[it.ssid_len] = '\0'; ESP_LOGV(TAG, "Event: Connected ssid='%s' bssid=" LOG_SECRET("%s") " channel=%u, authmode=%s", buf, format_mac_addr(it.bssid).c_str(), it.channel, get_auth_mode_str(it.authmode)); +#if LWIP_IPV6 + WiFi.enableIpV6(); +#endif /* LWIP_IPV6 */ break; } @@ -547,6 +550,13 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ s_sta_connecting = false; break; } +#if LWIP_IPV6 + case ESPHOME_EVENT_ID_WIFI_STA_GOT_IP6: { + auto it = info.got_ip6.ip6_info; + ESP_LOGV(TAG, "Got IPv6 address=" IPV6STR, IPV62STR(it.ip)); + break; + } +#endif /* LWIP_IPV6 */ case ESPHOME_EVENT_ID_WIFI_STA_LOST_IP: { ESP_LOGV(TAG, "Event: Lost IP"); break;