lwip: fix socket memory leak issue
1. Add socket memory leak debug counter 2. Fix TCP PCB leak issue
This commit is contained in:
parent
139fdcb9ec
commit
ab92d43bc6
7 changed files with 102 additions and 74 deletions
|
@ -18,6 +18,8 @@
|
||||||
#include "lwip/tcp.h"
|
#include "lwip/tcp.h"
|
||||||
#include "lwip/udp.h"
|
#include "lwip/udp.h"
|
||||||
#include "lwip/priv/tcp_priv.h"
|
#include "lwip/priv/tcp_priv.h"
|
||||||
|
#include "lwip/priv/memp_priv.h"
|
||||||
|
#include "lwip/memp.h"
|
||||||
|
|
||||||
#define DBG_LWIP_IP_SHOW(info, ip) printf("%s type=%d ip=%x\n", (info), (ip).type, (ip).u_addr.ip4.addr)
|
#define DBG_LWIP_IP_SHOW(info, ip) printf("%s type=%d ip=%x\n", (info), (ip).type, (ip).u_addr.ip4.addr)
|
||||||
#define DBG_LWIP_IP_PCB_SHOW(pcb) \
|
#define DBG_LWIP_IP_PCB_SHOW(pcb) \
|
||||||
|
@ -127,3 +129,22 @@ void dbg_lwip_udp_rxtx_show(void)
|
||||||
printf("TBC\n");
|
printf("TBC\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (ESP_CNT_DEBUG == 1)
|
||||||
|
|
||||||
|
uint32_t g_lwip_mem_cnt[MEMP_MAX][2];
|
||||||
|
extern const struct memp_desc * const memp_pools[MEMP_MAX];
|
||||||
|
|
||||||
|
void dbg_lwip_cnt_show(void)
|
||||||
|
{
|
||||||
|
int i=0;
|
||||||
|
|
||||||
|
printf("-----lwip memory counter-----\n");
|
||||||
|
printf("%6s %8s %8s\n", "index", "alloc", "free");
|
||||||
|
for (i=0; i<MEMP_MAX; i++){
|
||||||
|
printf("%6u %8u %8u\n", i, g_lwip_mem_cnt[i][0], g_lwip_mem_cnt[i][1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1389,59 +1389,55 @@ tcp_kill_timewait(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ESP_LWIP
|
#if ESP_LWIP
|
||||||
/**
|
typedef struct {
|
||||||
* Kills the oldest connection that is in FIN_WAIT_2 state.
|
u8_t time_wait;
|
||||||
* Called from tcp_alloc() if no more connections are available.
|
u8_t closing;
|
||||||
*/
|
u8_t fin_wait2;
|
||||||
static void tcp_kill_finwait2(void)
|
u8_t last_ack;
|
||||||
{
|
u8_t listen;
|
||||||
struct tcp_pcb *pcb, *inactive;
|
u8_t bound;
|
||||||
u32_t inactivity;
|
u8_t total;
|
||||||
/* Go through the list of FIN_WAIT_2 pcbs and get the oldest pcb. */
|
}tcp_pcb_num_t;
|
||||||
inactivity = 0;
|
|
||||||
inactive = NULL;
|
|
||||||
for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
|
|
||||||
if (pcb->state == FIN_WAIT_2) {
|
|
||||||
if ((u32_t) (tcp_ticks - pcb->tmr) >= inactivity) {
|
|
||||||
inactivity = tcp_ticks - pcb->tmr;
|
|
||||||
inactive = pcb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (inactive != NULL) {
|
|
||||||
tcp_pcb_remove(&tcp_active_pcbs, inactive);
|
|
||||||
memp_free(MEMP_TCP_PCB, inactive);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
void tcp_pcb_num_cal(tcp_pcb_num_t *tcp_pcb_num)
|
||||||
* Kills the oldest connection that is in LAST_ACK state.
|
|
||||||
* Called from tcp_alloc() if no more connections are available.
|
|
||||||
*/
|
|
||||||
static void tcp_kill_lastack(void)
|
|
||||||
{
|
{
|
||||||
struct tcp_pcb *pcb, *inactive;
|
struct tcp_pcb_listen *listen;
|
||||||
u32_t inactivity;
|
struct tcp_pcb *pcb;
|
||||||
/* Go through the list of LAST_ACK pcbs and get the oldest pcb. */
|
|
||||||
inactivity = 0;
|
if (!tcp_pcb_num){
|
||||||
inactive = NULL;
|
return;
|
||||||
for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
|
}
|
||||||
if (pcb->state == LAST_ACK) {
|
|
||||||
if ((u32_t) (tcp_ticks - pcb->tmr) >= inactivity) {
|
memset(tcp_pcb_num, 0, sizeof(*tcp_pcb_num));
|
||||||
inactivity = tcp_ticks - pcb->tmr;
|
for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||||
inactive = pcb;
|
tcp_pcb_num->total ++;
|
||||||
|
tcp_pcb_num->time_wait ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next){
|
||||||
|
tcp_pcb_num->total ++;
|
||||||
|
if (pcb->state == FIN_WAIT_2){
|
||||||
|
tcp_pcb_num->fin_wait2 ++;
|
||||||
|
} else if (pcb->state == LAST_ACK) {
|
||||||
|
tcp_pcb_num->last_ack ++;
|
||||||
|
} else if (pcb->state == CLOSING) {
|
||||||
|
tcp_pcb_num->closing ++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (pcb = tcp_listen_pcbs.listen_pcbs; pcb != NULL; pcb = pcb->next){
|
||||||
|
tcp_pcb_num->total ++;
|
||||||
|
tcp_pcb_num->listen ++;
|
||||||
}
|
}
|
||||||
if (inactive != NULL) {
|
|
||||||
tcp_pcb_remove(&tcp_active_pcbs, inactive);
|
for (pcb = tcp_bound_pcbs; pcb != NULL; pcb = pcb->next){
|
||||||
memp_free(MEMP_TCP_PCB, inactive);
|
tcp_pcb_num->total ++;
|
||||||
|
tcp_pcb_num->bound ++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate a new tcp_pcb structure.
|
* Allocate a new tcp_pcb structure.
|
||||||
*
|
*
|
||||||
|
@ -1455,34 +1451,32 @@ tcp_alloc(u8_t prio)
|
||||||
u32_t iss;
|
u32_t iss;
|
||||||
|
|
||||||
#if ESP_LWIP
|
#if ESP_LWIP
|
||||||
/*Kills the oldest connection that is in TIME_WAIT state.*/
|
tcp_pcb_num_t tcp_pcb_num;
|
||||||
u8_t time_wait_num = 0;
|
|
||||||
for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
|
|
||||||
time_wait_num ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (time_wait_num >= MEMP_NUM_TCP_PCB)
|
tcp_pcb_num_cal(&tcp_pcb_num);
|
||||||
|
|
||||||
|
if (tcp_pcb_num.total >= MEMP_NUM_TCP_PCB){
|
||||||
|
if (tcp_pcb_num.time_wait > 0){
|
||||||
tcp_kill_timewait();
|
tcp_kill_timewait();
|
||||||
|
} else if (tcp_pcb_num.last_ack > 0){
|
||||||
/*Kills the oldest connection that is in FIN_WAIT_2 state.*/
|
tcp_kill_state(LAST_ACK);
|
||||||
time_wait_num = 0;
|
} else if (tcp_pcb_num.closing > 0){
|
||||||
for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next){
|
tcp_kill_state(CLOSING);
|
||||||
if (pcb->state == FIN_WAIT_2)
|
} else if (tcp_pcb_num.fin_wait2 > 0){
|
||||||
time_wait_num ++;
|
tcp_kill_state(FIN_WAIT_2);//TODO check whether we have issue here?????
|
||||||
|
} else {
|
||||||
|
tcp_kill_prio(prio);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (time_wait_num >= MEMP_NUM_TCP_PCB)
|
tcp_pcb_num_cal(&tcp_pcb_num);
|
||||||
tcp_kill_finwait2();
|
if (tcp_pcb_num.total >= MEMP_NUM_TCP_PCB){
|
||||||
|
LWIP_DEBUGF(TCP_DEBUG, ("tcp_alloc: no available tcp pcb %d %d %d %d %d %d %d\n",
|
||||||
/*Kills the oldest connection that is in LAST_ACK state.*/
|
tcp_pcb_num.total, tcp_pcb_num.time_wait, tcp_pcb_num.last_ack, tcp_pcb_num.closing,
|
||||||
time_wait_num = 0;
|
tcp_pcb_num.fin_wait2, tcp_pcb_num.listen, tcp_pcb_num.bound));
|
||||||
for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next){
|
return NULL;
|
||||||
if (pcb->state == LAST_ACK)
|
|
||||||
time_wait_num ++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (time_wait_num >= MEMP_NUM_TCP_PCB)
|
|
||||||
tcp_kill_lastack();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB);
|
pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB);
|
||||||
|
|
|
@ -176,7 +176,8 @@ tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno,
|
||||||
struct tcp_seg *seg;
|
struct tcp_seg *seg;
|
||||||
u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags);
|
u8_t optlen = LWIP_TCP_OPT_LENGTH(optflags);
|
||||||
|
|
||||||
if ((seg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG)) == NULL) {
|
seg = (struct tcp_seg *)memp_malloc(MEMP_TCP_SEG);
|
||||||
|
if (seg == NULL) {
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_create_segment: no memory.\n"));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_create_segment: no memory.\n"));
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -20,5 +20,6 @@ void dbg_lwip_tcp_pcb_show(void);
|
||||||
void dbg_lwip_udp_pcb_show(void);
|
void dbg_lwip_udp_pcb_show(void);
|
||||||
void dbg_lwip_tcp_rxtx_show(void);
|
void dbg_lwip_tcp_rxtx_show(void);
|
||||||
void dbg_lwip_udp_rxtx_show(void);
|
void dbg_lwip_udp_rxtx_show(void);
|
||||||
|
void dbg_lwip_mem_cnt_show(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -71,8 +71,8 @@ extern const struct memp_desc* const memp_pools[MEMP_MAX];
|
||||||
#include "lwip/mem.h"
|
#include "lwip/mem.h"
|
||||||
|
|
||||||
#define memp_init()
|
#define memp_init()
|
||||||
#define memp_malloc(type) mem_malloc(memp_pools[type]->size)
|
#define memp_malloc(type) mem_malloc(memp_pools[type]->size); ESP_CNT_MEM_MALLOC_INC(type)
|
||||||
#define memp_free(type, mem) mem_free(mem)
|
#define memp_free(type, mem) mem_free(mem); ESP_CNT_MEM_FREE_INC(type)
|
||||||
|
|
||||||
#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \
|
#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \
|
||||||
const struct memp_desc memp_ ## name = { \
|
const struct memp_desc memp_ ## name = { \
|
||||||
|
|
|
@ -140,6 +140,16 @@ struct memp_desc {
|
||||||
#endif /* MEMP_MEM_MALLOC */
|
#endif /* MEMP_MEM_MALLOC */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if (ESP_CNT_DEBUG == 1)
|
||||||
|
extern uint32_t g_lwip_mem_cnt[MEMP_MAX][2];
|
||||||
|
#define ESP_CNT_MEM_MALLOC_INC(type) g_lwip_mem_cnt[type][0]++
|
||||||
|
#define ESP_CNT_MEM_FREE_INC(type) g_lwip_mem_cnt[type][1]++
|
||||||
|
#else
|
||||||
|
#define ESP_CNT_MEM_MALLOC_INC(type)
|
||||||
|
#define ESP_CNT_MEM_FREE_INC(type)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef LWIP_DEBUG
|
#ifdef LWIP_DEBUG
|
||||||
#define DECLARE_LWIP_MEMPOOL_DESC(desc) (desc),
|
#define DECLARE_LWIP_MEMPOOL_DESC(desc) (desc),
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -526,6 +526,7 @@ extern unsigned long os_random(void);
|
||||||
#define ESP_IP4_ATON 1
|
#define ESP_IP4_ATON 1
|
||||||
#define ESP_LIGHT_SLEEP 1
|
#define ESP_LIGHT_SLEEP 1
|
||||||
#define ESP_L2_TO_L3_COPY CONFIG_L2_TO_L3_COPY
|
#define ESP_L2_TO_L3_COPY CONFIG_L2_TO_L3_COPY
|
||||||
|
#define ESP_CNT_DEBUG 0
|
||||||
|
|
||||||
#define TCP_WND_DEFAULT (4*TCP_MSS)
|
#define TCP_WND_DEFAULT (4*TCP_MSS)
|
||||||
#define TCP_SND_BUF_DEFAULT (2*TCP_MSS)
|
#define TCP_SND_BUF_DEFAULT (2*TCP_MSS)
|
||||||
|
|
Loading…
Reference in a new issue