mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-12-25 00:14:02 +00:00
tcp: handle pcb->snd_queuelen and chained pbufs during segment split (bug #52692)
This fixes a bug in tcp_split_unsent_seg() where a chained pbuf was not correctly updating pcb->snd_queuelen during trimming and snd_queuelen would desynchronize if pbuf_realloc() freed some of the chain Also, use pbuf_clen() for adding the new remaining segment rather than ++. The new remaining segment should always be one pbuf due to the semantics of PBUF_RAM, but this follows the best practice of using pbuf_clen()
This commit is contained in:
parent
f334ac68b6
commit
04b983b4f3
@ -1900,6 +1900,9 @@ tcp_split_unsent_seg(struct tcp_pcb *pcb, u16_t split)
|
||||
seg->flags |= TF_SEG_DATA_CHECKSUMMED;
|
||||
#endif /* TCP_CHECKSUM_ON_COPY */
|
||||
|
||||
/* Remove this segment from the queue since trimming it may free pbufs */
|
||||
pcb->snd_queuelen -= pbuf_clen(useg->p);
|
||||
|
||||
/* Trim the original pbuf into our split size. At this point our remainder segment must be setup
|
||||
successfully because we are modifying the original segment */
|
||||
pbuf_realloc(useg->p, useg->p->tot_len - remainder);
|
||||
@ -1910,6 +1913,9 @@ tcp_split_unsent_seg(struct tcp_pcb *pcb, u16_t split)
|
||||
useg->oversize_left = 0;
|
||||
#endif /* TCP_OVERSIZE_DBGCHECK */
|
||||
|
||||
/* Add back to the queue with new trimmed pbuf */
|
||||
pcb->snd_queuelen += pbuf_clen(useg->p);
|
||||
|
||||
#if TCP_CHECKSUM_ON_COPY
|
||||
/* The checksum on the split segment is now incorrect. We need to re-run it over the split */
|
||||
useg->chksum = 0;
|
||||
@ -1933,7 +1939,7 @@ tcp_split_unsent_seg(struct tcp_pcb *pcb, u16_t split)
|
||||
/* Update number of segments on the queues. Note that length now may
|
||||
* exceed TCP_SND_QUEUELEN! We don't have to touch pcb->snd_buf
|
||||
* because the total amount of data is constant when packet is split */
|
||||
pcb->snd_queuelen++;
|
||||
pcb->snd_queuelen += pbuf_clen(seg->p);
|
||||
|
||||
/* Finally insert remainder into queue after split (which stays head) */
|
||||
seg->next = useg->next;
|
||||
|
Loading…
Reference in New Issue
Block a user