Skip to content

Commit 9b87551

Browse files
author
Arun S
committed
Remove ethernet interface logic for SoftAP and STA
Issue: The problem is that there is a race condition introduced in that the LWIP thread is relying on the interface as it is taken down by a application thread while calling disconnect. In disconnect api called from application context, whd_emac_wifi_link_state_changed() will refer to netif interface structure in its callback api netif_link_irq(netif). This netif will be cleared by remove_etherent_interface(). whd_emac_wifi_link_state_changed will post message to tcpip_thread. tcpip_thread will process the message and call the callback api netif_link_irq(netif) Calling sequence is whd_emac_wifi_link_state_changed -> remove_etherent_interface(). Hence there is a timing issue that netif might be cleared first before tcpip thread process the message netif_link_irq(netif) Fix: remove_etherent_interface() will post message to tcpip thread and tcpip: thread process the message delete_interface() which will actually remove the inferface from the netif_list. Calling sequence is whd_emac_wifi_link_state_changed() message post -> remove_etherent_interface() message post. message processing order netif_link_irq(netif) -> delete_interface(). Since both the processing is handled in single thread, processing of message is handled sequentially.
1 parent 565ab14 commit 9b87551

File tree

5 files changed

+82
-0
lines changed

5 files changed

+82
-0
lines changed

features/lwipstack/LWIPInterface.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,11 @@ LWIP::Interface::Interface() :
494494
attr.cb_mem = &has_any_addr_sem;
495495
attr.cb_size = sizeof has_any_addr_sem;
496496
has_any_addr = osSemaphoreNew(UINT16_MAX, 0, &attr);
497+
498+
attr.cb_mem = &remove_interface_sem;
499+
attr.cb_size = sizeof remove_interface_sem;
500+
remove_interface = osSemaphoreNew(UINT16_MAX, 0, &attr);
501+
497502
#if PREF_ADDR_TIMEOUT
498503
attr.cb_mem = &has_pref_addr_sem;
499504
attr.cb_size = sizeof has_pref_addr_sem;
@@ -565,6 +570,49 @@ nsapi_error_t LWIP::add_ethernet_interface(EMAC &emac, bool default_if, OnboardN
565570
#endif //LWIP_ETHERNET
566571
}
567572

573+
void LWIP::Interface::delete_interface(OnboardNetworkStack::Interface **interface_out)
574+
{
575+
#if LWIP_ETHERNET
576+
if ((interface_out != NULL) && (*interface_out != NULL)) {
577+
LWIP::Interface *lwip = static_cast<Interface *>(*interface_out);
578+
LWIP::Interface *node = lwip->list;
579+
580+
if (lwip->list != NULL) {
581+
if (lwip->list == lwip) {
582+
583+
lwip->list = lwip->list->next;
584+
netif_remove(&node->netif);
585+
*interface_out = NULL;
586+
delete node;
587+
} else {
588+
while (node->next != NULL && node->next != lwip) {
589+
node = node->next;
590+
}
591+
if (node->next != NULL && node->next == lwip) {
592+
Interface *remove = node->next;
593+
node->next = node->next->next;
594+
netif_remove(&remove->netif);
595+
*interface_out = NULL;
596+
delete remove;
597+
}
598+
}
599+
}
600+
osSemaphoreRelease(lwip->remove_interface);
601+
}
602+
#endif
603+
}
604+
605+
nsapi_error_t LWIP::remove_ethernet_interface(OnboardNetworkStack::Interface **interface_out)
606+
{
607+
#if LWIP_ETHERNET
608+
LWIP::Interface *lwip = static_cast<Interface *>(*interface_out);
609+
tcpip_callback_with_block((tcpip_callback_fn)&LWIP::Interface::delete_interface, interface_out, 1);
610+
osSemaphoreAcquire(lwip->remove_interface, osWaitForever);
611+
return NSAPI_ERROR_OK;
612+
#else
613+
return NSAPI_ERROR_UNSUPPORTED;
614+
#endif //LWIP_ETHERNET
615+
}
568616

