Операционная система ЗОСРВ «Нейтрино» > Руководство разработчика > Интерфейсы различных подсистем > Сетевая подсистема > Общие сведения > Сетевые драйверы, их типы, разработка и отладка



Сетевые драйверы, их типы, разработка и отладка

Поддержка в сетевом стеке драйверов различных типов

В этой главе:

Типы сетевых драйверов
Различия между портированными из NetBSD драйверами и современными драйверами
Различия между legacy драйверами и другими
Загрузка и выгрузка драйвера
Отладка драйвера
Проблемы с совместно используемыми (разделяемыми) прерываниями
Создание нового драйвера
Отладка драйвера с использованием gdb
Дамп отладочной информации для 802.11-драйверов
Jumbo-фреймы и аппаратное вычисление контрольных сумм
Заполнение пакетов Ethernet
Поддержка функции Transmit Segmentation Offload (TSO)

Типы сетевых драйверов

Сетевой стек поддерживает следующие типы драйверов:

Современные драйвера можно отличить от legacy драйверы по имени:

Драйверы NetBSD менее тесно интегрированы в стек io-pkt-*. Поскольку в операционной системе NetBSD они работают с отключенными прерываниями, в них, как правило, реже возникают неполадки с мьютексами при отправке и приеме пакетов. Если драйвер напрямую портирован из NetBSD, стек по умолчанию работает в однопоточном режиме для предотвращения возможных проблем с синхронизацией передачи и приема в многопоточной среде. Если драйвер тщательно проверен и его методы синхронизации работают корректно, при его присоединении к стеку можно указать флаг, который разрешает выполнение в многопоточном режиме.


Caution: Если один драйвер работает в однопоточном режиме, все остальные драйверы также будут работать в однопоточном режиме.

Все современные драйверы и портированные из NetBSD подключаются непосредственно к стеку схожим образом. Legacy драйверы взаимодействуют со стеком io-pkt-* с помощью интерфейса-прокладки ( shim), который преобразует двоичный интерфейс устаревшего стека в совместимый интерфейс io-pkt-*. В состав ЗОСРВ «Нейтрино» входит специальный драйвер-прокладка devnp-shim.so, который автоматически загружается при запуске legacy драйвера и обеспечивает двоичную совместимость с существующими legacy драйверами. Таким образом, эти драйверы также не имеют тесного сопряжения со стеком — например, они не могут использовать функции динамической настройки среды передачи и пакеты Jumbo. Поскольку эти драйверы работают в контексте устаревшего стека, их эффективность ниже, чем у современных драйверов. Помимо приема и передачи пакетов, драйверы устройств могут интегрировать функции ускорения аппаратного кодирования непосредственно в стек.

Информацию о конкретных драйверах можно найти в разделах:

Различия между портированными из NetBSD драйверами и современными драйверами

Существует тонкая грань между драйверами, которые написаны специально для стека io-pkt-*, и портированными драйверами. Если перенос выполнен тщательно, функциональные возможности конечного и исходного драйверов практически одинаковы, однако имеется ряд нюансов:

Различия между legacy драйверами и другими

Между legacy драйверами и другими драйверами существуют следующие различия:

Загрузка и выгрузка драйвера

Драйверы можно загружать в сетевой стек io-pkt-* с помощью командной строки:

io-pkt-v4-hc -di82544

Эту команду можно применять как к современным драйверам, так и к legacy. Стек автоматически определяет тип драйвера и загружает библиотеку devnp-shim.so для legacy драйверов.


Note: Можно не задавать полное имя устройства в командной строке при условии, что все драйверы находятся в каталогах, указанных в переменной окружения LD_LIBRARY_PATH.

Также можно монтировать драйвер стандартным способом с помощью утилиты mount:

mount -Tio-pkt /lib/dll/devnp-i82544.so

Для обратной совместимости с существующими сценариями команда mount по-прежнему поддерживает параметр io-net:

