Несоответствие MTU между GetIfEntry и netsh
-
04-10-2019 - |
Вопрос
Я работаю над программным обеспечением псевдотранспортного уровня, которое работает по протоколу UDP, обеспечивая надежную передачу, ориентированную на соединение, в качестве альтернативы TCP.Чтобы максимизировать эффективность сети, мы запрашиваем MTU "лучшего" сетевого адаптера при инициализации.
MIB_IFROW row = {0};
row.dwIndex = dwBestIfIndex;
dwRes = GetIfEntry(&row);
Поискав в Интернете, я обнаружил, что вы можете использовать следующие команды netsh для запроса этого же значения из командной строки (не C ++ API)
netsh interface ipv4 show interfaces
netsh interface ipv4 show subinterfaces
Проблема заключается в том, что, хотя row.dwMtu может быть установлен на 1500, отслеживание сетевого трафика на отправляющем ноутбуке показывает, что наши пакеты фрагментированы на пакеты размером 1300 байт.netsh также сообщает, что MTU равен 1300.
Очевидно, что значение, сообщаемое командой netsh, является фактически используемыми значениями.Кто-нибудь знает, какой API я могу вызвать, чтобы получить те же значения, что и netsh?
Решение
Существуют локальный размер MTU и MTU пути (см. RFC 1191).Вы можете использовать такие команды, как
ping -f -l 1464 www.stackoverflow.com
ping -f -l 1465 www.stackoverflow.com
чтобы определить MTU пути.Примите во внимание размер заголовка ICMP-пакетов и IP-заголовков.Видишь Обнаружение MTU пути для решения API.
ОБНОВЛЕННЫЙ:Пожалуйста, больше никаких подобных вопросов!Мне было очень интересно найти ответ, и я потратил на это несколько часов.Но...Я нашел!Чтобы получить правильное значение размера MTU, вы должны использовать GetIpInterfaceTable
API, который возвращает PMIB_IPINTERFACE_TABLE
структура, которая имеет массив MIB_IPINTERFACE_ROW
структуры. MIB_IPINTERFACE_ROW
шляпа InterfaceIndex
который помогает вам идентифицировать IP-интерфейс, он такой же, как и в других хорошо известных вспомогательных функциях IP.Вы также можете использовать ConvertInterfaceLuidToNameW
функция для получения из другого поля InterfaceLuid
имя интерфейса.
Но самое интересное заключается в том, что NlMtu поле
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 (см. http://msdn.microsoft.com/en-us/library/ff559254 (ПРОТИВ 85).aspx).Это поле NlMtu это то, что вы ищете.Например, мой компьютер подключен к Интернету через DSL-маршрутизатор и NlMtu
это не 1500, как было бы без маршрутизатора, а вместо этого имеет правильное значение 1492.В вашем случае это должно быть 1300.
Если у вас установлена одна из последних версий Microsoft SDK, то вы найдете в C:\Program Файлы\Microsoft SDKs\Windows\версия 7.0\Образцы
etds\iphelp
etinfo каталог - пример, который использует GetIpInterfaceTable
API.Просто установите точку торможения на линии около 270 в netinfo.c файл, и вы увидите в InterfaceTable->Table[i].NlMtu
правильное значение IP MTU соответствующего интерфейсного адаптера.Если вы подтвердите это в реестре в разделе HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services cpip\Parameters\Interfaces{34407201-997C-41FF-9EBF-1B7D6DF92B38 } какое значение имеет MTU REG_DWORD для вашей интерфейсной платы ({34407201-997C-41FF-9EBF-1B7D6DF92B38} в моем случае), это должно быть то же значение.
Функция GetIpInterfaceTable
существует, начиная с Vista, но, как вы можете видеть из названия PMIB_IPINTERFACE_TABLE
значения взяты из MIB-информации TCP-адаптера, см. (Windows DDK).Несколько лет назад это вообще не было IP helper DLL и для получения информации, которая отображается IpConfig.exe нужно использовать CreateFile и DeviceIoControl для предоставления такой информации из драйвера TCP TDI (см. Константы типа L"\ Device cp" и IOCTL_TCP_QUERY_INFORMATION_EX в tcpioctl.h).Так что, возможно, можно предоставить ту же информацию и в Windows XP, но это не важно.