1

As we all know, the MTU is 1500 and the MSS for TCP is 1460. So when the buf used in the recv function is large than 1460 bytes, the TCP will be splitted into many parts.

I write a simple echo prog, and want to use tcpdump to check the fragmentation. However, it does not show the fragmentation when the buf is small, but shows when the buf is about 20K.

Here is the code:

Server:

import socket
import sys
import os

addr = ('10.0.0.2',10086)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(addr)
server.listen(5)

while True:
    connfd, addr= server.accept()
    print 'connection ip:', addr
    data = connfd.recv(8192);

Client:

import socket
import os
import sys

addr = ('10.0.0.2', 10086)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(addr)

data = '';
for num in range(0,8192):
    data += '1'

client.sendall(bytes(data))

Here is the tcpdump cmd I used:

sudo tcpdump -i lo port 10086 -s 1514 -v

enter image description here

See from the code, the buf is 8192, the MSS is 1460. So, in my opinion, the packet will be splitted into 1460, 1460, 1460, 1460, 1460, 892. But in the screenshots it not.

Also, I am not sure if this is caused by the [DF] flags. The prog is used python, so the build-in sockopt [DF] is set default? Heaven knows.

Tony Chen
  • 51
  • 1
  • 1
  • 4

3 Answers3

7

I'd like to add that you wont see fragments with your tcpdump filter because you are filtering on a port number. IP fragments don't really have a port number. Just the packet id and offset and also the protocol number. So you should filter on UDP with the IP src or destination. Or use this filter to see fragments: tcpdump -i eth1 '((ip[6:2] > 0) and (not ip[6] = 64))'

Credit: https://github.com/SergK/cheatsheat-tcpdump/blob/master/tcpdump_advanced_filters.txt

rbhkamal
  • 147
  • 2
  • 7
6

As we all know, the MTU is 1500 and the MSS for TCP is 1460

This is not true.

The MTU depends on the transport medium and a MTU of 1500 is specific to ethernet. But based on your tcpdump you are not using the ethernet interface (i.e. wired LAN connection between two machines) but have client and server on the same machine and thus use the lo interface (tcpdump -i lo ...). The MTU for the localhost interface is usually much higher:

  $ ifconfig lo
  lo: ...  mtu 65536

  $ ifconfig eth0
  eth0: ...  mtu 1500

Apart from that you will probably not see any fragmentation at all. If the packets are larger than the MTU you will see TCP segmentation (not fragmentation), i.e. that the OS will split the TCP stream into different segments where each if not larger than the MSS. Fragmentation instead occurs on the lower layers, for example if an IP packet needs to be split further since somewhere in the path to the target is a device with a smaller MTU.

The [DF] (don't fragment) you see is to make sure that no IP level fragmentation occurs and the packet instead gets discarded and the sender notified so that the Path MTU (minimal MTU of the Path) can be discovered and the TCP segmentation optimized for this in order to reduce the overhead of delivery. See Path MTU discovery for more information.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • Many thanks. I overlook the MTU of `lo` interface. I have tried to test on two hosts and I can see TCP segmentation packet now. What's more, I also turn off the `tso`. IIRC, it will forward the TCP segmentation to datalink layer, not on the TCP layer. – Tony Chen May 27 '18 at 14:26
1

You are sending data from localhost to localhost, inside one host. So, the MTU of ethernet (1500) won't limit size of MSS, because the data is not going over the ethernet.

Try to repeat the test between two different hosts.

SKi
  • 8,007
  • 2
  • 26
  • 57