mount -Tio-net /lib/dll/devnp-i82544.so

Стандартным способом удаления драйвера из стека является команда ifconfig iface destroy. Пример:

ifconfig wm0 destroy

Отладка драйвера

При возникновении неполадок первым инструментом для отладки любых сетевых драйверов (помимо ifconfig) является утилита nicinfo. Она позволяет определять корректность согласования параметров канального уровня драйвером и наличие/отсутствие приема/передачи пакетов.

Убедитесь, что демон slogger работает, и после возникновения неполадки запустите утилиту sloginfo, чтобы определить наличие диагностической информации от драйвера. Чтобы получать от драйвера более подробную диагностическую информацию, следует передать ему командно-строковый параметр verbose. Многие драйверы поддерживают различные уровни детализации диагностической информации; можно попробовать передать драйверу параметр типа verbose=10.

Если драйвер портирован из стека NetBSD и не поддерживает функции утилиты nicinfo, можно воспользоваться командой netstat -I iface, чтобы получить краткую информацию о приеме и передаче пакетов. Команда ifconfig возвращает краткую информацию об устройстве, а команда ifconfig -v – более подробную информацию.

Проблемы с совместно используемыми (разделяемыми) прерываниями

Совместное использование одного прерывания несколькими устройствами — технически элегантное решение, однако оно полезно лишь при условии, что в системе недостаточно линий прерываний. Более того, оно может вызывать проблемы. Например, если драйвер не работает (не принимает пакеты), следует проверить, использует ли он прерывание совместно с другим устройством, и если да, перенастроить плату таким образом, чтобы отключить этот механизм.

Совместное использование прерываний часто используется без необходимости (т.е. при наличии свободных прерываний) и снижает производительность системы, поскольку при возникновении прерывания all использующие его устройства должны проверять, требуется ли обрабатывать его. Если изучить исходный код драйверов, можно увидеть, что некоторые из них действуют «правильно» — считывают регистры в обработчике прерывания и игнорируют прерывание от другого устройства. Тем не менее, многие драйверы работают иначе: они проверяют устройства с помощью механизма обработки событий на уровне потоков, что является неэффективным и снижает производительность системы.

При использовании шины PCI можно получать информацию о назначенных прерываниях с помощью команды pci -v.

Совместное использование прерываний может значительно увеличивать задержку их обработки в зависимости от алгоритма работы каждого драйвера. После возникновения прерывания ядро не разрешает его до тех пор, пока all обработчики не сообщают ядру о своем завершении. Таким образом, если один драйвер долго обрабатывает маскированное совместно используемое прерывание и в это время другое устройство генерирует такое же прерывание, длительность задержки его обработки неизвестна.

Совместное использование прерываний может вызывать неполадки, ухудшать производительность системы, повышать нагрузку на процессор и значительно увеличивать задержки. Этот механизм следует использовать только по необходимости. Следует убедиться, что при совместном использовании прерываний ваши драйверы действуют «правильно».

Создание нового драйвера

Исходный код, скачанный из нашего публичного репозитория https://git.kpda.ru/drivers/network, включает в себя техническую статью с описанием процедуры создания драйвера (см. README.md).

Отладка драйвера с использованием gdb

Чтобы отладить драйвер с помощью инструмента gdb, необходимо сначала проверить, что при компиляции исходного кода была включена отладочная информация. Если код драйвера размещен в подходящем каталоге дерева исходного кода, выполните следующие действия:

make CPULIST=x86 clean make CPULIST=x86 CCOPTS=-O0 DEBUG=-g install

Отладочная версия драйвера создана; теперь можно запустить инструмент gdb и задать точку останова в функции main() бинарного файла io-pkt-*.


Note: Не забудьте указать драйвер в аргументах и проверьте, что переменные окружения PATH и LD_LIBRARY_PATH заданы корректно.

