diff --git a/components/drivers/wlan/dev_wlan_lwip.c b/components/drivers/wlan/dev_wlan_lwip.c index 21f43c115b40..7857e1dc8c25 100644 --- a/components/drivers/wlan/dev_wlan_lwip.c +++ b/components/drivers/wlan/dev_wlan_lwip.c @@ -18,6 +18,8 @@ #ifdef RT_USING_LWIP #include +#include +#include #include #ifdef LWIP_USING_DHCPD #include @@ -357,6 +359,37 @@ static rt_err_t rt_wlan_lwip_protocol_recv(struct rt_wlan_device *wlan, void *bu #endif } +rt_err_t rt_wlan_lwip_direct_input(struct rt_wlan_device *wlan, struct pbuf *p) +{ + struct lwip_prot_des *lwip_prot; + struct netif *netif; + err_t result; + + /* The caller must already be in the lwIP core context. */ + if (wlan == RT_NULL || p == RT_NULL || wlan->prot == RT_NULL) + { + return -RT_EINVAL; + } + + lwip_prot = (struct lwip_prot_des *)wlan->prot; + netif = lwip_prot->eth.netif; + if (netif == RT_NULL) + { + return -RT_ERROR; + } + +#if LWIP_ETHERNET + if (netif->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) + { + result = ethernet_input(p, netif); + } + else +#endif + result = ip_input(p, netif); + + return result == ERR_OK ? RT_EOK : -RT_ERROR; +} + static rt_err_t rt_wlan_lwip_protocol_send(rt_device_t device, struct pbuf *p) { struct rt_wlan_device *wlan = ((struct eth_device *)device)->parent.user_data; @@ -370,20 +403,20 @@ static rt_err_t rt_wlan_lwip_protocol_send(rt_device_t device, struct pbuf *p) #ifdef RT_WLAN_PROT_LWIP_PBUF_FORCE { - rt_wlan_prot_transfer_dev(wlan, p, p->tot_len); - return RT_EOK; + return rt_wlan_prot_transfer_dev(wlan, p, p->tot_len); } #else { rt_uint8_t *frame; + rt_err_t result; /* sending data directly */ if (p->len == p->tot_len) { frame = (rt_uint8_t *)p->payload; - rt_wlan_prot_transfer_dev(wlan, frame, p->tot_len); + result = rt_wlan_prot_transfer_dev(wlan, frame, p->tot_len); LOG_D("F:%s L:%d run len:%d", __FUNCTION__, __LINE__, p->tot_len); - return RT_EOK; + return result; } frame = rt_malloc(p->tot_len); if (frame == RT_NULL) @@ -394,10 +427,10 @@ static rt_err_t rt_wlan_lwip_protocol_send(rt_device_t device, struct pbuf *p) /*copy pbuf -> data dat*/ pbuf_copy_partial(p, frame, p->tot_len, 0); /* send data */ - rt_wlan_prot_transfer_dev(wlan, frame, p->tot_len); + result = rt_wlan_prot_transfer_dev(wlan, frame, p->tot_len); LOG_D("F:%s L:%d run len:%d", __FUNCTION__, __LINE__, p->tot_len); rt_free(frame); - return RT_EOK; + return result; } #endif } diff --git a/components/drivers/wlan/dev_wlan_mgnt.c b/components/drivers/wlan/dev_wlan_mgnt.c index b5cb3959db93..bdb5e952c8fd 100644 --- a/components/drivers/wlan/dev_wlan_mgnt.c +++ b/components/drivers/wlan/dev_wlan_mgnt.c @@ -467,6 +467,7 @@ static void rt_wlan_event_dispatch(struct rt_wlan_device *device, rt_wlan_dev_ev { RT_WLAN_LOG_D("event: DISCONNECT"); _sta_mgnt.state &= ~RT_WLAN_STATE_CONNECT; + _sta_mgnt.state &= ~RT_WLAN_STATE_CONNECTING; _sta_mgnt.state &= ~RT_WLAN_STATE_READY; user_event = RT_WLAN_EVT_STA_DISCONNECTED; user_buff.data = &_sta_mgnt.info; @@ -1073,6 +1074,7 @@ rt_err_t rt_wlan_disconnect(void) /* run disconnect */ MGNT_LOCK(); + TIME_STOP(); /* create event wait complete */ complete = rt_wlan_complete_create("disc"); if (complete == RT_NULL) @@ -1101,6 +1103,7 @@ rt_err_t rt_wlan_disconnect(void) MGNT_UNLOCK(); return -RT_ERROR; } + TIME_STOP(); RT_WLAN_LOG_I("disconnect success!"); MGNT_UNLOCK(); return err; @@ -1228,10 +1231,27 @@ int rt_wlan_get_rssi(void) return rssi; } +static rt_bool_t rt_wlan_ap_config_matches(const struct rt_wlan_info *info, + const char *password, int password_len) +{ + return (_ap_mgnt.info.ssid.len == info->ssid.len) && + (_ap_mgnt.info.security == info->security) && + (_ap_mgnt.info.channel == info->channel) && + (_ap_mgnt.info.hidden == info->hidden) && + (_ap_mgnt.key.len == password_len) && + (rt_memcmp(&_ap_mgnt.info.ssid.val[0], &info->ssid.val[0], + info->ssid.len) == 0) && + ((password_len == 0) || + (rt_memcmp(&_ap_mgnt.key.val[0], password, password_len) == 0)); +} + rt_err_t rt_wlan_start_ap(const char *ssid, const char *password) { rt_err_t err = RT_EOK; int ssid_len = 0; + int password_len = 0; + rt_bool_t ap_active; + rt_bool_t same_config; struct rt_wlan_info info; struct rt_wlan_complete_des *complete; rt_uint32_t set = 0, recved = 0; @@ -1247,11 +1267,18 @@ rt_err_t rt_wlan_start_ap(const char *ssid, const char *password) if (password) { info.security = SECURITY_WPA2_AES_PSK; + password_len = rt_strlen(password); } ssid_len = rt_strlen(ssid); if (ssid_len > RT_WLAN_SSID_MAX_LENGTH) { RT_WLAN_LOG_E("ssid is to long! len:%d", ssid_len); + return -RT_EINVAL; + } + if (password_len > RT_WLAN_PASSWORD_MAX_LENGTH) + { + RT_WLAN_LOG_E("key is to long! len:%d", password_len); + return -RT_EINVAL; } /* copy info */ @@ -1260,6 +1287,28 @@ rt_err_t rt_wlan_start_ap(const char *ssid, const char *password) info.channel = 6; info.band = RT_802_11_BAND_2_4GHZ; + /* A repeated request needs no new AP_START event. A changed request must + * stop the active AP first; otherwise drivers correctly reject it busy. */ + MGNT_LOCK(); + ap_active = rt_wlan_ap_is_active(); + same_config = ap_active && + rt_wlan_ap_config_matches(&info, password, password_len); + MGNT_UNLOCK(); + if (same_config) + { + RT_WLAN_LOG_I("ap already started with requested configuration"); + return RT_EOK; + } + if (ap_active) + { + err = rt_wlan_ap_stop(); + if (err != RT_EOK) + { + RT_WLAN_LOG_E("failed to stop active ap: %d", err); + return err; + } + } + /* Initializing events that need to wait */ MGNT_LOCK(); /* create event wait complete */ @@ -1322,13 +1371,7 @@ rt_err_t rt_wlan_start_ap_adv(struct rt_wlan_info *info, const char *password) MGNT_LOCK(); if (rt_wlan_ap_is_active()) { - if ((_ap_mgnt.info.ssid.len == info->ssid.len) && - (_ap_mgnt.info.security == info->security) && - (_ap_mgnt.info.channel == info->channel) && - (_ap_mgnt.info.hidden == info->hidden) && - (_ap_mgnt.key.len == password_len) && - (rt_memcmp(&_ap_mgnt.info.ssid.val[0], &info->ssid.val[0], info->ssid.len) == 0) && - (rt_memcmp(&_ap_mgnt.key.val[0], password, password_len))) + if (rt_wlan_ap_config_matches(info, password, password_len)) { RT_WLAN_LOG_D("wifi Already Start"); MGNT_UNLOCK(); @@ -1343,7 +1386,11 @@ rt_err_t rt_wlan_start_ap_adv(struct rt_wlan_info *info, const char *password) return err; } rt_memcpy(&_ap_mgnt.info, info, sizeof(struct rt_wlan_info)); - rt_memcpy(&_ap_mgnt.key.val, password, password_len); + rt_memset(&_ap_mgnt.key, 0, sizeof(_ap_mgnt.key)); + if (password_len > 0) + { + rt_memcpy(&_ap_mgnt.key.val, password, password_len); + } _ap_mgnt.key.len = password_len; MGNT_UNLOCK(); diff --git a/components/drivers/wlan/dev_wlan_prot.h b/components/drivers/wlan/dev_wlan_prot.h index 3ba1daa9fd14..810c8ed66fad 100644 --- a/components/drivers/wlan/dev_wlan_prot.h +++ b/components/drivers/wlan/dev_wlan_prot.h @@ -38,6 +38,7 @@ typedef enum } rt_wlan_prot_event_t; struct rt_wlan_prot; +struct pbuf; struct rt_wlan_prot_ops { rt_err_t (*prot_recv)(struct rt_wlan_device *wlan, void *buff, int len); @@ -68,6 +69,9 @@ rt_err_t rt_wlan_prot_transfer_dev(struct rt_wlan_device *wlan, void *buff, int rt_err_t rt_wlan_dev_transfer_prot(struct rt_wlan_device *wlan, void *buff, int len); +/* Submit an RX pbuf from lwIP core context; lwIP owns it on success. */ +rt_err_t rt_wlan_lwip_direct_input(struct rt_wlan_device *wlan, struct pbuf *p); + rt_err_t rt_wlan_prot_event_register(struct rt_wlan_prot *prot, rt_wlan_prot_event_t event, rt_wlan_prot_event_handler handler); rt_err_t rt_wlan_prot_event_unregister(struct rt_wlan_prot *prot, rt_wlan_prot_event_t event); diff --git a/components/net/lwip-dhcpd/dhcp_server_raw.c b/components/net/lwip-dhcpd/dhcp_server_raw.c index b271ce36b95d..2e18966151fe 100644 --- a/components/net/lwip-dhcpd/dhcp_server_raw.c +++ b/components/net/lwip-dhcpd/dhcp_server_raw.c @@ -577,7 +577,6 @@ dhcp_server_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t break; } node_prev = node; - node = node->next; } if (node != NULL) @@ -615,6 +614,7 @@ err_t dhcp_server_start(struct netif *netif, ip4_addr_t *start, ip4_addr_t *end) { struct dhcp_server *dhcp_server; + err_t err; /* If this netif alreday use the dhcp server. */ for (dhcp_server = lw_dhcp_server; dhcp_server != NULL; dhcp_server = dhcp_server->next) @@ -640,9 +640,6 @@ dhcp_server_start(struct netif *netif, ip4_addr_t *start, ip4_addr_t *end) /* clear data structure */ memset(dhcp_server, 0, sizeof(struct dhcp_server)); - /* store this dhcp server to list */ - dhcp_server->next = lw_dhcp_server; - lw_dhcp_server = dhcp_server; dhcp_server->netif = netif; dhcp_server->node_list = NULL; dhcp_server->start = *start; @@ -654,15 +651,27 @@ dhcp_server_start(struct netif *netif, ip4_addr_t *start, ip4_addr_t *end) if (dhcp_server->pcb == NULL) { LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_server_start(): could not obtain pcb\n")); + mem_free(dhcp_server); return ERR_MEM; } ip_set_option(dhcp_server->pcb, SOF_BROADCAST); /* set up local and remote port for the pcb */ - udp_bind(dhcp_server->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT); + err = udp_bind(dhcp_server->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT); + if (err != ERR_OK) + { + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_server_start(): could not bind pcb, err=%d\n", (int)err)); + udp_remove(dhcp_server->pcb); + mem_free(dhcp_server); + return err; + } //udp_connect(dhcp_server->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); /* set up the recv callback and argument */ udp_recv(dhcp_server->pcb, dhcp_server_recv, dhcp_server); + + /* Publish the server only after all resources are ready. */ + dhcp_server->next = lw_dhcp_server; + lw_dhcp_server = dhcp_server; LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_server_start(): starting DHCP server\n")); return ERR_OK; @@ -742,7 +751,7 @@ void dhcpd_start(const char *netif_name) res = dhcp_server_start(netif, &ip_start, &ip_end); if (res != 0) { - DEBUG_PRINTF("dhcp_server_start res: %s.\r\n", res); + DEBUG_PRINTF("dhcp_server_start res: %d.\r\n", (int)res); } } diff --git a/components/net/lwip/lwip-2.1.2/src/core/pbuf.c b/components/net/lwip/lwip-2.1.2/src/core/pbuf.c index a209e0ca8fce..40071728e42a 100644 --- a/components/net/lwip/lwip-2.1.2/src/core/pbuf.c +++ b/components/net/lwip/lwip-2.1.2/src/core/pbuf.c @@ -271,7 +271,10 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) break; } case PBUF_RAM: { - u16_t payload_len = (u16_t)(LWIP_MEM_ALIGN_SIZE(offset) + LWIP_MEM_ALIGN_SIZE(length)); + mem_size_t payload_len = (mem_size_t)(LWIP_MEM_ALIGN_SIZE(offset) + LWIP_MEM_ALIGN_SIZE(length)); +#if PBUF_PAYLOAD_MARGIN_LEN > 0 + payload_len += LWIP_MEM_ALIGN_SIZE(PBUF_PAYLOAD_MARGIN_LEN); +#endif mem_size_t alloc_len = (mem_size_t)(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF) + payload_len); /* bug #50040: Check for integer overflow when calculating alloc_len */ @@ -440,9 +443,31 @@ pbuf_realloc(struct pbuf *p, u16_t new_len) && ((q->flags & PBUF_FLAG_IS_CUSTOM) == 0) #endif /* LWIP_SUPPORT_CUSTOM_PBUF */ ) { - /* reallocate and adjust the length of the pbuf that will be split */ - q = (struct pbuf *)mem_trim(q, (mem_size_t)(((u8_t *)q->payload - (u8_t *)q) + rem_len)); - LWIP_ASSERT("mem_trim returned q == NULL", q != NULL); + size_t trim_len = (size_t)((u8_t *)q->payload - (u8_t *)q); +#if PBUF_PAYLOAD_MARGIN_LEN > 0 + size_t margin_len = LWIP_MEM_ALIGN_SIZE((size_t)PBUF_PAYLOAD_MARGIN_LEN); +#endif + /* Keep the original allocation if the aligned trim size would wrap. */ + int trim_size_ok = (size_t)rem_len <= (size_t)-1 - trim_len; +#if PBUF_PAYLOAD_MARGIN_LEN > 0 + trim_size_ok = trim_size_ok && + margin_len <= (size_t)-1 - trim_len - rem_len; +#endif + if (trim_size_ok) { + trim_len += rem_len; +#if PBUF_PAYLOAD_MARGIN_LEN > 0 + trim_len += margin_len; +#endif + if (trim_len <= (size_t)((mem_size_t)-1) - (MEM_ALIGNMENT - 1U)) { + struct pbuf *trimmed; + /* reallocate and adjust the length of the pbuf that will be split */ + trimmed = (struct pbuf *)mem_trim(q, (mem_size_t)trim_len); + LWIP_ASSERT("mem_trim returned q == NULL", trimmed != NULL); + if (trimmed != NULL) { + q = trimmed; + } + } + } } /* adjust length fields for new last pbuf */ q->len = rem_len; diff --git a/components/net/lwip/port/lwipopts.h b/components/net/lwip/port/lwipopts.h index 424430c6657e..7d29d79b6bf9 100644 --- a/components/net/lwip/port/lwipopts.h +++ b/components/net/lwip/port/lwipopts.h @@ -282,14 +282,21 @@ //#define MEM_LIBC_MALLOC 1 //#define MEM_USE_POOLS 1 //#define MEMP_USE_CUSTOM_POOLS 1 -//#define MEM_SIZE (1024*64) + +#ifdef RT_LWIP_MEM_SIZE +#define MEM_SIZE RT_LWIP_MEM_SIZE +#endif #define MEMP_MEM_MALLOC 0 /* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application sends a lot of data out of ROM (or other static memory), this should be set high. */ +#ifdef RT_LWIP_PBUF_STRUCT_NUM +#define MEMP_NUM_PBUF RT_LWIP_PBUF_STRUCT_NUM +#else #define MEMP_NUM_PBUF 32 //16 +#endif /* the number of struct netconns */ #ifdef RT_MEMP_NUM_NETCONN @@ -323,17 +330,44 @@ * setting in the lwip opts.h */ /* MEMP_NUM_NETBUF: the number of struct netbufs. */ -// #define MEMP_NUM_NETBUF 2 +#ifdef RT_LWIP_MEMP_NUM_NETBUF +#define MEMP_NUM_NETBUF RT_LWIP_MEMP_NUM_NETBUF +#endif /* MEMP_NUM_NETCONN: the number of struct netconns. */ // #define MEMP_NUM_NETCONN 4 /* MEMP_NUM_TCPIP_MSG_*: the number of struct tcpip_msg, which is used for sequential API communication and incoming packets. Used in src/api/tcpip.c. */ -// #define MEMP_NUM_TCPIP_MSG_API 16 -// #define MEMP_NUM_TCPIP_MSG_INPKT 16 +#ifdef RT_LWIP_TCPIP_MSG_API_NUM +#define MEMP_NUM_TCPIP_MSG_API RT_LWIP_TCPIP_MSG_API_NUM +#endif +#ifdef RT_LWIP_TCPIP_MSG_INPKT_NUM +#define MEMP_NUM_TCPIP_MSG_INPKT RT_LWIP_TCPIP_MSG_INPKT_NUM +#endif /* ---------- Pbuf options ---------- */ + +/* Optional driver-reserved space before and after a PBUF_RAM payload. */ +#ifdef RT_LWIP_PBUF_LINK_ENCAPSULATION_HLEN +#define PBUF_LINK_ENCAPSULATION_HLEN RT_LWIP_PBUF_LINK_ENCAPSULATION_HLEN +#endif + +#ifdef RT_LWIP_PBUF_PAYLOAD_MARGIN_LEN +#define PBUF_PAYLOAD_MARGIN_LEN RT_LWIP_PBUF_PAYLOAD_MARGIN_LEN +#else +#define PBUF_PAYLOAD_MARGIN_LEN 0 +#endif + +/* Only the bundled lwIP 2.1.2 implements PBUF_RAM tailroom allocation. */ +#if PBUF_PAYLOAD_MARGIN_LEN != 0 && !defined(RT_USING_LWIP212) +#error "PBUF_PAYLOAD_MARGIN_LEN requires the bundled lwIP 2.1.2 (RT_USING_LWIP212)" +#endif + +#ifdef RT_LWIP_NETIF_TX_SINGLE_PBUF +#define LWIP_NETIF_TX_SINGLE_PBUF 1 +#endif + /* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ #ifdef RT_LWIP_PBUF_NUM #define PBUF_POOL_SIZE RT_LWIP_PBUF_NUM @@ -415,7 +449,11 @@ #define TCPIP_THREAD_STACKSIZE 4096 #endif #define TCPIP_THREAD_NAME "tcpip" +#ifdef RT_LWIP_TCP_RECVMBOX_SIZE +#define DEFAULT_TCP_RECVMBOX_SIZE RT_LWIP_TCP_RECVMBOX_SIZE +#else #define DEFAULT_TCP_RECVMBOX_SIZE 10 +#endif /* ---------- ARP options ---------- */ #define LWIP_ARP 1 @@ -490,7 +528,11 @@ #define LWIP_UDPLITE 0 #define UDP_TTL 255 +#ifdef RT_LWIP_UDP_RECVMBOX_SIZE +#define DEFAULT_UDP_RECVMBOX_SIZE RT_LWIP_UDP_RECVMBOX_SIZE +#else #define DEFAULT_UDP_RECVMBOX_SIZE 1 +#endif /* ---------- RAW options ---------- */ #ifdef RT_LWIP_RAW