Home > database >  Why do I see strange UDP fragmentation on my C server?
Why do I see strange UDP fragmentation on my C server?

Time:12-22

I have build an UDP server with C and I have a couple questions about this.

Goal:

I have incomming TCP trafic and I need to sent this further as UDP trafic. My own UDP server then processes this UDP data. The size of the TCP packets can vary.

Details:

In my example I have a TCP packet that consists of a total of 2000 bytes (4 random bytes, 1995 'a' (0x61) bytes and the last byte being 'b' (0x62)).

My UDP server has a buffer (recvfrom buffer) with size larger then 2000 bytes. My MTU size is 1500 everywhere.

My server is receiving this packet correctly. In my UDP server I can see the received packet has a length of 2000 and if I check the last byte buffer[1999], it prints 'b' (0x62), which is correct. But if I open tcpdump -i eth0 I see only one UDP packet: 09:06:01.143207 IP 192.168.1.1.5472 > 192.168.1.2.9000: UDP, bad length 2004 > 1472. With the tcpdump -i eth0 -X command, I see the data of the packet, but only ~1472 bytes, which does not include the 'b' (0x62) byte.

The ethtool -k eth0 command prints udp-fragmentation-offload: off.

So my questions are:

  1. Why do I only see one packet and not two (fragmented part 1 and 2)?
  2. Why dont I see the 'b' (0x62) byte in the tcpdump?
  3. In my C server, what buffer size is best to use? I have it now on 65535 because the incomming TCP packets can be any size.
  4. What will happen if the size exceedes 65535 bytes, will I have to make an own fragmentation scheme before sending the TCP packet as UDP?

CodePudding user response:

The size of the TCP packets can vary.

While there is no code shown the sentence above and your description suggests that you are working with wrong assumptions of how TCP works.

Contrary to UDP, TCP is not a message based protocol but a byte stream. This especially means that it does not guarantee that single send at the sender will be matched by a single recv in the recipient. Thus even if the send is done with 2000 bytes it might still be that the first recv only gets 1400 bytes while another recv will get the rest - no matter if everything would fit into the socket buffer at once.

CodePudding user response:

OK, circumstances are more complicated as they appear from question, extracted from your comments there's the following information available:

  1. Some client sends data to a server – both not modifiable – via TCP.
  2. In between both resides a firewall, though, only allowing uni-directional communication to server via UDP.
  3. You now intend to implement a proxy consisting of two servers residing in between and tunneling TCP data via UDP.
  4. Not being able for the server to reply backwards does not impose a problem either.

My personal approach would then be as follows:

  1. Let the proxy servers be entirely data unaware! Let the outbound receiver accept (recv or recvfrom depending on a single or multiple clients being available) chunks of data that yet fit into UDP packets and simply forward them as they are.
  2. Apply some means to assure lost data is at least detected, better such that lost data can be reconstructed. As confirmation or re-request messages are impossible due to firewall limitation, only chance to increase reliability is via redundancy, though.
  3. Configure the final target server to listen on loopback only.
  4. Let the inbound proxy connect to the target server via TCP and as long as no (non-recoverable) errors occur just forward any incoming data as is.

To be able to detect lost messages I'd at very least prepend a packet counter to any UDP message sent. If two subsequent messages do not provide consecutive counter values then a message has been lost in between.

As no communication backwards is possible the only way to increase reliability is unconditional redundancy, trading some of your transfer rate for, e.g. by sending every message more than once and ignoring surplus duplicates on reception side.

A more elaborate approach might distribute redundant data over several packets such that a missing one can be reconstructed from the remaining ones – maybe similar to what RAID level 5 does. Admitted, you need to be pretty committed to try that...

Final question would be how routing looks like. There's no guarantee with UDP for packets being received in the same order as they are sent. If there's really only one fix route available from outbound proxy to inbound one via firewall then packets shouldn't overtake one another – you might still want to at least log to file appropriately to monitor the inbound UDP packets and in case of errors occurring apply appropriate means (buffering packets and re-ordering them if need be).

  • Related