569617
nsapi_error_t LWIP::add_l3ip_interface(L3IP &l3ip, bool default_if, OnboardNetworkStack::Interface **interface_out)
570618
{

features/lwipstack/LWIPStack.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ class LWIP : public OnboardNetworkStack, private mbed::NonCopyable<LWIP> {
149149
static void netif_link_irq(struct netif *netif);
150150
static void netif_status_irq(struct netif *netif);
151151
static Interface *our_if_from_netif(struct netif *netif);
152+
static void delete_interface(OnboardNetworkStack::Interface **interface_out);
152153

153154
#if LWIP_ETHERNET
154155
static err_t emac_low_level_output(struct netif *netif, struct pbuf *p);
@@ -208,6 +209,8 @@ class LWIP : public OnboardNetworkStack, private mbed::NonCopyable<LWIP> {
208209
void *hw; /**< alternative implementation pointer - used for PPP */
209210
};
210211

212+
mbed_rtos_storage_semaphore_t remove_interface_sem;
213+
osSemaphoreId_t remove_interface;
211214
mbed_rtos_storage_semaphore_t linked_sem;
212215
osSemaphoreId_t linked;
213216
mbed_rtos_storage_semaphore_t unlinked_sem;
@@ -282,6 +285,14 @@ class LWIP : public OnboardNetworkStack, private mbed::NonCopyable<LWIP> {
282285
*/
283286
virtual nsapi_error_t add_ppp_interface(PPP &ppp, bool default_if, OnboardNetworkStack::Interface **interface_out);
284287

288+
/** Remove a network interface from IP stack
289+
*
290+
* Removes layer 3 IP objects,network interface from stack list .
291+
* @param[out] interface_out pointer to stack interface object controlling the EMAC
292+
* @return NSAPI_ERROR_OK on success, or error code
293+
*/
294+
nsapi_error_t remove_ethernet_interface(OnboardNetworkStack::Interface **interface_out) override;
295+
285296
/** Remove a network interface from IP stack
286297
*
287298
* Removes layer 3 IP objects,network interface from stack list, and shutdown device driver .

features/netsocket/OnboardNetworkStack.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,11 @@ class OnboardNetworkStack : public NetworkStack {
169169
return NSAPI_ERROR_UNSUPPORTED;
170170
};
171171

172+
virtual nsapi_error_t remove_ethernet_interface(Interface **interface_out)
173+
{
174+
return NSAPI_ERROR_OK;
175+
};
176+
172177
virtual nsapi_error_t remove_l3ip_interface(Interface **interface_out)
173178
{
174179
return NSAPI_ERROR_OK;

features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/WhdSTAInterface.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,15 @@ nsapi_error_t WhdSTAInterface::disconnect()
359359
}
360360
whd_emac_wifi_link_state_changed(_whd_emac.ifp, WHD_FALSE);
361361

362+
// remove the interface added in connect
363+
if (_interface) {
364+
nsapi_error_t err = _stack.remove_ethernet_interface(&_interface);
365+
if (err != NSAPI_ERROR_OK) {
366+
return err;
367+
}
368+
_iface_shared.iface_sta = NULL;
369+
}
370+
362371
res = whd_wifi_deregister_event_handler(_whd_emac.ifp, sta_link_update_entry);
363372
if (res != WHD_SUCCESS) {
364373
return whd_toerror(res);

features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/WhdSoftAPInterface.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,15 @@ int WhdSoftAPInterface::stop(void)
201201
if (res != WHD_SUCCESS) {
202202
return whd_toerror(res);
203203
}
204+
205+
// remove the interface added in start
206+
if (_interface) {
207+
nsapi_error_t err = _stack.remove_ethernet_interface(&_interface);
208+
if (err != NSAPI_ERROR_OK) {
209+
return err;
210+
}
211+
_iface_shared.iface_softap = NULL;
212+
}
204213
return NSAPI_ERROR_OK;
205214
}
206215

0 commit comments

Comments
 (0)