Skip to content

Commit

Permalink
issue: 2690914 Remove forced split for retransmitted TSO segment
Browse files Browse the repository at this point in the history
When a TSO segment appears in the unsent queue we split it to a set of
small segments. This leads to a data corruption in configuration of
large buffers. Probably because we can free and re-allocate pbuf which
is transmitted.

It can happen that we queue a spurious fast retransmission, split the
big TSO segment into small ones, receive ACK for part of the original
TSO segment and free few small segments as ACKed. If card still sends
the freed pbuf, it can send corrupted data since the pbuf can be
re-allocated. Also the freed pbuf must be the one which is not used for
reference tracking in cq_mgr to be freed before the TX completion.

As solution, don't split TSO segment into multiple small ones. Instead,
reset TSO flag and let tcp_split_segment() and tcp_tso_segment() handle
all scenarios. tcp_split_segment() splits a segment into 2 segments when
necessary and creates maximum possible segment. This is more optimal.

Signed-off-by: Dmytro Podgornyi <[email protected]>
  • Loading branch information
pasis authored and igor-ivanov committed Sep 29, 2021
1 parent 2d13fe4 commit 2bc5c84
Showing 1 changed file with 5 additions and 5 deletions.
10 changes: 5 additions & 5 deletions src/vma/lwip/tcp_out.c
Original file line number Diff line number Diff line change
Expand Up @@ -1154,7 +1154,7 @@ tcp_split_one_segment(struct tcp_pcb *pcb, struct tcp_seg *seg, u32_t lentosend,
* @param wnd current window size
* @return current segment to proceed
*/
static struct tcp_seg *
__attribute__((unused)) static struct tcp_seg *
tcp_rexmit_segment(struct tcp_pcb *pcb, struct tcp_seg *seg, u32_t wnd)
{
struct tcp_seg *cur_seg = NULL;
Expand Down Expand Up @@ -1538,12 +1538,12 @@ tcp_output(struct tcp_pcb *pcb)

while (seg) {
#if LWIP_TSO
/* TSO segment can be in unsent queue only in case retransmission
* The purpose of this processing is to avoid to send TSO segment
* during retransmition.
/* TSO segment can be in unsent queue only in case of retransmission.
* Clear TSO flag, tcp_split_segment() and tcp_tso_segment() will handle
* all scenarios further.
*/
if (seg->flags & TF_SEG_OPTS_TSO) {
seg = tcp_rexmit_segment(pcb, seg, wnd);
seg->flags &= ~TF_SEG_OPTS_TSO;
}
#endif /* LWIP_TSO */

Expand Down

0 comments on commit 2bc5c84

Please sign in to comment.