MTU несовпадение между GetIfEntry и netsh
Я работаю над программным обеспечением псевдотранспортного уровня, которое работает по протоколу UDP, обеспечивая надежную передачу, ориентированную на соединение, в качестве альтернативы TCP. Чтобы максимизировать эффективность сети, мы запрашиваем MTU "лучшего" сетевого адаптера при инициализации.
MIB_IFROW row = {0};
row.dwIndex = dwBestIfIndex;
dwRes = GetIfEntry(&row);
Поиск в Интернете Я обнаружил, что вы можете использовать следующие команды netsh для запроса этого же значения из командной строки (не API C++)
netsh interface ipv4 show interfaces
netsh interface ipv4 show subinterfaces
Беспокойство вызывает то, что хотя row.dwMtu может быть установлен на 1500, отслеживание сетевого трафика на отправляющем ноутбуке показывает, что наши пакеты фрагментированы в пакеты по 1300 байт.NETsh также сообщает, что MTU составляет 1300.
Очевидно, что значение, сообщаемое командой netsh, является фактическим используемым значением. Кто-нибудь знает, какой API я могу вызвать, чтобы получить те же значения, что и netsh?
1 ответ
Существуют локальный размер MTU и Path MTU (см. RFC 1191). Вы можете использовать такие команды, как
ping -f -l 1464 www.stackru.com
ping -f -l 1465 www.stackru.com
определить путь MTU. Учитывайте размер заголовков пакетов ICMP и заголовков IP. См. Path MTU Discovery для решения API.
ОБНОВЛЕНО: Пожалуйста, не надо больше таких вопросов! Мне было очень интересно найти ответ, и я трачу на это несколько часов. Но... я нашел! Чтобы получить правильное значение размера MTU, вы должны использовать GetIpInterfaceTable
API, который возвращает PMIB_IPINTERFACE_TABLE
структура, которая имеет массив MIB_IPINTERFACE_ROW
структур. MIB_IPINTERFACE_ROW
шапка InterfaceIndex
который помогает вам идентифицировать IP-интерфейс, он такой же, как и в других известных функциях IP Helper. Вы также можете использовать ConvertInterfaceLuidToNameW
функция для получения из другого поля InterfaceLuid
имя интерфейса.
Но самое интересное это поле НлМту
typedef struct _MIB_IPINTERFACE_ROW {
ADDRESS_FAMILY Family;
NET_LUID InterfaceLuid;
NET_IFINDEX InterfaceIndex;
// ...
ULONG NlMtu;
// ...
};
В документации (см. http://msdn.microsoft.com/en-us/library/aa814496(v=VS.85).aspx) он описывается как " Размер MTU сетевого уровня в байтах ". Тот же текст и больше не найдете также в документации Windows Driver Kit (см. http://msdn.microsoft.com/en-us/library/ff559254(VS.85).aspx). Это поле NlMtu - то, что вы ищете. Мой компьютер, например, подключен к Интернету через маршрутизатор DSL и NlMtu
не 1500, как это было бы без маршрутизатора, но вместо этого имеет правильное значение 1492. В вашем случае это должно быть 1300.
Если у вас установлена одна из последних версий Microsoft SDK, вы можете найти в каталоге C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\netds\iphelp\Netinfo пример использования GetIpInterfaceTable
API. Просто установите точку торможения на линии около 270 в файле netinfo.c, и вы увидите в InterfaceTable->Table[i].NlMtu
правильное значение IP MTU соответствующего интерфейсного адаптера. Если вы проверите в реестре в разделе HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Tcpip\Parameters\Interfaces{34407201-997C-41FF-9EBF-1B7D6DF92B38}, у какого значения есть MTU REG_DWORD для вашей карты интерфейсов ({34407201-997BF-41BF-416-RUF-41BF-416FF-41BF-416FF-41BF-416FBF-416-FF-367-FF-41BF-416FF-41BF-416F6BF-416F6BF) } в моем случае) это должно быть одинаковое значение.
Функция GetIpInterfaceTable
существует, начиная с Vista, но как вы можете видеть из названия PMIB_IPINTERFACE_TABLE
значения поступают из информации MIB TCP-адаптера (см. Windows DDK). Несколько лет назад это была вообще не DLL-помощник DLL, и для получения информации, отображающей IpConfig.exe, необходимо использовать CreateFile и DeviceIoControl для выдачи такой информации из драйвера TCP TDI (см. Константы, такие как L"\Device\Tcp" и IOCTL_TCP_QUERY_INFORMATION_EX в tcpioctl.h). Так что, возможно, можно дать ту же информацию о Windows XP, но это не важно.