6

I intend to set the "don't fragment" flag bit in Go, the same thing as this post while it is in C. I checked the constant list but I didn't find this option. So what is the corresponding option in Go?

Thanks in advance!

Community
  • 1
  • 1
zzy
  • 751
  • 1
  • 13
  • 25
  • Maybe you would need your own loop in order to not allow fragment, as in https://github.com/beatgammit/arduino-tcp-server/blob/master/TCPServer.ino – VonC Jun 11 '16 at 10:54
  • @VonC Hello, I don't fully understand why setting the first byte as 0x81 (as mentioned in their README) could prevent fragment. My gut feeling is that this magic number could form the byte for a packet without fragmenting, but actually the packet can still be fragmented. Am I correct or do I miss anything here? Thanks!! – zzy Jun 11 '16 at 12:24
  • Good question. I don't know, except section 5.7 of https://datatracker.ietf.org/doc/rfc6455/?include_text=1 has single frame examples starting with `0x81`. – VonC Jun 11 '16 at 12:34
  • @VonC Thanks! That example makes sense and perhaps fits my assumption - such byte represents unfragmented frames. – zzy Jun 11 '16 at 13:08

1 Answers1

6

How to set "don't fragment" flag bit for TCP packet in Go?

First up you should know that TCP really doesn't like IP fragments. Most if not all major implementations avoid fragmentation for TCP segments by using path MTU discovery.

The TL;DR is that the typical IP packet containing a TCP segment has a DF bit set. You can (and should) try this out. Here I am sniffing a few seconds of traffic between my machine and stackoverflow.com:

% tshark -w /tmp/tcp.pcap tcp and host stackoverflow.com
<wait a few seconds>
% tshark -r /tmp/tcp.pcap -T fields -e ip.flags | sort | uniq -c
    186 0x00000002

0x02 means the DF bit is set. I confess in other captures I have seen the occasional TCP segment in an IP packet without a DF bit; I suspect rfc1191 has an explanation for this.


Now back to your question, I think there's no portable way to set the DF bit and this is a more widespread question (there isn't even a POSIX-portable way). There is (likely) an escape hatch in the relevant package for your implementation under golang.org/x/sys.

For example, on a Unix that supports IP_DONTFRAG such as FreeBSD one could use unix.SetsockoptInt and dig the relevant constant value.

On Linux there is not IP_DONTFRAG, as you discovered from the question you linked. The workaround seems to be to use IP_MTU_DISCOVER which happens to be available as a constant in the unix package. You can use that same unix.SetsockoptInt to set it.

Community
  • 1
  • 1
cnicutar
  • 178,505
  • 25
  • 365
  • 392