После достижения точки останова в функции main(), выполните команду sharedlibrary в отладчике gdb. Вы увидите загруженную библиотеку libc. Задайте точку останова в функции dlsym(). В момент ее достижения драйвер загружен, но стек io-pkt-* еще не выполнил первое обращение к нему. Выполните команду set solib-search-path, добавьте путь к драйверу, а затем еще раз выполните команду sharedlibrary. Отладчик загрузит символы для драйвера, после чего можно задать точку останова в точке начала отладки.

Дамп отладочной информации для 802.11-драйверов

Уровень 802.11 стека может создавать дампы с отладочной информацией. Включение и выключение дампирования осуществляется с помощью настроек sysctl. Если выполнить команду:

sysctl -a | grep 80211

для драйвера Wi-Fi, будут отображены переменные net.link.ieee80211.debug и net.link.ieee80211.vap0.debug. Включите вывод отладочной информации с помощью команд:

sysctl -w net.link.ieee80211.debug = 1 sysctl -w net.link.ieee80211.vap0.debug=0xffffffff

Теперь можно просмотреть журнал отладки утилитой sloginfo.

Jumbo-фреймы и аппаратное вычисление контрольных сумм

В отличие от обычных пакетов, Jumbo пакеты включают в себя более 1500 байт данных. У них нет четкого определения, и разработчики используют пакеты разной длины. Для применения Jumbo-фреймов необходимо, чтобы их поддерживали стек протоколов, драйверы и сетевые коммутаторы:

Использование Jumbo-фреймов значительно повышает эффективность передачи данных через стек io-pkt-*, благодаря уменьшению затрат времени на обработку заголовков пакетов.

Пример настройки Jumbo-фреймов в драйвере:

ifconfig wm0 ip4csum tcp4csum udp4csum ifconfig wm0 mtu 8100 ifconfig wm0 10.42.110.237

Для достижения максимальной производительности мы также включили функцию аппаратного вычисления контрольных сумм принимаемых и отправляемых пакетов и выбрали произвольную длину Jumbo пакета — 8100 байт. Следует иметь в виду, что стек io-pkt-* по умолчанию выделяет области размером 2 Кбайт для буферов пакетов. Этот механизм эффективен, если размер пакетов составляет 1500 байт, однако при получении Jumbo-фрейма размером 8 Кбайт выделяются четыре связанных области. Для повышения производительности можно указать стеку io-pkt-*, что мы будем использовать Jumbo пакеты:

io-pkt-v6-hc -d i82544 -p tcpip \ pagesize=8192,mclbytes=8192

С помощью параметров pagesize и mclbytes мы даем стеку команду выделять непрерывные буферы размером 8 Кбайт (которые могут занимать две соседние страницы размером 4 Кбайт, что вполне рационально). Это снижает затраты времени на обработку пакетов, увеличивает пропускную способность и уменьшает нагрузку на процессор.

Заполнение пакетов Ethernet

Если длина пакета Ethernet составляет менее ETHERMIN байт, для соблюдения минимальной длины можно воспользоваться механизмом заполнения пакета. Во избежание снижения производительности драйвер не заполняет пакеты самостоятельно, а делегирует эту задачу устройству, если оно может выполнить ее. Данные, которыми заполняется пакет, определяются устройством.

Поддержка функции Transmit Segmentation Offload (TSO)

Функция Transmit Segmentation Offload (TSO) поддерживается некоторыми современными сетевыми платами (примеры см. в статье http://en.wikipedia.org/wiki/Large_segment_offload). Разбиение крупного IP-пакета на блоки MTU осуществляется не стеком, а драйвером, что значительно снижает нагрузку на процессор при передаче больших объемов данных.

Чтобы определить, поддерживает ли драйвер функцию TSO, можно ввести команду ifconfig и просмотреть раздел функций передачи интерфейса. tso будет указана в списке доступных функций. Для активации функции TSO в драйвере можно ввести следующие команды:

ifconfig wm0 tso4 ifconfig wm0 10.42.110.237




Предыдущий раздел: перейти