prvTCPWindowFastRetransmit error when reading data fastly from server

Hello Everyone,
I’m also facing some error with polarfire fpga with RISCV port.
I’m sending near 5000 KB video data from FPGA ethernet stack continiously on port 1234 with udp.

in RISCV firmware i used freeRTOS and want to read sensor data from it to client side with 100ms delay but then i got this error

prvTCPWindowFastRetransmit: Requeue sequence number xxxxx < yyyyy
if i read data with 1 second delay on client side or the video is off then i have no error.

I’m using Remote procedure call with etherent stack in Riscv.

if anyone has solution then please guide me.
Thank you very much.

@asiddiqui You mention that your sensor data stream is received via a UDP socket, however prvTCPWindowFastRetransmit is only used for tcp connections. I’m guessing that the communication between the RISC-V core and client machine takes place over TCP.

Are the FPGA and RISCV sides sharing a single ethernet MAC? If so, how do you arbitrate access to the peripheral between the RISC-V and FPGA cores?

Can you share some more details about your application? Are you using a particular demo as a starting point?

Additionally, please take a look at the following forum post from 2018 which may help address this issue:

Hello @PaulB-AWS
Thanks for the reply.
we are using UDP broadcast on broadcast port 10000 and listening port is TCP 10001.
The network communication is based on remote procedure calls between server and client.
We have initialize both socket and we are using opencore for Etherent in FPGA.
The video data is write on Vram on FPGA side with VHDL process and send by using etherent mac to udp port 5678.

With RISCV and FreeRTOS we are using the following structure for DPRAM to read and write data from and to FPGA ethernet mac.

NetworkBufferDescriptor_t *pxBufferDescriptor;

and then transmit packet using dpram which will also use Etherent mac on FPGA side but different port 10001 and RPC.

I used tcpdump and with only UDP stream video, output is
10:33:18.434209 IP 10.0.0.6.1234 > ali.5678: UDP, length 1460

with reading data only without video with TCP port
10:26:46.206258 IP 10.0.0.6.10001 > ali.50546: Flags [.], ack 35371, win 961, length 0
10:26:46.304434 IP 10.0.0.6.10001 > ali.50546: Flags [P.], seq 20348:20374, ack 35371, win 1003, length 26

and with both (reading data and video on) i got the following information with tcpdump
10:33:18.433995 IP rico.60924 > 10.0.0.6.10001: Flags [P.], seq 3514:3556, ack 1966, win 501, length 42
10:33:18.434209 IP 10.0.0.6.1234 > rico.5678: UDP, length 1460
10:33:18.434478 IP 10.0.0.6.1234 > rico.5678: UDP, length 1460
10:33:18.434734 IP 10.0.0.6.1234 > rico.5678: UDP, length 1460
10:33:18.434734 IP 10.0.0.6.10001 > rico.60924: Flags [.], ack 3556, win 961, length 0
10:33:18.434988 IP 10.0.0.6.1234 > rico.5678: UDP, length 1460

the sensor reading data packets are very small and receiving much slower as compared to video packets.

The output on debug console on server side where FreeRTOS is running.

prvTCPWindowFastRetransmit: Requeue sequence number 128430 < 128560
COMM: RCV OK. Err: 0
COMM: RCV OK. Err: 0
COMM: RCV OK. Err: 0
COMM: RCV OK. Err: 0
prvTCPWindowFastRetransmit: Requeue sequence number 128612 < 128638
COMM: RCV OK. Err: 0
COMM: RCV OK. Err: 0
prvTCPWindowFastRetransmit: Requeue sequence number 128664 < 128690
COMM: RCV OK. Err: 0
COMM: RCV OK. Err: 0

So i got the WindowRetransmit error when video is on with UDP port and TCP is reading data…

As @PaulB-AWS you said this may a problem of dpram memory arbitration on fpga side…?
Can we solve this issue with FreeRTOS or with software rather than using some VHDL programming…?
or it’s related to some communication problem with FreeRTOS stack.?
is it not a problem with Linux buffer on client side PC…?
if anyone has some helpful tips then please share.
Thank you very much

Hi @asiddiqui, your pointing at this statement:

FreeRTOS_debug_printf( ( "prvTCPWindowFastRetransmit: Requeue sequence number %u < %u\n",
    ( unsigned ) ( pxSegment->ulSequenceNumber - pxWindow->tx.ulFirstSequenceNumber ),
    ( unsigned ) ( ulFirst - pxWindow->tx.ulFirstSequenceNumber ) ) );

This is printed every time when a fast retransmission takes place. It is not an error.

So you see a fast retransmission when:

"you read data with 1 second delay on client side" or
"when the video is off then i have no error".

What do you mean exactly, “read data with 1 second delay”?

Hello @htibosch
Thanks for the reply.
In RPC we have different functional blocks.
there is a timeout for every functional block which will block the other function call during this time.
If i use 1 second timeout then i got the right value of sensor data but if i decrease the timeout to 100msec then sometime i got right data and mostly i got wrong data with zero value and during fast read i got prvTCPWindowFastRetransmit statement.
I’m only calling one function of a functional block.

