The following code allows to discover MTU between your local machine and remote host in C#:
static int? DiscoverMtu(IPAddress address, int timeout, int ttl = 240)
{
const int icmpEchoHeaderSize = 8;
const int mtuMinSize = 60;
const int mtuMaxSize = 65500;
int mtuLowerBound = mtuMinSize, mtuUpperBound = mtuMaxSize;
var bestMtu = default(int?);
using var ping = new Ping();
var options = new PingOptions(ttl, true);
for(int currentMtu; mtuLowerBound <= mtuUpperBound; )
{
currentMtu = (mtuLowerBound + mtuUpperBound) / 2;
var buffer = new byte[currentMtu];
var reply = ping.Send(address, timeout, buffer, options);
if(reply.Status == IPStatus.Success)
{
bestMtu = currentMtu + icmpEchoHeaderSize;
mtuLowerBound = currentMtu + 1;
}
else
mtuUpperBound = currentMtu - 1;
}
return bestMtu;
}
The method returns null if MTU cannot be discovered. If you need asynchronous version then just replace ping.Send
with ping.SendPingAsync
call and change return type to Task<int?>
.
Note that discovered MTU is the amount of data that can be placed inside of single IP packet with DF
(don't fragment) flag. This value doesn't include IP header size (which is at least 20 bytes for IPv4).
You can compare result of this method with the output produced by tracepath
on Linux (which includes size of IP header).
Completed implementation you can find here