mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 06:33:51 +00:00 
			
		
		
		
	Merge branch 'fix_ethernet_reconnect_ipv6' into integration
This commit is contained in:
		| @@ -300,6 +300,7 @@ void EthernetComponent::loop() { | ||||
|         this->state_ = EthernetComponentState::CONNECTING; | ||||
|         this->start_connect_(); | ||||
|       } else { | ||||
|         this->finish_connect_(); | ||||
|         // When connected and stable, disable the loop to save CPU cycles | ||||
|         this->disable_loop(); | ||||
|       } | ||||
| @@ -486,10 +487,33 @@ void EthernetComponent::got_ip6_event_handler(void *arg, esp_event_base_t event_ | ||||
| } | ||||
| #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_() { | ||||
|   global_eth_component->got_ipv4_address_ = false; | ||||
| #if USE_NETWORK_IPV6 | ||||
|   global_eth_component->ipv6_count_ = 0; | ||||
|   this->ipv6_setup_done_ = false; | ||||
| #endif /* USE_NETWORK_IPV6 */ | ||||
|   this->connect_begin_ = millis(); | ||||
|   this->status_set_warning(LOG_STR("waiting for IP configuration")); | ||||
| @@ -545,9 +569,22 @@ void EthernetComponent::start_connect_() { | ||||
|     } | ||||
|   } | ||||
| #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_); | ||||
|   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 */ | ||||
|  | ||||
|   | ||||
| @@ -102,6 +102,7 @@ class EthernetComponent : public Component { | ||||
| #endif /* LWIP_IPV6 */ | ||||
|  | ||||
|   void start_connect_(); | ||||
|   void finish_connect_(); | ||||
|   void dump_connect_params_(); | ||||
|   /// @brief Set `RMII Reference Clock Select` bit for KSZ8081. | ||||
|   void ksz8081_set_clock_reference_(esp_eth_mac_t *mac); | ||||
| @@ -144,6 +145,7 @@ class EthernetComponent : public Component { | ||||
|   bool got_ipv4_address_{false}; | ||||
| #if LWIP_IPV6 | ||||
|   uint8_t ipv6_count_{0}; | ||||
|   bool ipv6_setup_done_{false}; | ||||
| #endif /* LWIP_IPV6 */ | ||||
|  | ||||
|   // Pointers at the end (naturally aligned) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user