Давай продолжим начал серия статей о NDIS. В этой теме мы рассмотрим версии NDIS и принципы передачи пакетов между драйверами «стека» и архитектурой NET_BUFFER.
Введение
Для начала давайте рассмотрим версии NDIS и их особенности в связи с тем, что их чуть больше одной.
- НСИС 5.1. Windows XP, Server 2003. Большинство драйверов написано под эту версию и портировать их никто не берется, т.к.
портировать там особо нечего - почти все придется переписывать;
- НСИС 5.2. Windows Сервер 2003 с пакетом обновления 2. Скорее всего, для этой версии не написаны драйвера, потому что.
Драйвера от 5.1 здесь работают нормально;
- НДИС 6.0. Виндоус виста.
подсистема NDIS в Windows Vista претерпела огромные изменения, были добавлены новые типы драйверов, улучшена производительность;
- НСИС 6.1. Windows Vista SP2, Server 2008. Та же история, что и с NDIS 5.2;
- НСИС 6.20. Windows 7. Незначительные изменения относительно NDIS 6.0, поддержка последней в режиме эмуляции.
Поддерживать это нет смысла.
Microsoft также прекращает поддержку NDIS 5.1 в Windows 8. Как видно из списка, между NDIS 5.x и NDIS 6.x существует огромный разрыв.
Фактически, все, что у них было общего, — это архитектурная особенность и библиотека функций.
Все остальные компоненты были переработаны для повышения производительности.
Кстати, этот прирост унаследован на 20%, так что хоть в чем-то Vista лучше своей предшественницы.
В архитектуру добавлены драйверы фильтров, которых так не хватало в предыдущих версиях.
Кардинально изменились принципы передачи пакетов, а именно: если раньше промежуточный драйвер должен был реализовать как минимум три функции приема и отправки пакетов, то теперь количество этих функций в любом случае равно одной.
Это стало возможным благодаря новой архитектуре передачи пакетов под названием NET_BUFFER. Мы поговорим об этом ниже.
NET_BUFFER архитектура
Так что же это такое? По сути, NET_BUFFER — это замена предыдущего NDIS_BUFFER, но обо всем по порядку.Что случилось? Драйвер реализует три функции отправки и получения пакетов.
По-русски назовем эти функции так:
- ПринятьПакет;
- Принять пакеты;
- ПодтвердитьПринятиеПакетов;
- ОтправитьПакет;
- ОтправитьПакеты;
- Подтвердите отправку посылки.
А для промежуточных драйверов вообще разбирать пакет до ядра, собирать свой (потому что чужое все равно трогать нельзя) и отправлять.
Поэтому в NDIS 6.x появилась архитектура NET_BUFFER. Согласно этой архитектуре достаточно реализовать по 2 функции для приема и отправки пакета (теперь это не пакет, а буфер, поэтому ниже воспринимайте эти слова как синонимы, говоря о NDIS 6+).
Да, насчет 2х я соврал, но эти двое ничего особенного не делают и переходят от драйвера к драйверу без изменений.
Итак, функции приема и отправки, их подписи я напишу здесь для общего понимания:
Первые параметры по сути представляют собой указатель, который передаст вам NDIS. При регистрации драйвера, а точнее при присоединении его к очереди, можно указать этот самый указатель.VOID FilterSendNetBufferLists( IN NDIS_HANDLE FilterModuleContext, IN PNET_BUFFER_LIST NetBufferLists, IN NDIS_PORT_NUMBER PortNumber, IN ULONG SendFlags ); VOID FilterReceiveNetBufferLists( IN NDIS_HANDLE FilterModuleContext, IN PNET_BUFFER_LIST NetBufferLists, IN NDIS_PORT_NUMBER PortNumber, IN ULONG NumberOfNetBufferLists, IN ULONG ReceiveFlags );
Что.
В нашем распоряжении всегда есть ссылка на пользовательскую переменную, которая, как мы знаем, имеет неограниченную сферу применения.
Очень удобно.
Вторые параметры — это указатели на списки NET_BUFFER. Мы разберемся с этим позже.
Все остальные параметры используются редко, поэтому рассматривать их не будем.
Перейдем к самой архитектуре.
На рисунке ниже примерно представлена архитектура:
Каждый NET_BUFFER может описывать пакет, как показано на рисунке ниже:
Наша посылка хранится в затененном месте.
Как видите, это не обязательно непрерывный блок памяти; один пакет может быть разбросан по всему адресному пространству системы.
Также рекомендуется хранить пакеты в невыгружаемой памяти (для справки: при попытке доступа к страничной памяти по IRQL > = DISPATCH_LEVEL мы получим синий экран с кодом D1. DRIVER_IRQL_NOT_LESS_OR_EQUAL, самая распространенная ошибка авторов драйверов).
Сразу возникает вопрос: зачем оставлять пустое место перед упаковкой? Затем, когда IP-пакет приходит, он упаковывается в кадр Ethernet для отправки.
И чтобы не перестраивать это дело, заголовок Ethernet просто записывается перед пакетом.
Довольно задумчиво.
Тот же принцип реализован в драйверах верхнего уровня.
Вся информация о так называемом пространстве обратной засыпки (он же DataOffset), смещениях и длине буфера хранится в структуре NET_BUFFER. Еще хочу отметить, что размер буфера можно менять, т.е.
начало буфера можно переместить влево, а конец — вправо.
Это делается с помощью специальных функций, экспортируемых ядром NDIS.
Вместо заключения
В этой статье намеренно опущено огромное количество деталей, с которыми я столкнулся при исследовании подсистемы NDIS. Я их не публикую, потому что.количество материала, однако, не укладывается ни в какие разумные рамки.
При этом я пытаюсь пролить свет на некоторые ключевые особенности, которые считаю базовыми для понимания сути происходящего.
Дополнительную литературу читайте здесь: www.codemachine.com/article_ndis6nbls.html msdn.microsoft.com/en-us/library/ff564881 (v=vs.85).
aspx До скорого.
Теги: #NDIS #filter #реализация драйвера фильтра #C++ #KM #режим ядра #Разработка для Windows
-
Список Лучших Альтернатив Psiphon
19 Oct, 24 -
Больше Места В Воронеже
19 Oct, 24 -
Стандартная Модель Частиц Для Начинающих
19 Oct, 24 -
Мой Вклад В Коптостроение
19 Oct, 24