forked from espressif/esp-idf
Merge branch 'bugfix/add_tx_flowcontrol' into 'master'
lwip: add socket tx flow control This fix is used to solve wifi q full issue: 1. When wifi tx q is full, set tx_enable to false 2. When wifi tx q decrease 1/2 max length, set tx_enable to true again 3. esp_wifi_tx_enable return whether tx_enable is true 4. If esp_wifi_tx_enable return false, socket will be blocked See merge request !62
This commit is contained in:
@@ -388,19 +388,30 @@ static void lwip_socket_drop_registered_memberships(int s);
|
|||||||
#endif /* LWIP_IGMP */
|
#endif /* LWIP_IGMP */
|
||||||
|
|
||||||
#ifdef LWIP_ESP8266
|
#ifdef LWIP_ESP8266
|
||||||
extern size_t system_get_free_heap_size(void);
|
|
||||||
|
|
||||||
#define DELAY_WHEN_MEMORY_NOT_ENOUGH() \
|
/* Since esp_wifi_tx_is_stop/system_get_free_heap_size are not an public wifi API, so extern them here*/
|
||||||
do{\
|
extern size_t system_get_free_heap_size(void);
|
||||||
uint8_t _wait_delay = 0;\
|
extern bool esp_wifi_tx_is_stop(void);
|
||||||
while (system_get_free_heap_size() < HEAP_HIGHWAT){\
|
|
||||||
vTaskDelay(_wait_delay/portTICK_RATE_MS);\
|
/* Please be notified that this flow control is just a workaround for fixing wifi Q full issue.
|
||||||
if (_wait_delay < 64) _wait_delay *= 2;\
|
* Under UDP/TCP pressure test, we found that the sockets may cause wifi tx queue full if the socket
|
||||||
}\
|
* sending speed is faster than the wifi sending speed, it will finally cause the packet to be dropped
|
||||||
}while(0)
|
* in wifi layer, it's not acceptable in some application. That's why we introdue the tx flow control here.
|
||||||
|
* However, current solution is just a workaround, we need to consider the return value of wifi tx interface,
|
||||||
|
* and feedback the return value to lwip and let lwip do the flow control itself.
|
||||||
|
*/
|
||||||
|
static inline void esp32_tx_flow_ctrl(void)
|
||||||
|
{
|
||||||
|
uint8_t _wait_delay = 0;
|
||||||
|
|
||||||
|
while ((system_get_free_heap_size() < HEAP_HIGHWAT) || esp_wifi_tx_is_stop()){
|
||||||
|
vTaskDelay(_wait_delay/portTICK_RATE_MS);
|
||||||
|
if (_wait_delay < 64) _wait_delay *= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define DELAY_WHEN_MEMORY_NOT_ENOUGH()
|
#define esp32_tx_flow_ctrl()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** The global array of available sockets */
|
/** The global array of available sockets */
|
||||||
@@ -1219,7 +1230,7 @@ lwip_send(int s, const void *data, size_t size, int flags)
|
|||||||
#endif /* (LWIP_UDP || LWIP_RAW) */
|
#endif /* (LWIP_UDP || LWIP_RAW) */
|
||||||
}
|
}
|
||||||
|
|
||||||
DELAY_WHEN_MEMORY_NOT_ENOUGH();
|
esp32_tx_flow_ctrl();
|
||||||
|
|
||||||
write_flags = NETCONN_COPY |
|
write_flags = NETCONN_COPY |
|
||||||
((flags & MSG_MORE) ? NETCONN_MORE : 0) |
|
((flags & MSG_MORE) ? NETCONN_MORE : 0) |
|
||||||
@@ -1402,7 +1413,7 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
|
|||||||
#endif /* LWIP_TCP */
|
#endif /* LWIP_TCP */
|
||||||
}
|
}
|
||||||
|
|
||||||
DELAY_WHEN_MEMORY_NOT_ENOUGH();
|
esp32_tx_flow_ctrl();
|
||||||
|
|
||||||
if ((to != NULL) && !SOCK_ADDR_TYPE_MATCH(to, sock)) {
|
if ((to != NULL) && !SOCK_ADDR_TYPE_MATCH(to, sock)) {
|
||||||
/* sockaddr does not match socket type (IPv4/IPv6) */
|
/* sockaddr does not match socket type (IPv4/IPv6) */
|
||||||
|
@@ -68,7 +68,5 @@ void sys_delay_ms(uint32_t ms);
|
|||||||
sys_sem_t* sys_thread_sem_init(void);
|
sys_sem_t* sys_thread_sem_init(void);
|
||||||
void sys_thread_sem_deinit(void);
|
void sys_thread_sem_deinit(void);
|
||||||
sys_sem_t* sys_thread_sem_get(void);
|
sys_sem_t* sys_thread_sem_get(void);
|
||||||
|
|
||||||
|
|
||||||
#endif /* __SYS_ARCH_H__ */
|
#endif /* __SYS_ARCH_H__ */
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user