The main goal of application is to read data with near 100msec.
i checked tcp buffer and try increasing it’s size to 128 and in function
BaseType_t xSendEventStructToIPTask( const IPStackEvent_t * pxEvent,
TickType_t uxTimeout )
first i was using 0 in timeout for non blocking read from MAC and result was not good as compared to 200 ticks timeout.
But still i got wrong values particularly if the video size increase from 4MB to 6MB depends on capture colours.

if you have any idea then please guide me.
Thank you very much.

Hello @asiddiqui,

Did you develop your own Network Interface? Would you mind to share that code? Or if that is a problem, could you share it privately by emailing it? ( hein [at] htibosch [dot] net ).
Also it would be useful to see a PCAP of the data.

When a NIC calls xSendEventStructToIPTask(), I would recommend to use an infinite timeout of portMAX_DELAY. When this function fails to deliver a packet, it will likely cause a FastRetransmit :slight_smile:

The main goal of application is to read data with near 100msec.

What do you mean with this phrase? What should last 100 ms?

i checked tcp buffer and try increasing it’s size to 128

Could you show me that code?

But still i got wrong values particularly if the video

What do you mean with “wrong values”? Is what you receive different from what was sent?

Hello @htibosch ,
Thank you very much for the reply.
Unfortunately i can not share the code.
I will give a try with portMAX_DELAY and update you,Thank you.
Yes The sampling time is 100 mili second.
The buffere is network buffer in FreeRTOSIPConfig.h file.
using this Macro
#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTIONRS 120
which was 60 earlier.
The server is reading value from a sensor with 100ms vTaskDelay with a functional block in RPC but if i try to read that value from client side with 300ms i got only sensor value and zero.
So sometime i got right value of sensor and sometime i got only zero(if video is on, that’s why i am getting data around 5-6MB).
But if i use 1 second delay on client side then all values are right.
if i did not start video data and read sensor even with 100ms then all values are right.
The connection is 100Mb and i also try with 1Gb but behavior is same.
It’s not some memory arbitration problem in MAC side …?
Because i got only error if i receive huge data and the fast re-transmit messages only appear with Video on and reading sensor data in client side.
Thank you for your suggestion.

@asiddiqui It’s hard for us to look into this further without more information.

It sounds like some sort of concurrency issue when accessing the emac from the FPGA and CPU without some sort of locking. Perhaps you can try using separate macs for the cpu and fpga to eliminate that as a potential cause.

1 Like

Hello @PaulB-AWS and @htibosch ,
Thanks for the reply.
I tried with portMAX_DELAY but the result is same.
first i will check without RPC with simple server/ client with video, if it will give the same error then i will go with separate mac and memory arbitration.
Thank you very much for your help and suggestions…

To summarise my conclusion: the problem seems not be prvTCPWindowFastRetransmit(), but the missing packets.
When working on a LAN, there should almost never be a retransmission.

Good luck with it.

1 Like

Hello @htibosch and @PaulB-AWS ,

I tried with simple server on FreeRTOS RISCV side and client on linux side.
The code on the server side is

const TickType_t xSendTimeOut= 10 / portTICK_PERIOD_MS;
    socket = FreeRTOS_socket(FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP);
     FreeRTOS_setsockopt(socket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof(xSendTimeOut));
    xBindAddress.sin_port = FreeRTOS_htons(5000);
    xBindAddress.sin_family = FREERTOS_AF_INET;
    FreeRTOS_bind(socket, &xBindAddress, sizeof(xBindAddress));

    while(1) {

       recvLength = FreeRTOS_recvfrom(socket, buffer, sizeof(buffer), 0, &xBindAddress, sizeof(xBindAddress));

      char send [4];
      sprintf(&send[0], "%x", 125);
      sprintf(&send[2], "%x", 255);
      FreeRTOS_sendto(socket, send, sizeof(send), 0, &xBindAddress, sizeof(xBindAddress));

      vTaskDelay(20 / portTICK_PERIOD_MS);
    }

Without video it works properly.
but again with video stream it’s slow as compared to 20msec delay.
it’s not giving the wronge or zero values but most of the time the delay between values are nearly 2-3 seconds and after a delay comes suddenly a stream of packets.
The other thing is i did not get why i need to call every time FreeRTOS_recvfrom(...) function when i only want to send some values from server.
The same applies also on linux side i also have to call there sendto(..)function but i only want to receive there.
Can anyone please clarify it.
Thank you very much.

Well, if your UDP data is outgoing only, it is useless to constantly call recvfrom() from the device that is only sending.

The same is true for the other side: you don’t have to call sendto() when you only expect to receive data.

    FreeRTOS_sendto(socket, send, sizeof(send), 0, &xBindAddress, sizeof(xBindAddress));
    vTaskDelay(20 / portTICK_PERIOD_MS);

It is a good custom to write some logging in case a function fails. Here above you call FreeRTOS_sendto() without testing it’s result.