Hello and thanks for this interesting discussion!
When I look at the TCP statistics, I don’t see a big problem:

And when I zoom into the first 120 samples, I see this:

which is indeed around packet 75.
Note that the TCP peer must do some calculation, when it sees a win=5267, it must subtract the packets that are on its way, so the “real win” equals “win - outstanding”.
Actually the receiving end is reporting: “at the moment I acknowledged packet 18741, I had a buffer space of 5267”.
Please note also that the time stamps in Wireshark may not always agree with reality. Under Windows, it might use a time clock that runs at 18.2 Hz ( good-old MSDOS ). It just estimates the high-precision time-stamps.
Often while testing I created a PCAP-1 under Windows, and also a PCAP-2 in the FreeRTOS application ( using a fast Zynq with a disk ).
Looking at PCAP-1, I concluded that the Zynq was very slow.
Looking at PCAP-2, I concluded that Windows had huge delays!
While developing FreeRTOS+TCP, I have looked at ( the behaviour of ) other TCP/IP stacks, especially Linux and Windows. And yes I saw the slow-start and other tricks to handle congestion, Nagle’s algorithm, and more. We studied PCAPS, both taken from a LAN, as well as from a poor-quality Internet connection with a high amount of dropped packets.
These studies resulted in two features related to TCP flow-control:
-
Low- and High-water system. The value of “win” can drop to zero in case low-water has been reached. It will become non-zero again as soon as high-water has been reached.
( see FREERTOS_SO_SET_LOW_HIGH_WATER ).
-
A stop and go system: this is the manual version. This was developed for audio streaming. As soon as the DAC driver ( Digital to Analogue Convertor ) has enough data, it will send a STOP. As soon as the DAC buffer gets below 50%, it sends a START again.
( see FREERTOS_SO_STOP_RX ).
As these are non-standard features, they are hardly documented. I will document them more in detail and post that first here, then on freertos.org.
FreeRTOS+TCP is in style with the kernel: it is kept as simple as possible in order to:
- have a small memory footprint.
- to keep it easy to understand.
- to keep it robust and fast.
- facilitate debugging your TCP/IP application.