MTU

From Leo's Notes
Last edited on 14 June 2020, at 22:22.

The Maximum Transmission Unit (MTU) is the largest number of bytes in an individual datagram or packet in a communications link. In the context of Ethernet, it is the largest possible frame size in a Protocol Data Unit (PDU) on the Layer 2 (data) of the OSI model. Ethernet networks use a MTU size of 1500 bytes, resulting in a frame size of 1518 bytes (14 for Ethernet header, 4 for Frame Check Sequence (FCS)). The 1500 byte MTU size is near universal on access networks.

Each layer of encapsulation adds an additional protocol header overhead which reduces the amount of data that can fit within a single 1500-byte packet.

Protocol Overhead
GRE (IP Protocol 47) (RFC 2784) 24 bytes (20 byte IPv4 header, 4 byte GRE header)
6in4 encapsulation (IP Protocol 41, RFC 4213) 20 bytes
4in6 encapsulation (e.g. DS-Lite RFC 6333) 40 bytes
Any Additional IPv4 Header 20 bytes
IPsec encryption performed by the DMVPN, ESP-AES-256 and ESP-SHA-HMAC 73 bytes
MPLS 4 bytes per label in the stack
IEEE 802.1Q tag 4 bytes (Q-in-Q would add 8 bytes)
VXLAN 50 bytes
OTV 42 bytes
LISP 36 bytes for IPv4 and 56 bytes for IPv6 encapsulation
NVGRE 42 bytes
STT 54 bytes

IPv4 routers fragment packets on behalf of the source node if the packet size exceeds the link's MTU unless the Do Not Fragment (DF) bit is set to 1. Packets that have DF set to 1 and exceeds the MTU will cause the router to reply back to the source with a ICMP 'Packet Too large' message. Path MTU Discovery (PMTUD) leverages this behavior to discover the maximum MTU that can be sent to a destination.

IPv6 routers must support MTU sizes of 1280 bytes or larger and will not fragment IPv6 packets on behalf of the source.

You can use ping to send a ICMP packet of a particular size with the DF bit set to detect the maximum MTU size over a link.

Header text Header text
Windows ping 10.1.1.1 -l 1500 -f
Linux ping -s 1500 -M do 10.1.1.1
MacOS ping -D -s 1500 10.1.1.1

Note: You might need to adjust the size value if ping does not account for the ICMP header (8 bytes) or the IPv4 header (20 bytes).

Setting MTU

On Linux, the MTU size can be set using ip link set.

# ip link set enp3s0 mtu 6128
# ip a | grep mtu
2: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 6128 qdisc fq_codel state UP group default qlen 1000

When setting the MTU, ensure that your network device is capable of handling the desired MTU. Exceeding this limit will result in an error. Eg.

# ip link set enp3s0 mtu 9000
Error: mtu greater than device maximum.

To have the MTU value persistent, see the relevant sections below.

Red Hat

Red Hat systems have the MTU size set in the /etc/sysconfig/network-scripts network config file. For example,

# echo "MTU=6128" >> /etc/sysconfig/network-scripts/ifcfg-enp3s0

Systemd

When using Systemd, you can either set it through systemd-networkd or a custom systemd unit.

Look at /usr/lib/systemd/network/ and create a corresponding override file in /etc/systemd/network/ with MTUBytes set to the desired MTU size.

To create a custom systemd unit, do something similar to:

# cat /etc/systemd/system/setmtu@.service
[Unit]
Description=Set mtu on device
Before=network.target

[Service]
Type=oneshot
EnvironmentFile=/etc/conf.d/setmtu
ExecStart=/usr/bin/ip link set dev %i up mtu ${%i}

[Install]
WantedBy=multi-user.target

# cat /etc/conf.d/setmtu
eth0=4000