1. Overview
The Maximum Transmission Unit (MTU) represents the maximum packet size that can be transmitted over a network without fragmentation. Discovering the appropriate MTU size between our machine, localhost, and a destination IP address is crucial for optimizing network performance.
In this tutorial, we’ll explore how to determine the MTU sizes using the shell in Linux. In addition, we’ll look at code snippets along with output examples, and discuss any necessary command options. While we concentrate on the IPv4 address space, the procedure can be expanded to IPv6 as well.
2. Using the ping Command
The first method to check for MTU sizes in our network or at the destination IP uses the ping command. One point in favor of the ping command is that it’s typically available by default on most Linux distributions, so no additional package installation is usually required.
To employ ping, we’ll write a short Bash script mtu.sh:
$ cat mtu.sh
#!/bin/bash
destination_ip="$1"
# Set initial packet size
packet_size=1200
# Loop to find the maximum MTU size
while true; do
ping -4 -M do -c 1 -s $packet_size $destination_ip &> /dev/null
if [ $? -ne 0 ]; then
echo "Maximum MTU size: $((packet_size + 28 - 2))"
break
fi
packet_size=$((packet_size + 2))
done
The ping command can help us discover the MTU size by utilizing the Don’t Fragment (DF) flag. We can determine the maximum MTU size by gradually increasing the packet size until we encounter fragmentation.
Let’s understand the code and see how to get the maximum MTU size in our multiple-hop network.
2.1. Initializing Variables
We start off with the usual shebang and variable initialization:
#!/bin/bash
destination_ip="$1"
# Set initial packet size
packet_size=1400
Firstly, we initialize a variable named destination_ip and assign the value of the first argument to the script. Afterward, we make sure to set the initial packet_size to the value of 1200 excluding 28 bytes for IP and ICMP headers.
2.2. Loop Structure
Next, we create an endless while loop to retrieve the maximum MTU size in our network:
# Loop to find the maximum MTU size
while true; do
ping -M do -c 1 -s $packet_size $destination_ip &> /dev/null
So far, we’ve used several options:
- -4 specifies that the command should use IPv4
- -M sets the Don’t Fragment flag in the IP header
- -c specifies the number of packets sent with the ping command, i.e., 1 in this case
- -s sets the value of the packet size excluding headers
- $destination_ip sets the target
- &> /dev/null discards any output
Next, we’ll see what we can do with this data.
2.3. Process Data
Accordingly, let’s continue our while loop to meet our objective:
if [ $? -ne 0 ]; then
echo "Maximum MTU size: $((packet_size + 28 - 2))"
break
fi
packet_size=$((packet_size + 2))
done
By gradually incrementing the packet size, the loop iterates until it finds the maximum packet size that can’t traverse the network without fragmentation, at which point the code stops the loop.
Increasing the packet size by exactly 2 bytes in each iteration is an arbitrary choice.
Let’s break down the if statement conditions:
- $? is a special variable that holds the exit status of the previously executed command, in this case – ping
- -ne is a comparison operator that stands for not equal
- 0 means the command executed without errors in most Unix-like systems
In essence, the if condition [ $? -ne 0 ] checks whether the exit status of the ping command isn’t equal to 0, which means that the ping command didn’t receive a reply. Finally, failing to receive a reply usually indicates that the packet size is too large and requires fragmentation.
Consequently, the code inside the if block is executed. There, we add 28 bytes for headers to the packet size, but remove 2 bytes since that’s what caused the final overflow. Finally, we break out of the loop.
2.4. Run Script
Next, we can run the script for a given IP to get the maximum MTU size:
$ bash mtu.sh 192.168.0.1
Maximum MTU size: 1472
The script enables us to automate the process of obtaining the optimal MTU size for our network configuration.
2.5. Special Cases
Finally, some known IPs, such as 8.8.8.8, the one used for Google, restrict the MTU ping sizes:
$ ping -M do -s 1500 8.8.8.8
Request timed out.
Request timed out.
Request timed out.
Request timed out.
Therefore, we ought to avoid testing with well-known IPs.
3. Using the traceroute Command
Besides the ping command, there are other methods available to discover the MTU sizes between our machine and a destination IP.
One such method uses the traceroute command, which provides additional information about the path that packets take to reach the destination. The traceroute command helps discover the MTU sizes along the route by examining the Frag needed messages. It provides a comprehensive view of the network path and potential bottlenecks. However, it may not always reveal the MTU sizes for each hop, as network routers and firewalls can block or suppress certain ICMP messages.
3.1. Package Installation
If the traceroute command isn’t already installed, we’ll need to install it first. For instance, on Ubuntu, we can install traceroute using apt:
$ sudo apt install traceroute
Before proceeding, we’ll use dpkg to verify the package is installed correctly:
$ dpkg --get-selections | grep -w "install" | head
acl install
traceroute install
The above output shows the list of installed packages via the –get-selections option. Furthermore, we piped the output to a grep command that selects the lines matching the word install. Finally, the head command shows the first 10 lines of the original output.
3.2. Command Run
Since we’re done with the installation part, we can now issue our command:
$ destination_ip="192.168.1.1"
$ traceroute -n $destination_ip | grep -i "frag needed"
First, we assign an IP address of 192.168.1.1 to our variable named destination_ip. We then use this variable instead of typing the destination IP address.
Here, we use the traceroute command with the -n option to display IP addresses instead of hostnames for quicker execution. Then, we pipe the output to grep to search for Frag needed messages. The Frag needed messages indicate that fragmentation occurred during the route and suggest a smaller MTU size.
3.3. Example Output
Let’s go through a real-world example output from the command above to understand how it can help us discover MTU sizes:
$ traceroute -n 192.168.1.1 | grep -i "frag needed"
1 192.168.0.1 2.345 ms 1.234 ms 1.567 ms Frag needed
2 10.0.0.1 3.456 ms 2.123 ms 2.789 ms Frag needed
3 203.0.113.1 5.678 ms 4.567 ms 6.789 ms Frag needed
4 172.16.0.1 8.123 ms 7.234 ms 7.345 ms
5 192.168.1.1 10.123 ms 9.234 ms 8.345 ms Frag needed
In the above output, we have a traceroute to the destination IP 192.168.1.1. Each line represents a hop along the network path. Let’s break down the information provided for each hop by column:
- hop number, so we have five hops in this example
- IP addresses of the device at that hop
- round-trip time (RTT) in milliseconds for the first of three consecutive packets sent to that hop
- RTT for second packet
- RTT for third packet
- status, which, if it’s equal to Frag needed, shows that the packet has undergone fragmentation
In-depth, the traceroute output helps us visualize the network path from our machine to the destination IP. By observing the sequence of IP addresses, we can understand the intermediate routers or devices that the packets pass through.
3.4. Calculating the MTU
Since we’ve already filtered Frag needed message rows, we see each hop that required fragmentation. The packet size at that hop can give us an estimate of the MTU size at that particular point.
For example, we can take a sample output line:
3 203.0.113.1 5.678 ms 4.567 ms 6.789 ms Frag needed
Knowing fragmentation was needed at that point, we can employ our ping method to get the MTU size.
The traceroute output can vary based on network configurations, and not all hops may reveal messages about fragmentation. However, by analyzing the output and focusing on the hops with such messages, one can gain insights into potential MTU size limitations along the route to the destination.
4. Conclusion
In this article, we went through ways to get the MTU sizes between our machine and a specific destination IP.
While the ping command allows us to determine the MTU size for the direct link, the traceroute command provides insights into the path and potential fragmentation along the route.
By using both methods together, we can gather more comprehensive information about the network infrastructure and make informed decisions regarding MTU sizes.