Skip to content

WiFi: ARP gratuitous API for wifi station mode #6889

New issue

Have a question about this project? No Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “No Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? No Sign in to your account

Merged
merged 20 commits into from
Apr 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions libraries/ESP8266WiFi/keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ PublicKey KEYWORD1
CertStoreSPIFFSBearSSL KEYWORD1
CertStoreSDBearSSL KEYWORD1
Session KEYWORD1
ESP8266WiFiGratuitous KEYWORD1


#######################################
Expand Down Expand Up @@ -108,6 +109,9 @@ psk KEYWORD2
BSSID KEYWORD2
BSSIDstr KEYWORD2
RSSI KEYWORD2
stationKeepAliveSetIntervalMs KEYWORD2
stationKeepAliveStop KEYWORD2
stationKeepAliveNow KEYWORD2
enableInsecureWEP KEYWORD2
getListenInterval KEYWORD2
isSleepLevelMax KEYWORD2
Expand Down
94 changes: 94 additions & 0 deletions libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
ESP8266WiFiGratuitous.cpp - esp8266 Wifi support
copyright esp8266/arduino

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

extern "C"
{
#include "lwip/init.h" // LWIP_VERSION_*
#if LWIP_VERSION_MAJOR == 1
#include "netif/wlan_lwip_if.h" // eagle_lwip_getif()
#include "netif/etharp.h" // gratuitous arp
#include "user_interface.h"
#else
#include "lwip/etharp.h" // gratuitous arp
#endif
} // extern "C"

#include <Schedule.h>

#include "ESP8266WiFiGratuitous.h"

namespace experimental
{

ETSTimer* ESP8266WiFiGratuitous::_timer = nullptr;

void ESP8266WiFiGratuitous::stationKeepAliveNow ()
{
for (netif* interface = netif_list; interface != nullptr; interface = interface->next)
if (
(interface->flags & NETIF_FLAG_LINK_UP)
&& (interface->flags & NETIF_FLAG_UP)
#if LWIP_VERSION_MAJOR == 1
&& interface == eagle_lwip_getif(STATION_IF) /* lwip1 does not set if->num properly */
&& (!ip_addr_isany(&interface->ip_addr))
#else
&& interface->num == STATION_IF
&& (!ip4_addr_isany_val(*netif_ip4_addr(interface)))
#endif
)
{
etharp_gratuitous(interface);
break;
}
}

void ESP8266WiFiGratuitous::scheduleItForNextYieldOnce (void*)
{
schedule_recurrent_function_us([]()
{
ESP8266WiFiGratuitous::stationKeepAliveNow();
return false;
}, 0);
}

bool ESP8266WiFiGratuitous::stationKeepAliveSetIntervalMs (uint32_t ms)
{
if (_timer)
{
os_timer_disarm(_timer);
_timer = nullptr;
}

if (ms)
{
// send one now
stationKeepAliveNow();

_timer = (ETSTimer*)malloc(sizeof(ETSTimer));
if (_timer == nullptr)
return false;

os_timer_setfn(_timer, ESP8266WiFiGratuitous::scheduleItForNextYieldOnce, nullptr);
os_timer_arm(_timer, ms, true);
}

return true;
}

}; // experimental::
54 changes: 54 additions & 0 deletions libraries/ESP8266WiFi/src/ESP8266WiFiGratuitous.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
ESP8266WiFiGratuitous.h - esp8266 Wifi support
copyright esp8266/arduino

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifndef ESP8266WIFIGRATUITOUS_H_
#define ESP8266WIFIGRATUITOUS_H_

#include <stdint.h> // uint32_t
#include <ets_sys.h> // ETSTimer

namespace experimental
{

class ESP8266WiFiGratuitous
{
public:

// disable(0) or enable/update automatic sending of Gratuitous ARP packets.
// A gratuitous ARP packet is immediately sent when calling this function, then
// based on a time interval in milliseconds, default = 1s
// return value: true when started, false otherwise
static bool stationKeepAliveSetIntervalMs (uint32_t ms = 1000);

// request for stopping arp gratuitous packets
static void stationKeepAliveStop () { (void)stationKeepAliveSetIntervalMs(0); }

// immediately send one gratuitous ARP from STA
static void stationKeepAliveNow ();

protected:

static void scheduleItForNextYieldOnce (void*);

static ETSTimer* _timer;
};

}; // experimental::

#endif // ESP8266WIFIGRATUITOUS_H_
2 changes: 1 addition & 1 deletion libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ static bool sta_config_equal(const station_config& lhs, const station_config& rh
return false;
}
}

