0

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

Eggi
  • 170
  • 1
  • 15
  • Define "custom client". I don't understand if you use windows socket TCP API or if you are writing your own implementation using RAW socket or something else. Please clarify. [Edit](https://stackoverflow.com/posts/68555195/edit) your message to give the clarification. – fpiette Jul 28 '21 at 09:27
  • You have two packets for your data because the MTU is 4088 (You said) and you send 4092 bytes. MTU is the maximum size of a packet that can be sent, including the header. Maybe this is where your problem comes from. – fpiette Jul 28 '21 at 12:55
  • @fpiette Yes it should be, but if the ACK is coming in less then 30ms (30ms is not always the timeout) i do not have this behaviour. I cannot see any hint in the msdn docu where it states that this is prohibited. Only for message orientated protocols like udp you should not send more than MTU size. – Eggi Jul 28 '21 at 13:14
  • 1
    You can send more than MTU but "don't fragment" can't be honored. – fpiette Jul 28 '21 at 14:11
  • @fpiette Just experimented a bit with the TIdTCPClient class, and with this one, I can't reconstruct this behaviour - everything ok. So I went and checked what is done, and I changed from WSASend to the old send function and when creating the Socket Handle I went from SOCK_TCP to SOCK_IP like in the Indy implementation. Still get the error with my implementation. – Eggi Jul 29 '21 at 12:16
  • You can also have a look at my own implementation in [ICS](http://wiki.overbyte.eu/wiki/index.php/ICS_Download) (Also available on GetIT from Delphi IDE). Look in TWSocket source code. – fpiette Jul 29 '21 at 19:15
  • @fpiette had a good laugh at the postcard registration :) But i just sent some data with TWSock and it sends the data, but in a very strange order. 8K Data are split into 4 packets, 1514B, 4086B, 402B - then waits for an ACK of the client, then sends the remaining 2406B and waits for an ACK. – Eggi Aug 02 '21 at 09:06
  • TWSocket buffers data for you, in packets whose size if governed by the property BufSize. How network packets are actually sent depend on BufSize, the number of send() you do, the TC/IP stack, the MTU, the active or not nagle algorithm and probably more. I seems you forget that TCP is stream oriented and the number of actual packet has NO impact on the transmission, except that performance is lowered by small packets. ICS has his [own support forum](https://en.delphipraxis.net/forum/37-ics-internet-component-suite/). It is better to ask there. – fpiette Aug 02 '21 at 10:04

1 Answers1

0

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.

Eggi
  • 170
  • 1
  • 15