MTU несоответствие между GetIfEntry и netsh - PullRequest
3 голосов
/ 07 мая 2010

Я работаю над программным обеспечением псевдотранспортного уровня, которое работает по протоколу 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 Ответ

3 голосов
/ 07 мая 2010

Существуют локальный размер MTU и Path MTU (см. RFC 1191). Вы можете использовать такие команды, как

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

для определения MTU пути. Учитывайте размер заголовков пакетов ICMP и заголовков IP. См. Path MTU Discovery для решения API.

ОБНОВЛЕНО : Пожалуйста, больше нет таких вопросов! Мне было очень интересно найти ответ, и я трачу на это несколько часов. Но ... я нашел! Чтобы получить правильное значение размера MTU, вы должны использовать GetIpInterfaceTable API, который возвращает PMIB_IPINTERFACE_TABLE структуру, которая имеет массив MIB_IPINTERFACE_ROW структур. MIB_IPINTERFACE_ROW hat InterfaceIndex, которая помогает идентифицировать IP-интерфейс, такая же, как и в других известных функциях IP Helper. Вы также можете использовать функцию ConvertInterfaceLuidToNameW для получения из другого поля InterfaceLuid имени интерфейса.

Но самое интересное - это NlMtu field

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 SDK \ 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-416-RUF-416-RUF-416-RUF-416-RUF-416-FF-366-RUF-416-FF-366-RUF-416-FF-366-RUF-416-RUF-416-RUF-416-RUF-366-RU) } в моем случае) это должно быть то же значение.

Функция 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, но это не важно.

...