Merge branch 'bufix/Backport_some_wifi_lwip_bugs_for_5.0_0314' into 'release/v5.0'

bufix/Backport_some_wifi_lwip_bugs_for_5.0_0314

See merge request espressif/esp-idf!22758
This commit is contained in:
Jiang Jiang Jian 2023-03-16 10:49:26 +08:00
commit 6dc6b57180
9 changed files with 165 additions and 18 deletions

View File

@ -17,9 +17,15 @@ extern "C" {
// Macros to assemble master configs with partial configs from netif, stack and driver // Macros to assemble master configs with partial configs from netif, stack and driver
// //
#ifdef CONFIG_LWIP_ESP_MLDV6_REPORT
#define ESP_NETIF_DEFAULT_MLDV6_REPORT_FLAGS (ESP_NETIF_FLAG_MLDV6_REPORT)
#else
#define ESP_NETIF_DEFAULT_MLDV6_REPORT_FLAGS (0)
#endif
#define ESP_NETIF_INHERENT_DEFAULT_WIFI_STA() \ #define ESP_NETIF_INHERENT_DEFAULT_WIFI_STA() \
{ \ { \
.flags = (esp_netif_flags_t)(ESP_NETIF_DHCP_CLIENT | ESP_NETIF_FLAG_GARP | ESP_NETIF_FLAG_EVENT_IP_MODIFIED), \ .flags = (esp_netif_flags_t)(ESP_NETIF_DHCP_CLIENT | ESP_NETIF_FLAG_GARP | ESP_NETIF_DEFAULT_MLDV6_REPORT_FLAGS | ESP_NETIF_FLAG_EVENT_IP_MODIFIED), \
ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(mac) \ ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(mac) \
ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(ip_info) \ ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(ip_info) \
.get_ip_event = IP_EVENT_STA_GOT_IP, \ .get_ip_event = IP_EVENT_STA_GOT_IP, \

View File

@ -160,6 +160,7 @@ typedef enum esp_netif_flags {
ESP_NETIF_FLAG_EVENT_IP_MODIFIED = 1 << 4, ESP_NETIF_FLAG_EVENT_IP_MODIFIED = 1 << 4,
ESP_NETIF_FLAG_IS_PPP = 1 << 5, ESP_NETIF_FLAG_IS_PPP = 1 << 5,
ESP_NETIF_FLAG_IS_BRIDGE = 1 << 6, ESP_NETIF_FLAG_IS_BRIDGE = 1 << 6,
ESP_NETIF_FLAG_MLDV6_REPORT = 1 << 7,
} esp_netif_flags_t; } esp_netif_flags_t;
typedef enum esp_netif_ip_event_type { typedef enum esp_netif_ip_event_type {

View File

@ -24,6 +24,7 @@
#include "lwip/ip_addr.h" #include "lwip/ip_addr.h"
#include "lwip/ip6_addr.h" #include "lwip/ip6_addr.h"
#include "lwip/mld6.h" #include "lwip/mld6.h"
#include "lwip/prot/mld6.h"
#include "lwip/nd6.h" #include "lwip/nd6.h"
#include "lwip/snmp.h" #include "lwip/snmp.h"
#include "lwip/priv/tcpip_priv.h" #include "lwip/priv/tcpip_priv.h"
@ -115,6 +116,8 @@ static netif_ext_callback_t netif_callback = { .callback_fn = NULL, .next = NULL
static void esp_netif_internal_dhcpc_cb(struct netif *netif); static void esp_netif_internal_dhcpc_cb(struct netif *netif);
#if LWIP_IPV6 #if LWIP_IPV6
static void esp_netif_internal_nd6_cb(struct netif *p_netif, uint8_t ip_index); static void esp_netif_internal_nd6_cb(struct netif *p_netif, uint8_t ip_index);
static void netif_set_mldv6_flag(struct netif *netif);
static void netif_unset_mldv6_flag(struct netif *netif);
#endif /* LWIP_IPV6 */ #endif /* LWIP_IPV6 */
static void netif_callback_fn(struct netif* netif, netif_nsc_reason_t reason, const netif_ext_callback_args_t* args) static void netif_callback_fn(struct netif* netif, netif_nsc_reason_t reason, const netif_ext_callback_args_t* args)
@ -709,6 +712,11 @@ static void esp_netif_lwip_remove(esp_netif_t *esp_netif)
if (esp_netif->flags & ESP_NETIF_FLAG_GARP) { if (esp_netif->flags & ESP_NETIF_FLAG_GARP) {
netif_unset_garp_flag(esp_netif->lwip_netif); netif_unset_garp_flag(esp_netif->lwip_netif);
} }
#endif
#if ESP_MLDV6_REPORT && LWIP_IPV6
if (esp_netif->flags & ESP_NETIF_FLAG_MLDV6_REPORT) {
netif_unset_mldv6_flag(esp_netif->lwip_netif);
}
#endif #endif
if (esp_netif->flags & ESP_NETIF_DHCP_CLIENT) { if (esp_netif->flags & ESP_NETIF_DHCP_CLIENT) {
dhcp_cleanup(esp_netif->lwip_netif); dhcp_cleanup(esp_netif->lwip_netif);
@ -1500,6 +1508,11 @@ static esp_err_t esp_netif_down_api(esp_netif_api_msg_t *msg)
esp_netif_reset_ip_info(esp_netif); esp_netif_reset_ip_info(esp_netif);
} }
#if CONFIG_LWIP_IPV6 #if CONFIG_LWIP_IPV6
#if ESP_MLDV6_REPORT
if (esp_netif->flags & ESP_NETIF_FLAG_MLDV6_REPORT) {
netif_unset_mldv6_flag(esp_netif->lwip_netif);
}
#endif
for(int8_t i = 0 ;i < LWIP_IPV6_NUM_ADDRESSES ;i++) { for(int8_t i = 0 ;i < LWIP_IPV6_NUM_ADDRESSES ;i++) {
netif_ip6_addr_set(lwip_netif, i, IP6_ADDR_ANY6); netif_ip6_addr_set(lwip_netif, i, IP6_ADDR_ANY6);
netif_ip6_addr_set_valid_life(lwip_netif, i, 0); netif_ip6_addr_set_valid_life(lwip_netif, i, 0);
@ -1807,6 +1820,34 @@ esp_err_t esp_netif_get_dns_info(esp_netif_t *esp_netif, esp_netif_dns_type_t ty
} }
#if CONFIG_LWIP_IPV6 #if CONFIG_LWIP_IPV6
#ifdef CONFIG_LWIP_MLDV6_TMR_INTERVAL
static void netif_send_mldv6(void *arg)
{
struct netif *netif = arg;
if (!netif_is_up(netif)) {
return;
}
mld6_report_groups(netif);
sys_timeout(CONFIG_LWIP_MLDV6_TMR_INTERVAL*1000, netif_send_mldv6, netif);
}
static void netif_set_mldv6_flag(struct netif *netif)
{
if (!netif_is_up(netif)) {
return;
}
sys_timeout(CONFIG_LWIP_MLDV6_TMR_INTERVAL*1000, netif_send_mldv6, netif);
}
static void netif_unset_mldv6_flag(struct netif *netif)
{
sys_untimeout(netif_send_mldv6, netif);
}
#endif
esp_ip6_addr_type_t esp_netif_ip6_get_addr_type(esp_ip6_addr_t* ip6_addr) esp_ip6_addr_type_t esp_netif_ip6_get_addr_type(esp_ip6_addr_t* ip6_addr)
{ {
ip6_addr_t* lwip_ip6_info = (ip6_addr_t*)ip6_addr; ip6_addr_t* lwip_ip6_info = (ip6_addr_t*)ip6_addr;
@ -1847,6 +1888,14 @@ static void esp_netif_internal_nd6_cb(struct netif *netif, uint8_t ip_index)
ip6_info.ip.zone = 0; // zero out zone, as not used in lwip ip6_info.ip.zone = 0; // zero out zone, as not used in lwip
#endif /* LWIP_IPV6_SCOPES */ #endif /* LWIP_IPV6_SCOPES */
if (esp_netif->flags&ESP_NETIF_FLAG_MLDV6_REPORT) {
#if ESP_MLDV6_REPORT
netif_set_mldv6_flag(netif);
#else
ESP_LOGW(TAG,"CONFIG_LWIP_ESP_MLDV6_REPORT not enabled, but esp-netif configured with ESP_NETIF_FLAG_MLDV6_REPORT");
#endif
}
memcpy(&evt.ip6_info, &ip6_info, sizeof(esp_netif_ip6_info_t)); memcpy(&evt.ip6_info, &ip6_info, sizeof(esp_netif_ip6_info_t));
int ret = esp_event_post(IP_EVENT, IP_EVENT_GOT_IP6, &evt, sizeof(evt), 0); int ret = esp_event_post(IP_EVENT, IP_EVENT_GOT_IP6, &evt, sizeof(evt), 0);
if (ESP_OK != ret) { if (ESP_OK != ret) {

@ -1 +1 @@
Subproject commit 88b2729cbf3e653b08c3cc9a7a59689f439f53a3 Subproject commit ae66f24c6e1596a29c73130c5407d68e46502514

View File

@ -200,6 +200,24 @@ menu "LWIP"
help help
Set the timer interval for gratuitous ARP. The default value is 60s Set the timer interval for gratuitous ARP. The default value is 60s
config LWIP_ESP_MLDV6_REPORT
bool "Send mldv6 report periodically"
depends on LWIP_IPV6
default y
help
Enable this option allows to send mldv6 report periodically.
This option solve the issue that failed to receive multicast data.
Some routers fail to forward multicast packets.
To solve this problem, send multicast mdlv6 report to routers regularly.
config LWIP_MLDV6_TMR_INTERVAL
int "mldv6 report timer interval(seconds)"
default 40
depends on LWIP_ESP_MLDV6_REPORT
help
Set the timer interval for mldv6 report. The default value is 30s
config LWIP_TCPIP_RECVMBOX_SIZE config LWIP_TCPIP_RECVMBOX_SIZE
int "TCPIP task receive mail box size" int "TCPIP task receive mail box size"
default 32 default 32
@ -257,6 +275,14 @@ menu "LWIP"
help help
Number of clients that may store data in client_data member array of struct netif. Number of clients that may store data in client_data member array of struct netif.
config LWIP_DHCP_COARSE_TIMER_SECS
int "DHCP coarse timer interval(s)"
default 1
range 1 10
help
Set DHCP coarse interval in seconds.
A higher value will be less precise but cost less power consumption.
menu "DHCP server" menu "DHCP server"
config LWIP_DHCPS config LWIP_DHCPS

View File

@ -63,6 +63,19 @@
#define DHCPS_DEBUG 0 #define DHCPS_DEBUG 0
#define DHCPS_LOG printf #define DHCPS_LOG printf
#define IS_INVALID_SUBNET_MASK(x) (((x-1) | x) != 0xFFFFFFFF)
/* Notes:
* CIDR eliminates the traditional Class A, Class B and Class C addresses.
*/
#define IP_CLASS_HOST_NUM(mask) (0xffffffff & ~mask)
#define DHCP_CHECK_SUBNET_MASK_IP(mask) \
do { \
if (IS_INVALID_SUBNET_MASK(mask)) { \
DHCPS_LOG("dhcps: Illegal subnet mask.\n"); \
return ERR_ARG; \
} \
} while (0)
#define MAX_STATION_NUM CONFIG_LWIP_DHCPS_MAX_STATION_NUM #define MAX_STATION_NUM CONFIG_LWIP_DHCPS_MAX_STATION_NUM
#define DHCPS_STATE_OFFER 1 #define DHCPS_STATE_OFFER 1
@ -1141,23 +1154,25 @@ static void handle_dhcp(void *arg,
*******************************************************************************/ *******************************************************************************/
static void dhcps_poll_set(dhcps_t *dhcps, u32_t ip) static void dhcps_poll_set(dhcps_t *dhcps, u32_t ip)
{ {
u32_t softap_ip = 0, local_ip = 0; u32_t server_ip = 0, local_ip = 0;
u32_t start_ip = 0; u32_t start_ip = 0;
u32_t end_ip = 0; u32_t end_ip = 0;
u32_t temp_local_ip = 0;
u32_t host_num = 0;
dhcps_lease_t *dhcps_poll = &dhcps->dhcps_poll; dhcps_lease_t *dhcps_poll = &dhcps->dhcps_poll;
if (dhcps_poll->enable == true) { if (dhcps_poll->enable == true) {
softap_ip = htonl(ip); server_ip = htonl(ip);
start_ip = htonl(dhcps_poll->start_ip.addr); start_ip = htonl(dhcps_poll->start_ip.addr);
end_ip = htonl(dhcps_poll->end_ip.addr); end_ip = htonl(dhcps_poll->end_ip.addr);
/*config ip information can't contain local ip*/ /*config ip information can't contain local ip*/
if ((start_ip <= softap_ip) && (softap_ip <= end_ip)) { if ((start_ip <= server_ip) && (server_ip <= end_ip)) {
dhcps_poll->enable = false; dhcps_poll->enable = false;
} else { } else {
/*config ip information must be in the same segment as the local ip*/ /*config ip information must be in the same segment as the local ip*/
softap_ip >>= 8; server_ip >>= 8;
if (((start_ip >> 8 != softap_ip) || (end_ip >> 8 != softap_ip)) if (((start_ip >> 8 != server_ip) || (end_ip >> 8 != server_ip))
|| (end_ip - start_ip > DHCPS_MAX_LEASE)) { || (end_ip - start_ip > DHCPS_MAX_LEASE)) {
dhcps_poll->enable = false; dhcps_poll->enable = false;
} }
@ -1165,19 +1180,24 @@ static void dhcps_poll_set(dhcps_t *dhcps, u32_t ip)
} }
if (dhcps_poll->enable == false) { if (dhcps_poll->enable == false) {
local_ip = softap_ip = htonl(ip); local_ip = server_ip = htonl(ip);
softap_ip &= 0xFFFFFF00; server_ip &= 0xFFFFFF00;
local_ip &= 0xFF; temp_local_ip = local_ip &= 0xFF;
if (local_ip >= 0x80) { if (local_ip >= 0x80) {
local_ip -= DHCPS_MAX_LEASE; local_ip -= DHCPS_MAX_LEASE;
temp_local_ip -= DHCPS_MAX_LEASE;
} else { } else {
local_ip ++; local_ip ++;
} }
bzero(dhcps_poll, sizeof(*dhcps_poll)); bzero(dhcps_poll, sizeof(*dhcps_poll));
dhcps_poll->start_ip.addr = softap_ip | local_ip; host_num = IP_CLASS_HOST_NUM(htonl(dhcps->dhcps_mask.addr));
dhcps_poll->end_ip.addr = softap_ip | (local_ip + DHCPS_MAX_LEASE - 1); if (host_num > DHCPS_MAX_LEASE) {
host_num = DHCPS_MAX_LEASE;
}
dhcps_poll->start_ip.addr = server_ip | local_ip;
dhcps_poll->end_ip.addr = server_ip | (temp_local_ip + host_num - 1);
dhcps_poll->start_ip.addr = htonl(dhcps_poll->start_ip.addr); dhcps_poll->start_ip.addr = htonl(dhcps_poll->start_ip.addr);
dhcps_poll->end_ip.addr = htonl(dhcps_poll->end_ip.addr); dhcps_poll->end_ip.addr = htonl(dhcps_poll->end_ip.addr);
} }
@ -1229,6 +1249,7 @@ err_t dhcps_start(dhcps_t *dhcps, struct netif *netif, ip4_addr_t ip)
IP4_ADDR(&dhcps->broadcast_dhcps, 255, 255, 255, 255); IP4_ADDR(&dhcps->broadcast_dhcps, 255, 255, 255, 255);
dhcps->server_address.addr = ip.addr; dhcps->server_address.addr = ip.addr;
DHCP_CHECK_SUBNET_MASK_IP(htonl(dhcps->dhcps_mask.addr));
dhcps_poll_set(dhcps, dhcps->server_address.addr); dhcps_poll_set(dhcps, dhcps->server_address.addr);
dhcps->client_address_plus.addr = dhcps->dhcps_poll.start_ip.addr; dhcps->client_address_plus.addr = dhcps->dhcps_poll.start_ip.addr;

@ -1 +1 @@
Subproject commit 705dd71d46779bf29653f1f1d7b1af5a09fb2aa7 Subproject commit d5e56d06658ae11292be1baea56204f7120b6fa7

View File

@ -339,7 +339,7 @@ extern "C" {
#define ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID #define ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID
#define DHCP_DEFINE_CUSTOM_TIMEOUTS 1 #define DHCP_DEFINE_CUSTOM_TIMEOUTS 1
#define DHCP_COARSE_TIMER_SECS (1) #define DHCP_COARSE_TIMER_SECS CONFIG_LWIP_DHCP_COARSE_TIMER_SECS
#define DHCP_NEXT_TIMEOUT_THRESHOLD (3) #define DHCP_NEXT_TIMEOUT_THRESHOLD (3)
/* Since for embedded devices it's not that hard to miss a discover packet, so lower /* Since for embedded devices it's not that hard to miss a discover packet, so lower
* the discover retry backoff time from (2,4,8,16,32,60,60)s to (500m,1,2,4,8,15,15)s. * the discover retry backoff time from (2,4,8,16,32,60,60)s to (500m,1,2,4,8,15,15)s.
@ -354,6 +354,7 @@ static inline uint32_t timeout_from_offered(uint32_t lease, uint32_t min)
if (timeout == 0) { if (timeout == 0) {
timeout = min; timeout = min;
} }
timeout = (timeout + DHCP_COARSE_TIMER_SECS - 1) / DHCP_COARSE_TIMER_SECS;
return timeout; return timeout;
} }
@ -1455,6 +1456,15 @@ static inline uint32_t timeout_from_offered(uint32_t lease, uint32_t min)
#define ESP_GRATUITOUS_ARP 0 #define ESP_GRATUITOUS_ARP 0
#endif #endif
/**
* ESP_MLDV6_REPORT==1: This option allows to send mldv6 report periodically.
*/
#ifdef CONFIG_LWIP_ESP_MLDV6_REPORT
#define ESP_MLDV6_REPORT 1
#else
#define ESP_MLDV6_REPORT 0
#endif
#define ESP_LWIP 1 #define ESP_LWIP 1
#define ESP_LWIP_ARP 1 #define ESP_LWIP_ARP 1
#define ESP_PER_SOC_TCP_WND 0 #define ESP_PER_SOC_TCP_WND 0

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -12,6 +12,7 @@
#include "lwip/sockets.h" #include "lwip/sockets.h"
#include "ping/ping_sock.h" #include "ping/ping_sock.h"
#include "dhcpserver/dhcpserver.h" #include "dhcpserver/dhcpserver.h"
#include "dhcpserver/dhcpserver_options.h"
#define ETH_PING_END_BIT BIT(1) #define ETH_PING_END_BIT BIT(1)
#define ETH_PING_DURATION_MS (5000) #define ETH_PING_DURATION_MS (5000)
@ -127,8 +128,9 @@ TEST_CASE("dhcp server init/deinit", "[lwip][leaks=0]")
TEST_CASE("dhcp server start/stop on localhost", "[lwip]") TEST_CASE("dhcp server start/stop on localhost", "[lwip]")
{ {
test_case_uses_tcpip(); test_case_uses_tcpip();
dhcps_t *dhcps = dhcps_new();
struct netif *netif; struct netif *netif;
dhcps_t *dhcps;
ip4_addr_t netmask;
NETIF_FOREACH(netif) { NETIF_FOREACH(netif) {
if (netif->name[0] == 'l' && netif->name[1] == 'o') { if (netif->name[0] == 'l' && netif->name[1] == 'o') {
@ -137,8 +139,40 @@ TEST_CASE("dhcp server start/stop on localhost", "[lwip]")
} }
TEST_ASSERT_NOT_NULL(netif); TEST_ASSERT_NOT_NULL(netif);
ip4_addr_t ip = { .addr = 0x7f0001 }; //Class A
TEST_ASSERT(dhcps_start(dhcps, netif, ip) == ERR_OK); dhcps = dhcps_new();
IP4_ADDR(&netmask, 255,0,0,0);
dhcps_set_option_info(dhcps, SUBNET_MASK, (void*)&netmask, sizeof(netmask));
ip4_addr_t a_ip = { .addr = 0x7f0001 };
IP4_ADDR(&netmask, 255,0,0,0);
TEST_ASSERT(dhcps_start(dhcps, netif, a_ip) == ERR_OK);
TEST_ASSERT(dhcps_stop(dhcps, netif) == ERR_OK);
dhcps_delete(dhcps);
//Class B
dhcps = dhcps_new();
IP4_ADDR(&netmask, 255,255,0,0);
dhcps_set_option_info(dhcps, SUBNET_MASK, (void*)&netmask, sizeof(netmask));
ip4_addr_t b_ip = { .addr = 0x1000080 };
TEST_ASSERT(dhcps_start(dhcps, netif, b_ip) == ERR_OK);
TEST_ASSERT(dhcps_stop(dhcps, netif) == ERR_OK);
dhcps_delete(dhcps);
//Class C
dhcps = dhcps_new();
IP4_ADDR(&netmask, 255,255,255,0);
dhcps_set_option_info(dhcps, SUBNET_MASK, (void*)&netmask, sizeof(netmask));
ip4_addr_t c_ip = { .addr = 0x101A8C0 };
TEST_ASSERT(dhcps_start(dhcps, netif, c_ip) == ERR_OK);
TEST_ASSERT(dhcps_stop(dhcps, netif) == ERR_OK);
dhcps_delete(dhcps);
// Class A: IP: 127.0.0.1, with inaccurate Mask: 255.248.255.0
// expect dhcps_start() to fail
dhcps = dhcps_new();
IP4_ADDR(&netmask, 255,248,255,0);
dhcps_set_option_info(dhcps, SUBNET_MASK, (void*)&netmask, sizeof(netmask));
TEST_ASSERT(dhcps_start(dhcps, netif, a_ip) == ERR_ARG);
TEST_ASSERT(dhcps_stop(dhcps, netif) == ERR_OK); TEST_ASSERT(dhcps_stop(dhcps, netif) == ERR_OK);
dhcps_delete(dhcps); dhcps_delete(dhcps);
} }