diff options
author | Mithun Iyer <iyerm@google.com> | 2020-06-03 08:48:23 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2020-06-03 08:49:49 -0700 |
commit | 162848e129e50e25c3bb9c5fdc337584b3531da0 (patch) | |
tree | b48ecea3dcd0e920ed6237cf8fc4b61659d46e89 /pkg | |
parent | e6334e81ca8d951e56f03d8ea0629e3c85556cf1 (diff) |
Avoid TCP segment split when out of sender window.
If the entire segment cannot be accommodated in the receiver advertised
window and if there are still unacknowledged pending segments, skip
splitting the segment. The segment transmit would get retried by the
retransmit handler.
PiperOrigin-RevId: 314538523
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/tcpip/transport/tcp/snd.go | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/pkg/tcpip/transport/tcp/snd.go b/pkg/tcpip/transport/tcp/snd.go index 06dc9b7d7..3a19c4468 100644 --- a/pkg/tcpip/transport/tcp/snd.go +++ b/pkg/tcpip/transport/tcp/snd.go @@ -816,6 +816,25 @@ func (s *sender) maybeSendSegment(seg *segment, limit int, end seqnum.Value) (se panic("Netstack queues FIN segments without data.") } + segEnd = seg.sequenceNumber.Add(seqnum.Size(seg.data.Size())) + // If the entire segment cannot be accomodated in the receiver + // advertized window, skip splitting and sending of the segment. + // ref: net/ipv4/tcp_output.c::tcp_snd_wnd_test() + // + // Linux checks this for all segment transmits not triggered + // by a probe timer. On this condition, it defers the segment + // split and transmit to a short probe timer. + // ref: include/net/tcp.h::tcp_check_probe_timer() + // ref: net/ipv4/tcp_output.c::tcp_write_wakeup() + // + // Instead of defining a new transmit timer, we attempt to split the + // segment right here if there are no pending segments. + // If there are pending segments, segment transmits are deferred + // to the retransmit timer handler. + if s.sndUna != s.sndNxt && !segEnd.LessThan(end) { + return false + } + if !seg.sequenceNumber.LessThan(end) { return false } |