MTU mismatch between GetIfEntry and netsh

I am working on pseudo transport layer software that runs on top of UDP, providing reliable connection oriented transmission as an alternative to TCP. To maximize network efficiency, we request the MTU of the "best" network adapter during initialization.

MIB_IFROW row = {0};
row.dwIndex = dwBestIfIndex;

dwRes = GetIfEntry(&row);

      

Searching online I found that you can use the following netsh commands to request this same value from the command line (not the C ++ API)

netsh interface ipv4 show interfaces
netsh interface ipv4 show subinterfaces

      

The alarming issue is that while row.dwMtu can be set to 1500, monitoring the network traffic on the sending laptop shows that our packets are fragmented into 1300 byte packets. netsh also says the MTU is 1300.

Obviously, the value reported by the netsh command is the actual values ​​used. Does anyone know which API I can call to get the same values ​​as netsh?

+2


a source to share


1 answer


There is a local MTU size and a path MTU (see RFC 1191). You can use commands like

ping -f -l 1464 www.stackoverflow.com
ping -f -l 1465 www.stackoverflow.com

      

to determine the MTU of the path. Consider the size of the ICMP header and IP headers. See Path MTU Discovery for API solution.

UPDATED . Please, no more questions! I was very curious to find the answer, and I spent several hours on it. But ... I found it! To get the correct MTU size, you must use an API GetIpInterfaceTable

that returns a structure PMIB_IPINTERFACE_TABLE

that has an array of structures MIB_IPINTERFACE_ROW

. MIB_IPINTERFACE_ROW

hat InterfaceIndex

that helps you identify the IP interface, it is similar to other well known IP helper functions. You can also use a function ConvertInterfaceLuidToNameW

to get InterfaceLuid

the interface name from another field .

But the most interesting is the field NlMtu



typedef struct _MIB_IPINTERFACE_ROW {
    ADDRESS_FAMILY Family;
    NET_LUID InterfaceLuid;
    NET_IFINDEX InterfaceIndex;
    // ...
    ULONG NlMtu;
    // ...
};

      

The documentation (see http://msdn.microsoft.com/en-us/library/aa814496(v=VS.85).aspx ) describes it as " Network Layer MTU Size in Bytes. " You will also find the same text and nothing more in the Windows Driver Kit documentation (see http://msdn.microsoft.com/en-us/library/ff559254(VS.85).aspx ). This NlMtu field is what you are looking for. For example, my computer is connected to the Internet via a DSL router, NlMtu

not 1500 as it would be without a router, but instead has the correct value 1492. In your case, it should be 1300.

If you have one of the latest Microsoft SDK installed, you will find an example using the GetIpInterfaceTable

API in the C: \ Program Files \ Microsoft SDK \ Windows \ v7.0 \ Samples \ netds \ iphelp \ Netinfo directory . Just set brakepoint at line 270 in netinfo.c and you will see the InterfaceTable->Table[i].NlMtu

correct IP MTU of the corresponding interface adapter. If you check in the registry under HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ services \ Tcpip \ Parameters \ Interfaces {34407201-997C-41FF-9EBF-1B7D6DF92B38} the value of which is MTU REG_DWORD for your interface card ({3440CFF-41 -1B7D6DF92B38} in my case), it should be the same value.

The function GetIpInterfaceTable

has been around since Vista, but as you can see from the name, the PMIB_IPINTERFACE_TABLE

values ​​derived from the TCP adapter MIB information, see (Windows DDK). A few years ago it was not a DLL helper for IP addresses at all and to get the information displaying IpConfig.exe one has to use CreateFile and DeviceIoControl to provide such information from the TCP TDI driver (see Constants such as L "\ Device \ Tcp "and IOCTL_TCP_QUERY_INFORMATION_EX in tcpioctl.h). So maybe you can give the same information about Windows XP, but it doesn't matter.

+3


a source







All Articles