Skip to content

Commit

Permalink
Test: etharp_gratuitous (#1877)
Browse files Browse the repository at this point in the history
* 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...
  • Loading branch information
mcspr authored Aug 30, 2019
1 parent c123156 commit 35ce687
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 0 deletions.
19 changes: 19 additions & 0 deletions code/espurna/config/general.h
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,25 @@
#define WIFI_PROPAGATION_CONST 4 // This is typically something between 2.7 to 4.3 (free space is 2)
#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
// -----------------------------------------------------------------------------
Expand Down
6 changes: 6 additions & 0 deletions code/espurna/config/prototypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,12 @@ using wifi_callback_f = std::function<void(justwifi_messages_t code, char * para
void wifiRegister(wifi_callback_f callback);
bool wifiConnected();

#if LWIP_VERSION_MAJOR == 1
#include <netif/etharp.h>
#else // LWIP_VERSION_MAJOR >= 2
#include <lwip/etharp.h>
#endif

// -----------------------------------------------------------------------------
// THERMOSTAT
// -----------------------------------------------------------------------------
Expand Down
61 changes: 61 additions & 0 deletions code/espurna/wifi.ino
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ bool _wifi_smartconfig_running = false;
bool _wifi_smartconfig_initial = false;
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
// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -91,6 +96,14 @@ void _wifiConfigure() {
sleep_mode = constrain(sleep_mode, 0, 2);

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) {
Expand Down Expand Up @@ -504,6 +517,47 @@ void _wifiWebSocketOnAction(uint32_t client_id, const char * action, JsonObject&

#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
// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -730,4 +784,11 @@ void wifiLoop() {
_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

}

0 comments on commit 35ce687

Please sign in to comment.