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 <dmytrop@nvidia.com>
  • Loading branch information
pasis authored and igor-ivanov committed Oct 5, 2021
1 parent 3bedfa4 commit bcc3670
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
@@ -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;
@@ -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 */

0 comments on commit bcc3670

Please sign in to comment.