Browse Source

Test: etharp_gratuitous (#1877)

* test: etharp_gratuitous

* proper checks before calling etharp_gratuitous, move includes

* disable at runtime

* ms values

* reload

* debug

* reword

* filter by ifnum instead of checking for AP mode

* drop station_if check

2.3.0/lwip1 builds netif->num increments on for each sta or ap
lwip2 keeps those constant, but that seems like a implementation detail
might break in the future anyways...
master
Max Prokhorov 5 years ago
committed by GitHub
parent
commit
35ce68710c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 86 additions and 0 deletions
  1. +19
    -0
      code/espurna/config/general.h
  2. +6
    -0
      code/espurna/config/prototypes.h
  3. +61
    -0
      code/espurna/wifi.ino

+ 19
- 0
code/espurna/config/general.h View File

@ -554,6 +554,25 @@
#define WIFI_PROPAGATION_CONST 4 // This is typically something between 2.7 to 4.3 (free space is 2) #define WIFI_PROPAGATION_CONST 4 // This is typically something between 2.7 to 4.3 (free space is 2)
#endif #endif
// ref: https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/kconfig.html#config-lwip-esp-gratuitous-arp
// ref: https://github.com/xoseperez/espurna/pull/1877#issuecomment-525612546
//
// Broadcast gratuitous ARP periodically to update ARP tables on the AP and all devices on the same network.
// Helps to solve compatibility issues when ESP fails to timely reply to ARP requests, causing the device's ARP table entry to expire.
#ifndef WIFI_GRATUITOUS_ARP_SUPPORT
#define WIFI_GRATUITOUS_ARP_SUPPORT 1
#endif
// Interval is randomized on each boot in range from ..._MIN to ..._MAX (ms)
#ifndef WIFI_GRATUITOUS_ARP_INTERVAL_MIN
#define WIFI_GRATUITOUS_ARP_INTERVAL_MIN 15000
#endif
#ifndef WIFI_GRATUITOUS_ARP_INTERVAL_MAX
#define WIFI_GRATUITOUS_ARP_INTERVAL_MAX 30000
#endif
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// WEB // WEB
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------


+ 6
- 0
code/espurna/config/prototypes.h View File

@ -367,6 +367,12 @@ using wifi_callback_f = std::function<void(justwifi_messages_t code, char * para
void wifiRegister(wifi_callback_f callback); void wifiRegister(wifi_callback_f callback);
bool wifiConnected(); bool wifiConnected();
#if LWIP_VERSION_MAJOR == 1
#include <netif/etharp.h>
#else // LWIP_VERSION_MAJOR >= 2
#include <lwip/etharp.h>
#endif
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// THERMOSTAT // THERMOSTAT
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------


+ 61
- 0
code/espurna/wifi.ino View File

@ -15,6 +15,11 @@ bool _wifi_smartconfig_running = false;
bool _wifi_smartconfig_initial = false; bool _wifi_smartconfig_initial = false;
uint8_t _wifi_ap_mode = WIFI_AP_FALLBACK; uint8_t _wifi_ap_mode = WIFI_AP_FALLBACK;
#if WIFI_GRATUITOUS_ARP_SUPPORT
unsigned long _wifi_gratuitous_arp_interval = 0;
unsigned long _wifi_gratuitous_arp_last = 0;
#endif
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// PRIVATE // PRIVATE
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -91,6 +96,14 @@ void _wifiConfigure() {
sleep_mode = constrain(sleep_mode, 0, 2); sleep_mode = constrain(sleep_mode, 0, 2);
WiFi.setSleepMode(static_cast<WiFiSleepType_t>(sleep_mode)); WiFi.setSleepMode(static_cast<WiFiSleepType_t>(sleep_mode));
#if WIFI_GRATUITOUS_ARP_SUPPORT
_wifi_gratuitous_arp_last = millis();
_wifi_gratuitous_arp_interval = getSetting("wifiGarpIntvl", secureRandom(
WIFI_GRATUITOUS_ARP_INTERVAL_MIN, WIFI_GRATUITOUS_ARP_INTERVAL_MAX
)).toInt();
#endif
} }
void _wifiScan(uint32_t client_id = 0) { void _wifiScan(uint32_t client_id = 0) {
@ -504,6 +517,47 @@ void _wifiWebSocketOnAction(uint32_t client_id, const char * action, JsonObject&
#endif #endif
// -----------------------------------------------------------------------------
// SUPPORT
// -----------------------------------------------------------------------------
#if WIFI_GRATUITOUS_ARP_SUPPORT
// ref: lwip src/core/netif.c netif_issue_reports(...)
// ref: esp-lwip/core/ipv4/etharp.c garp_tmr()
// TODO: only for ipv4, need (?) a different method with ipv6
bool _wifiSendGratuitousArp() {
bool result = false;
for (netif* interface = netif_list; interface != nullptr; interface = interface->next) {
if (
(interface->flags & NETIF_FLAG_ETHARP)
&& (interface->hwaddr_len == ETHARP_HWADDR_LEN)
#if LWIP_VERSION_MAJOR == 1
&& (!ip_addr_isany(&interface->ip_addr))
#else
&& (!ip4_addr_isany_val(*netif_ip4_addr(interface)))
#endif
&& (interface->flags & NETIF_FLAG_LINK_UP)
&& (interface->flags & NETIF_FLAG_UP)
) {
etharp_gratuitous(interface);
result = true;
}
}
return result;
}
void _wifiSendGratuitousArp(unsigned long interval) {
if (millis() - _wifi_gratuitous_arp_last > interval) {
_wifi_gratuitous_arp_last = millis();
_wifiSendGratuitousArp();
}
}
#endif // WIFI_GRATUITOUS_ARP_SUPPORT
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// INFO // INFO
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -730,4 +784,11 @@ void wifiLoop() {
_wifiCheckAP(); _wifiCheckAP();
} }
#if WIFI_GRATUITOUS_ARP_SUPPORT
// Only send out gra arp when in STA mode
if (_wifi_gratuitous_arp_interval) {
_wifiSendGratuitousArp(_wifi_gratuitous_arp_interval);
}
#endif
} }

Loading…
Cancel
Save