Hi,

this is a new, narrow series for one specific receive-window problem in
the scaled no-shrink path.

The earlier larger receive-window accounting series tried to address
multiple cases at once: quantization slack, live scaling-ratio drift,
retracted windows, repair state, MPTCP state, and extra test plumbing.
Review on that version was useful, but it also made clear that the
series was trying to carry more mechanism than the currently proven
problem justified.

This repost keeps only the part with a clear fail-before/pass-after
story today, and it keeps the stored receive-window state representable
so later no-shrink decisions continue to reason from a right edge the
peer could actually have seen on the wire.

Problem
=======

In the scaled no-shrink path, __tcp_select_window() rounds free_space up
to the receive-window scale quantum:

  window = ALIGN(free_space, 1 << tp->rx_opt.rcv_wscale);

When free_space sits just below the next quantum, that can expose fresh
sender-visible credit that is not actually backed by the current receive
memory state.

That is not just a presentation artifact. Later hard admission can still
reject data which is within the sender-visible offer.

A narrower first rework that stored raw free_space would not have been
safe either. Later no-shrink preservation derives the current offer from

  tp->rcv_wup + tp->rcv_wnd - tp->rcv_nxt

so the stored window still needs to remain representable in scaled
units.

Approach
========

Instead of rounding larger raw windows up in the scaled no-shrink path,
keep only the cases we actually need:

  - relax one unrelated packetdrill test which was pinning an
    incidental advertised window
  - keep tp->rcv_wnd representable in scaled units by rounding larger
    windows down to the scale quantum
  - preserve only the small non-zero case that would otherwise scale
    away to zero
  - rely on the existing tcp_select_window() no-shrink preservation
    logic for already-exposed credit

That removes the larger-window quantization slack from rounding
free_space up, while preserving the small non-zero case needed to avoid
scaling away to zero.

Tests
=====

The packetdrill reproducer exercises both the immediate quantization
case and a follow-on ACK after a small OOO receive-memory change.
Before the TCP change, it fails on the first outbound packet with the
advertised window one scaled unit too large:

  expected: win 84
    actual: win 85

After the TCP change, the reproducer passes and the follow-on ACK also
stays at 84.

Series layout
=============

  1/3 selftests: packetdrill: stop pinning rwnd in tcp_ooo_rcv_mss
  2/3 tcp: keep scaled no-shrink window representable
  3/3 selftests: packetdrill: cover scaled rwnd quantization slack

Thanks,
Wesley Atwell

---
 net/ipv4/tcp_output.c                              | 16 +++++---
 .../selftests/net/packetdrill/tcp_ooo_rcv_mss.pkt |  8 ++--
 .../packetdrill/tcp_rcv_quantization_credit.pkt   | 45 ++++++++++++++++++++++
 3 files changed, 61 insertions(+), 8 deletions(-)

-- 
2.43.0

Reply via email to