From 9abbb581c544bb1dec64357208137ebbadd8fde5 Mon Sep 17 00:00:00 2001 From: goldsimon Date: Sun, 1 Jul 2007 15:56:04 +0000 Subject: [PATCH] Changed tcp_pcb->snd_queuelen from u8_t to u16_t to prevent overflowing when sending many small packets with big send buffer, added assertions and oveflow checks for snd_queuelen. --- src/core/tcp_in.c | 3 +++ src/core/tcp_out.c | 11 +++++------ src/include/lwip/tcp.h | 7 ++++--- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index 4f68a92a..e6fb13a8 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -513,6 +513,7 @@ tcp_process(struct tcp_pcb *pcb) pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */ pcb->state = ESTABLISHED; pcb->cwnd = pcb->mss; + LWIP_ASSERT("pcb->snd_queuelen > 0", (pcb->snd_queuelen > 0)); --pcb->snd_queuelen; LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen)); rseg = pcb->unacked; @@ -790,6 +791,7 @@ tcp_receive(struct tcp_pcb *pcb) pcb->unacked = pcb->unacked->next; LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); + LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); pcb->snd_queuelen -= pbuf_clen(next->p); tcp_seg_free(next); @@ -828,6 +830,7 @@ tcp_receive(struct tcp_pcb *pcb) next = pcb->unsent; pcb->unsent = pcb->unsent->next; LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); + LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); pcb->snd_queuelen -= pbuf_clen(next->p); tcp_seg_free(next); LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen)); diff --git a/src/core/tcp_out.c b/src/core/tcp_out.c index 98e8f4f2..8daa3d6f 100644 --- a/src/core/tcp_out.c +++ b/src/core/tcp_out.c @@ -133,7 +133,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len, u32_t seqno; u16_t left, seglen; void *ptr; - u8_t queuelen; + u16_t queuelen; LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%"U16_F", flags=%"X16_F", copy=%"U16_F")\n", (void *)pcb, arg, len, (u16_t)flags, (u16_t)copy)); @@ -158,8 +158,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len, /* If total number of pbufs on the unsent/unacked queues exceeds the * configured maximum, return an error */ queuelen = pcb->snd_queuelen; - /* check for configured max queuelen and possible overflow of u8_t */ - if ((queuelen >= TCP_SND_QUEUELEN) || (queuelen > 253)) { + /* check for configured max queuelen and possible overflow */ + if ((queuelen >= TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN)); TCP_STATS_INC(tcp.memerr); return ERR_MEM; @@ -261,9 +261,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len, } /* Now that there are more segments queued, we check again if the - length of the queue exceeds the configured maximum. */ - /* check for configured max queuelen and possible overflow of u8_t */ - if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > 253)) { + length of the queue exceeds the configured maximum or overflows. */ + if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) { LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN)); goto memerr; } diff --git a/src/include/lwip/tcp.h b/src/include/lwip/tcp.h index 668800ad..c3724ba9 100644 --- a/src/include/lwip/tcp.h +++ b/src/include/lwip/tcp.h @@ -118,8 +118,8 @@ void tcp_rexmit_rto (struct tcp_pcb *pcb); * unacknowledged. */ #define tcp_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \ - ((tpcb)->flags & TF_NODELAY) || \ - (((tpcb)->unsent != NULL) && ((tpcb)->unsent->next != NULL))) ? \ + ((tpcb)->flags & TF_NODELAY) || \ + (((tpcb)->unsent != NULL) && ((tpcb)->unsent->next != NULL))) ? \ tcp_output(tpcb) : ERR_OK) @@ -302,7 +302,8 @@ struct tcp_pcb { u16_t acked; u16_t snd_buf; /* Available buffer space for sending (in bytes). */ - u8_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */ +#define TCP_SNDQUEUELEN_OVERFLOW (0xffff-3) + u16_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */ /* These are ordered by sequence number: */