if(lhs.threshold.rssi != rhs.threshold.rssi) {
return false;
}
Expand Down
4 changes: 2 additions & 2 deletions libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ class ESP8266WiFiSTAClass {
wl_status_t begin(const String& ssid, const String& passphrase = emptyString, int32_t channel = 0, const uint8_t* bssid = NULL, bool connect = true);
wl_status_t begin();

//The argument order for ESP is not the same as for Arduino. However, there is compatibility code under the hood
//to detect Arduino arg order, and handle it correctly. Be aware that the Arduino default value handling doesn't
//The argument order for ESP is not the same as for Arduino. However, there is compatibility code under the hood
//to detect Arduino arg order, and handle it correctly. Be aware that the Arduino default value handling doesn't
//work here (see Arduino docs for gway/subnet defaults). In other words: at least 3 args must always be given.
bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = (uint32_t)0x00000000, IPAddress dns2 = (uint32_t)0x00000000);

Expand Down
19 changes: 19 additions & 0 deletions libraries/Ticker/src/Ticker.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,75 +35,94 @@ class Ticker
typedef void (*callback_with_arg_t)(void*);
typedef std::function<void(void)> callback_function_t;

// callback will be called at following loop() after ticker fires
void attach_scheduled(float seconds, callback_function_t callback)
{
_callback_function = [callback]() { schedule_function(callback); };
_attach_ms(1000UL * seconds, true);
}

// callback will be called in SYS ctx when ticker fires
void attach(float seconds, callback_function_t callback)
{
_callback_function = std::move(callback);
_attach_ms(1000UL * seconds, true);
}

// callback will be called at following loop() after ticker fires
void attach_ms_scheduled(uint32_t milliseconds, callback_function_t callback)
{
_callback_function = [callback]() { schedule_function(callback); };
_attach_ms(milliseconds, true);
}

// callback will be called at following yield() after ticker fires
void attach_ms_scheduled_accurate(uint32_t milliseconds, callback_function_t callback)
{
_callback_function = [callback]() { schedule_recurrent_function_us([callback]() { callback(); return false; }, 0); };
_attach_ms(milliseconds, true);
}

// callback will be called in SYS ctx when ticker fires
void attach_ms(uint32_t milliseconds, callback_function_t callback)
{
_callback_function = std::move(callback);
_attach_ms(milliseconds, true);
}

// callback will be called in SYS ctx when ticker fires
template<typename TArg>
void attach(float seconds, void (*callback)(TArg), TArg arg)
{
static_assert(sizeof(TArg) <= sizeof(void*), "attach() callback argument size must be <= sizeof(void*)");
_attach_ms(1000UL * seconds, true, reinterpret_cast<callback_with_arg_t>(callback), reinterpret_cast<void*>(arg));
}

// callback will be called in SYS ctx when ticker fires
template<typename TArg>
void attach_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg)
{
static_assert(sizeof(TArg) <= sizeof(void*), "attach() callback argument size must be <= sizeof(void*)");
_attach_ms(milliseconds, true, reinterpret_cast<callback_with_arg_t>(callback), reinterpret_cast<void*>(arg));
}

// callback will be called at following loop() after ticker fires
void once_scheduled(float seconds, callback_function_t callback)
{
_callback_function = [callback]() { schedule_function(callback); };
_attach_ms(1000UL * seconds, false);
}

// callback will be called in SYS ctx when ticker fires
void once(float seconds, callback_function_t callback)
{
_callback_function = std::move(callback);
_attach_ms(1000UL * seconds, false);
}

// callback will be called at following loop() after ticker fires
void once_ms_scheduled(uint32_t milliseconds, callback_function_t callback)
{
_callback_function = [callback]() { schedule_function(callback); };
_attach_ms(milliseconds, false);
}

// callback will be called in SYS ctx when ticker fires
void once_ms(uint32_t milliseconds, callback_function_t callback)
{
_callback_function = std::move(callback);
_attach_ms(milliseconds, false);
}

// callback will be called in SYS ctx when ticker fires
template<typename TArg>
void once(float seconds, void (*callback)(TArg), TArg arg)
{
static_assert(sizeof(TArg) <= sizeof(void*), "attach() callback argument size must be <= sizeof(void*)");
_attach_ms(1000UL * seconds, false, reinterpret_cast<callback_with_arg_t>(callback), reinterpret_cast<void*>(arg));
}

// callback will be called in SYS ctx when ticker fires
template<typename TArg>
void once_ms(uint32_t milliseconds, void (*callback)(TArg), TArg arg)
{
Expand Down
7 changes: 7 additions & 0 deletions tests/host/common/MocklwIP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,11 @@ const ip_addr_t* sntp_getserver(u8_t)
return IP_ADDR_ANY;
}

err_t etharp_request(struct netif *netif, const ip4_addr_t *ipaddr)
{
(void)netif;
(void)ipaddr;
return ERR_OK;
}

} // extern "C"