mirror of
https://git.savannah.nongnu.org/git/lwip.git
synced 2025-08-04 13:34:38 +08:00
Fixed some issues in the TCP_OVERSIZE code:
- reset tcp_pcb.unsent_oversize when last_unsent is changed; - added TCP_OVERSIZE_DBGCHECK: check tcp_pcb.unsent_oversize vs. (debug-only) tcp_seg.oversize_left to ensure the pcb counter is correct; - fixed a memory leak in tcp_write;
This commit is contained in:
parent
90c7d3aaff
commit
097e8c8eb4
@ -1344,6 +1344,9 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
|
|||||||
tcp_segs_free(pcb->unsent);
|
tcp_segs_free(pcb->unsent);
|
||||||
tcp_segs_free(pcb->unacked);
|
tcp_segs_free(pcb->unacked);
|
||||||
pcb->unacked = pcb->unsent = NULL;
|
pcb->unacked = pcb->unsent = NULL;
|
||||||
|
#if TCP_OVERSIZE
|
||||||
|
pcb->unsent_oversize = 0;
|
||||||
|
#endif /* TCP_OVERSIZE */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,6 +147,9 @@ tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno,
|
|||||||
seg->p = p;
|
seg->p = p;
|
||||||
seg->dataptr = p->payload;
|
seg->dataptr = p->payload;
|
||||||
seg->len = p->tot_len - optlen;
|
seg->len = p->tot_len - optlen;
|
||||||
|
#if TCP_OVERSIZE_DBGCHECK
|
||||||
|
seg->oversize_left = 0;
|
||||||
|
#endif /* TCP_OVERSIZE_DBGCHECK */
|
||||||
|
|
||||||
/* build TCP header */
|
/* build TCP header */
|
||||||
if (pbuf_header(p, TCP_HLEN)) {
|
if (pbuf_header(p, TCP_HLEN)) {
|
||||||
@ -355,11 +358,16 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
|
|||||||
* function.
|
* function.
|
||||||
*/
|
*/
|
||||||
#if TCP_OVERSIZE
|
#if TCP_OVERSIZE
|
||||||
|
#if TCP_OVERSIZE_DBGCHECK
|
||||||
|
/* check that pcb->unsent_oversize matches last_unsent->unsent_oversize */
|
||||||
|
LWIP_ASSERT("unsent_oversize mismatch (pcb vs. last_unsent)",
|
||||||
|
pcb->unsent_oversize == last_unsent->oversize_left);
|
||||||
|
#endif /* TCP_OVERSIZE_DBGCHECK */
|
||||||
oversize = pcb->unsent_oversize;
|
oversize = pcb->unsent_oversize;
|
||||||
if (oversize > 0) {
|
if (oversize > 0) {
|
||||||
|
LWIP_ASSERT("inconsistent oversize vs. space", oversize_used <= space);
|
||||||
seg = last_unsent;
|
seg = last_unsent;
|
||||||
oversize_used = oversize < len ? oversize : len;
|
oversize_used = oversize < len ? oversize : len;
|
||||||
LWIP_ASSERT("inconsistent oversize vs. space", oversize_used <= space);
|
|
||||||
pos += oversize_used;
|
pos += oversize_used;
|
||||||
oversize -= oversize_used;
|
oversize -= oversize_used;
|
||||||
space -= oversize_used;
|
space -= oversize_used;
|
||||||
@ -390,6 +398,9 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
|
|||||||
seglen));
|
seglen));
|
||||||
goto memerr;
|
goto memerr;
|
||||||
}
|
}
|
||||||
|
#if TCP_OVERSIZE_DBGCHECK
|
||||||
|
last_unsent->oversize_left = oversize;
|
||||||
|
#endif /* TCP_OVERSIZE_DBGCHECK */
|
||||||
MEMCPY(concat_p->payload, (u8_t*)arg + pos, seglen);
|
MEMCPY(concat_p->payload, (u8_t*)arg + pos, seglen);
|
||||||
} else {
|
} else {
|
||||||
/* Data is not copied */
|
/* Data is not copied */
|
||||||
@ -404,6 +415,9 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
|
|||||||
pos += seglen;
|
pos += seglen;
|
||||||
queuelen += pbuf_clen(concat_p);
|
queuelen += pbuf_clen(concat_p);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
LWIP_ASSERT("unsent_oversize mismatch (pcb->unsent is NULL)",
|
||||||
|
pcb->unsent_oversize == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -435,6 +449,7 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
|
|||||||
* party) we can safely use PBUF_ROM instead of PBUF_REF here.
|
* party) we can safely use PBUF_ROM instead of PBUF_REF here.
|
||||||
*/
|
*/
|
||||||
struct pbuf *p2;
|
struct pbuf *p2;
|
||||||
|
LWIP_ASSERT("oversize == 0", oversize == 0);
|
||||||
if ((p2 = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) {
|
if ((p2 = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) {
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: could not allocate memory for zero-copy pbuf\n"));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: could not allocate memory for zero-copy pbuf\n"));
|
||||||
goto memerr;
|
goto memerr;
|
||||||
@ -461,12 +476,16 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
|
|||||||
* overflows. */
|
* overflows. */
|
||||||
if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
|
if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {
|
||||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
|
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_write: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
|
||||||
|
pbuf_free(p);
|
||||||
goto memerr;
|
goto memerr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) {
|
if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) {
|
||||||
goto memerr;
|
goto memerr;
|
||||||
}
|
}
|
||||||
|
#if TCP_OVERSIZE_DBGCHECK
|
||||||
|
seg->oversize_left = oversize;
|
||||||
|
#endif /* TCP_OVERSIZE_DBGCHECK */
|
||||||
/* Fix dataptr for the nocopy case */
|
/* Fix dataptr for the nocopy case */
|
||||||
if ((apiflags & TCP_WRITE_FLAG_COPY) == 0) {
|
if ((apiflags & TCP_WRITE_FLAG_COPY) == 0) {
|
||||||
seg->dataptr = (u8_t*)arg + pos;
|
seg->dataptr = (u8_t*)arg + pos;
|
||||||
@ -511,6 +530,9 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
last_unsent->len += oversize_used;
|
last_unsent->len += oversize_used;
|
||||||
|
#if TCP_OVERSIZE_DBGCHECK
|
||||||
|
last_unsent->oversize_left -= oversize_used;
|
||||||
|
#endif /* TCP_OVERSIZE_DBGCHECK */
|
||||||
}
|
}
|
||||||
pcb->unsent_oversize = oversize;
|
pcb->unsent_oversize = oversize;
|
||||||
#endif /* TCP_OVERSIZE */
|
#endif /* TCP_OVERSIZE */
|
||||||
@ -889,6 +911,12 @@ tcp_output(struct tcp_pcb *pcb)
|
|||||||
}
|
}
|
||||||
seg = pcb->unsent;
|
seg = pcb->unsent;
|
||||||
}
|
}
|
||||||
|
#if TCP_OVERSIZE
|
||||||
|
if (pcb->unsent == NULL) {
|
||||||
|
/* last unsent has been removed, reset unsent_oversize */
|
||||||
|
pcb->unsent_oversize = 0;
|
||||||
|
}
|
||||||
|
#endif /* TCP_OVERSIZE */
|
||||||
|
|
||||||
if (seg != NULL && pcb->persist_backoff == 0 &&
|
if (seg != NULL && pcb->persist_backoff == 0 &&
|
||||||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > pcb->snd_wnd) {
|
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > pcb->snd_wnd) {
|
||||||
|
@ -253,12 +253,23 @@ PACK_STRUCT_END
|
|||||||
|
|
||||||
#endif /* LWIP_EVENT_API */
|
#endif /* LWIP_EVENT_API */
|
||||||
|
|
||||||
|
#if TCP_OVERSIZE && defined(LWIP_DEBUG)
|
||||||
|
#define TCP_OVERSIZE_DBGCHECK 1
|
||||||
|
#else
|
||||||
|
#define TCP_OVERSIZE_DBGCHECK 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/* This structure represents a TCP segment on the unsent and unacked queues */
|
/* This structure represents a TCP segment on the unsent and unacked queues */
|
||||||
struct tcp_seg {
|
struct tcp_seg {
|
||||||
struct tcp_seg *next; /* used when putting segements on a queue */
|
struct tcp_seg *next; /* used when putting segements on a queue */
|
||||||
struct pbuf *p; /* buffer containing data + TCP header */
|
struct pbuf *p; /* buffer containing data + TCP header */
|
||||||
void *dataptr; /* pointer to the TCP data in the pbuf */
|
void *dataptr; /* pointer to the TCP data in the pbuf */
|
||||||
u16_t len; /* the TCP length of this segment */
|
u16_t len; /* the TCP length of this segment */
|
||||||
|
#if TCP_OVERSIZE_DBGCHECK
|
||||||
|
u16_t oversize_left; /* Extra bytes available at the end of the last
|
||||||
|
pbuf in unsent (used for asserting vs.
|
||||||
|
tcp_pcb.unsent_oversized only) */
|
||||||
|
#endif /* TCP_OVERSIZE_DBGCHECK */
|
||||||
u8_t flags;
|
u8_t flags;
|
||||||
#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */
|
#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */
|
||||||
#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */
|
#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user