1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-18 19:22:22 +01:00

Merge branch 'fix_ethernet_reconnect_ipv6' into integration

This commit is contained in:
J. Nick Koston
2025-09-14 09:18:32 -05:00
3 changed files with 41 additions and 2 deletions

View File

@@ -300,6 +300,7 @@ void EthernetComponent::loop() {
this->state_ = EthernetComponentState::CONNECTING; this->state_ = EthernetComponentState::CONNECTING;
this->start_connect_(); this->start_connect_();
} else { } else {
this->finish_connect_();
// When connected and stable, disable the loop to save CPU cycles // When connected and stable, disable the loop to save CPU cycles
this->disable_loop(); this->disable_loop();
} }
@@ -486,10 +487,33 @@ void EthernetComponent::got_ip6_event_handler(void *arg, esp_event_base_t event_
} }
#endif /* USE_NETWORK_IPV6 */ #endif /* USE_NETWORK_IPV6 */
void EthernetComponent::finish_connect_() {
#if USE_NETWORK_IPV6
// Retry IPv6 link-local setup if it failed during initial connect
// This handles the case where IPv6 setup failed in start_connect_()
// because the interface wasn't ready (usually cable unplugged/link down,
// rarely a timing issue during state transitions).
// By now we're in CONNECTED state so the interface is definitely up.
if (!this->ipv6_setup_done_) {
esp_err_t err = esp_netif_create_ip6_linklocal(this->eth_netif_);
if (err == ESP_OK) {
ESP_LOGD(TAG, "IPv6 link-local address created (retry succeeded)");
}
// Always set the flag to prevent continuous retries
// If IPv6 setup fails here with the interface up and stable, it's
// likely a persistent issue (IPv6 disabled at router, hardware
// limitation, etc.) that won't be resolved by further retries.
// The device continues to work with IPv4.
this->ipv6_setup_done_ = true;
}
#endif /* USE_NETWORK_IPV6 */
}
void EthernetComponent::start_connect_() { void EthernetComponent::start_connect_() {
global_eth_component->got_ipv4_address_ = false; global_eth_component->got_ipv4_address_ = false;
#if USE_NETWORK_IPV6 #if USE_NETWORK_IPV6
global_eth_component->ipv6_count_ = 0; global_eth_component->ipv6_count_ = 0;
this->ipv6_setup_done_ = false;
#endif /* USE_NETWORK_IPV6 */ #endif /* USE_NETWORK_IPV6 */
this->connect_begin_ = millis(); this->connect_begin_ = millis();
this->status_set_warning(LOG_STR("waiting for IP configuration")); this->status_set_warning(LOG_STR("waiting for IP configuration"));
@@ -545,9 +569,22 @@ void EthernetComponent::start_connect_() {
} }
} }
#if USE_NETWORK_IPV6 #if USE_NETWORK_IPV6
// Attempt to create IPv6 link-local address
// Note: this may fail with ESP_FAIL if the interface is not up yet
// (typically cable unplugged, but could be timing during link transitions).
// We'll retry in the CONNECTED state if it fails here.
err = esp_netif_create_ip6_linklocal(this->eth_netif_); err = esp_netif_create_ip6_linklocal(this->eth_netif_);
if (err != ESP_OK) { if (err != ESP_OK) {
ESPHL_ERROR_CHECK(err, "Enable IPv6 link local failed"); if (err == ESP_ERR_ESP_NETIF_INVALID_PARAMS) {
// This is a programming error, not a transient failure
ESPHL_ERROR_CHECK(err, "esp_netif_create_ip6_linklocal invalid parameters");
} else {
// ESP_FAIL means the interface isn't up yet (e.g., cable unplugged, link down)
// This is expected during reconnection attempts after network interruptions
// We'll retry once we reach CONNECTED state and the interface is actually up
ESP_LOGW(TAG, "esp_netif_create_ip6_linklocal failed: %s", esp_err_to_name(err));
// Don't mark component as failed - this is a transient error
}
} }
#endif /* USE_NETWORK_IPV6 */ #endif /* USE_NETWORK_IPV6 */

View File

@@ -102,6 +102,7 @@ class EthernetComponent : public Component {
#endif /* LWIP_IPV6 */ #endif /* LWIP_IPV6 */
void start_connect_(); void start_connect_();
void finish_connect_();
void dump_connect_params_(); void dump_connect_params_();
/// @brief Set `RMII Reference Clock Select` bit for KSZ8081. /// @brief Set `RMII Reference Clock Select` bit for KSZ8081.
void ksz8081_set_clock_reference_(esp_eth_mac_t *mac); void ksz8081_set_clock_reference_(esp_eth_mac_t *mac);
@@ -144,6 +145,7 @@ class EthernetComponent : public Component {
bool got_ipv4_address_{false}; bool got_ipv4_address_{false};
#if LWIP_IPV6 #if LWIP_IPV6
uint8_t ipv6_count_{0}; uint8_t ipv6_count_{0};
bool ipv6_setup_done_{false};
#endif /* LWIP_IPV6 */ #endif /* LWIP_IPV6 */
// Pointers at the end (naturally aligned) // Pointers at the end (naturally aligned)

View File

@@ -12,7 +12,7 @@ platformio==6.1.18 # When updating platformio, also update /docker/Dockerfile
esptool==5.0.2 esptool==5.0.2
click==8.1.7 click==8.1.7
esphome-dashboard==20250904.0 esphome-dashboard==20250904.0
aioesphomeapi==40.1.0 aioesphomeapi==40.2.0
zeroconf==0.147.2 zeroconf==0.147.2
puremagic==1.30 puremagic==1.30
ruamel.yaml==0.18.15 # dashboard_import ruamel.yaml==0.18.15 # dashboard_import