Ver código fonte

lwip: fix socket memory leak issue

1. Add socket memory leak debug counter
2. Fix TCP PCB leak issue
Liu Zhi Fu 9 anos atrás
pai
commit
ab92d43bc6

+ 21 - 0
components/lwip/api/lwip_debug.c

@@ -18,6 +18,8 @@
 #include "lwip/tcp.h"
 #include "lwip/udp.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_PCB_SHOW(pcb) \
@@ -127,3 +129,22 @@ void dbg_lwip_udp_rxtx_show(void)
     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
+

+ 65 - 71
components/lwip/core/tcp.c

@@ -1389,59 +1389,55 @@ tcp_kill_timewait(void)
 }
 
 #if ESP_LWIP
-/**
- * Kills the oldest connection that is in FIN_WAIT_2 state.
- * Called from tcp_alloc() if no more connections are available.
- */
-static void tcp_kill_finwait2(void)
+typedef struct {
+    u8_t time_wait;
+    u8_t closing;
+    u8_t fin_wait2;
+    u8_t last_ack;
+    u8_t listen;
+    u8_t bound;
+    u8_t total;
+}tcp_pcb_num_t;
+
+void tcp_pcb_num_cal(tcp_pcb_num_t *tcp_pcb_num)
 {
-	struct tcp_pcb *pcb, *inactive;
-	u32_t inactivity;
-	/* Go through the list of FIN_WAIT_2 pcbs and get the oldest pcb. */
-	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);
-	}
-}
+    struct tcp_pcb_listen *listen;
+    struct tcp_pcb *pcb;
 
-/**
- * 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;
-	u32_t inactivity;
-	/* Go through the list of LAST_ACK pcbs and get the oldest pcb. */
-	inactivity = 0;
-	inactive = NULL;
-	for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
-		if (pcb->state == LAST_ACK) {
-			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);
-	}
+    if (!tcp_pcb_num){
+        return;
+    }
+
+    memset(tcp_pcb_num, 0, sizeof(*tcp_pcb_num));
+    for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
+        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 ++;
+    }
+
+    for (pcb = tcp_bound_pcbs; pcb != NULL; pcb = pcb->next){
+        tcp_pcb_num->total ++;
+        tcp_pcb_num->bound ++;
+    }
 }
 #endif
 
 
-
 /**
  * Allocate a new tcp_pcb structure.
  *
@@ -1455,34 +1451,32 @@ tcp_alloc(u8_t prio)
   u32_t iss;
 
 #if ESP_LWIP
-    /*Kills the oldest connection that is in TIME_WAIT state.*/
-    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_kill_timewait();
-
-    /*Kills the oldest connection that is in FIN_WAIT_2 state.*/
-    time_wait_num = 0;
-    for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next){
-        if (pcb->state == FIN_WAIT_2)
-            time_wait_num ++;
+    tcp_pcb_num_t tcp_pcb_num;
+
+    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();
+        } else if (tcp_pcb_num.last_ack > 0){
+            tcp_kill_state(LAST_ACK);
+        } else if (tcp_pcb_num.closing > 0){
+            tcp_kill_state(CLOSING);
+        } else if (tcp_pcb_num.fin_wait2 > 0){
+            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_kill_finwait2();
-
-    /*Kills the oldest connection that is in LAST_ACK state.*/
-    time_wait_num = 0;
-    for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next){
-        if (pcb->state == LAST_ACK)
-            time_wait_num ++;
+    tcp_pcb_num_cal(&tcp_pcb_num);
+    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",
+           tcp_pcb_num.total, tcp_pcb_num.time_wait, tcp_pcb_num.last_ack, tcp_pcb_num.closing,
+           tcp_pcb_num.fin_wait2, tcp_pcb_num.listen, tcp_pcb_num.bound));
+        return NULL;
     }
 
-    if (time_wait_num >= MEMP_NUM_TCP_PCB)
-  	  tcp_kill_lastack();
 #endif
 
   pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB);

+ 2 - 1
components/lwip/core/tcp_out.c

@@ -176,7 +176,8 @@ tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno,
   struct tcp_seg *seg;
   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"));
     pbuf_free(p);
     return NULL;

+ 1 - 0
components/lwip/include/lwip/lwip/lwip_debug.h

@@ -20,5 +20,6 @@ void dbg_lwip_tcp_pcb_show(void);
 void dbg_lwip_udp_pcb_show(void);
 void dbg_lwip_tcp_rxtx_show(void);
 void dbg_lwip_udp_rxtx_show(void);
+void dbg_lwip_mem_cnt_show(void);
 
 #endif

+ 2 - 2
components/lwip/include/lwip/lwip/memp.h

@@ -71,8 +71,8 @@ extern const struct memp_desc* const memp_pools[MEMP_MAX];
 #include "lwip/mem.h"
 
 #define memp_init()
-#define memp_malloc(type)     mem_malloc(memp_pools[type]->size)
-#define memp_free(type, mem)  mem_free(mem)
+#define memp_malloc(type)     mem_malloc(memp_pools[type]->size); ESP_CNT_MEM_MALLOC_INC(type)
+#define memp_free(type, mem)  mem_free(mem); ESP_CNT_MEM_FREE_INC(type)
 
 #define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \
   const struct memp_desc memp_ ## name = { \

+ 10 - 0
components/lwip/include/lwip/lwip/priv/memp_priv.h

@@ -140,6 +140,16 @@ struct memp_desc {
 #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
 #define DECLARE_LWIP_MEMPOOL_DESC(desc) (desc),
 #else

+ 1 - 0
components/lwip/include/lwip/port/lwipopts.h

@@ -526,6 +526,7 @@ extern unsigned long os_random(void);
 #define ESP_IP4_ATON                    1
 #define ESP_LIGHT_SLEEP                 1
 #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_SND_BUF_DEFAULT                  (2*TCP_MSS)