Search code examples
windowsdelphiwinsock2retransmit-timeout

Winsock - Retransmission Seq incremented


I get the following when communicating with a custom client. With custom client i mean a housemade PCB with a FPGA which runs the Triple-Speed Ethernet Intel FPGA IP. It does not make a difference if a switch is between the PC and the PCB.

Workflow seen from the Server(Windows PC) where i detect this behaviour with wireshark:

  1. Connect to client (Syn - Syn/Ack - Ack) Winsock2.connect
  2. Sending data > MTU with Winsock2.WSASend (4092 Bytes on a 4088 Bytes MTU)
  3. Packet gets "fragmented" into 2 packets - do not fragment bit is set
  4. A Retransmission happens (because the client answered too slow?)

I am using delphi 10.4 and use the Winsock2 functions. Bevore each send i check with select if fdwrite is set if FD_Isset. Nagle is deactivated.

The "retransmission" does not happen everytime and i could not detect any sort of pattern when they occur. Except most of the time it is when the client needs more than 30ms to send his ACK.

When the "retransmission" happens it is not packet 1 or two whicht is re-send, but packet 1 with an offset of 60 which is the payload of packet 2. The sequence number of packet 1 is incremented by 60 too. Even the data is correct, it's correctly incremented by 60. When I send 6000 Bytes i get the same behaviour with an incremented seq of 1968 which is correct too. What is happening here? Can i detect this with winsock2? Can i set the RTO with winsock? Why is the sequence number incremented and not packet 1, as it is, retransmitted?

Source Code of the send function:

function TZWinTCPSock.SendData (out ErrMsg : TAPILogStruct; SendOffset : 
Cardinal = 0)  : Boolean;
var
  WSABuff   : WSABUF;
  res       : Integer;
  IPFlags   : Cardinal;
  t         : Cardinal;
  WSAErr    : Cardinal;
begin
  Result      := FALSE;
  WSAErr      := WSAGetLastError;
  try
    if not CheckSockValid(ErrMsg) then // checks if fd_write is set
    begin
      exit(false);
    end;
    try
      WSABuff.len   := FMem.SendLength; // 4092 at this time Cardinal
      WSABuff.buf   := @FMem.SendData[SendOffset]; // 8192 Bytes reserved TArray<Byte>
      IPFlags       := 0;
      res := WSASend(FSocket,@WSABuff,1,FMem.sentBytes,IPFlags,nil,nil);
      if Res <> SOCKET_ERROR then
      begin
        if FMem.SendLength <> FMem.SentBytes then
        begin
          exit(false);
        end
        else
        begin
          Result := TRUE;
          if WSAGetLastError <> WSAErr then // unexpected WSA error
          begin
            exit(FALSE);
          end;
        end;
      end
      else
      begin
        FLastWSAErr       := WSAGetLastError;
        if FLastWSAErr = WSAECONNRESET then
        begin
          Disconnect(ErrMsg);
          exit(false);
        end;
      end;
    except
      on E : Exception do
      begin
        // Some error handling
      end;
    end;
  finally
    
  end;
  
end;

Wireshark

Edit1 The packets have the don't fragment Bit set. I tried to detect this "retransmission" with the windows admin center, but I don't see anything popping up. Perfmon


Solution

  • Got an answer on Microsoft Q&A. Looks like it was a tail loss probe problem where the destination host is at fault, because the reply took too long and srtt timed out.