Сетевая подсистема netgraph была создана в 1996 году Джулианом Элисчером и Арчи Коббсом, как попытка решить ограниченную поддержку некоторого оборудования и протоколов в FreeBSD. Основная идея новой подсистемы – модульность, комбинация простых инструментов для реализации более сложного решения.
Netgraph строится на взаимодействии узлов (nodes), которые посредством крючков (hooks) создают пару захвата (одну для каждого узла). Крючок узла формируется в момент связывания и определяет, как узел может быть подключен. Данные идут в двух направлениях вдоль ребер (edges) от узла к узлу. Когда узел получает пакет данных, он его обрабатывает и затем отправляет другому узлу. Узел может быть источником/потребителем данных, например, если он связан с аппаратной частью, или может просто добавлять/удалять заголовки, выполнять мультиплексирование и т.п.
С каждой новой версией системы количество узлов увеличивалось. Так для FreeBSD 6.х уже были доступны модули, обеспечивающие поддержку: PPPoE, ATM, ISDN, Bluetooth, HDLC, EtherChannel, Frame Relay, L2TP и др. Система построена так, что добавить новый модуль очень легко. В новой версии FreeBSD 7.0 появились новые узлы: ng_car (алгоритмы ограничения трафика и rate-лимитов), ng_deflate (поддержка Deflate сжатия для PPP) и ng_pred1 (Predictor-1 сжатие для PPP).
Многие программы завязаны на netgraph. Например, реализация PPP для FreeBSD MPD (mpd.sf.net) использует интерфейс netgraph, благодаря чему большинство операций выполняется на уровне ядра системы, и тем самым повышается скорость работы.
Поддержка ядром
Как правило, специально включать поддержку netgraph в ядре не требуется. Все, что необходимо, доступно в виде модулей. В чем можно убедиться во время работы того же MPD при помощи команды /sbin/kldstat. Просмотреть все имеющиеся KLD модули узлов, можно введя команду:
# ls /boot/kernel/ng_*.ko

Плюс еще модуль netgraph.ko, который является основным. При пересборке ядра следует включить группу параметров, найти которую просто:
# grep NETGRAPH /usr/src/sys/conf/NOTES
options NETGRAPH # поддержка netgraph
options NETGRAPH_PPP # поддержка PPP в netgraph
options NETGRAPH_PPTPGRE # поддержка gre-туннелирования
…
Каждый узел netgraph может адресоваться при помощи абсолютного или относительного адреса. Абсолютный адрес получается из имени узла или его ID. Если узел сопоставлен с устройством, то он обычно имеет такое же имя, как и устройство. В этом случае для адресации используется адрес, состоящий из имени устройства и двоеточия. Например, устройству fxp0 будет сопоставлен узел fxp0, к которому следует обращаться, введя «fxp0:». К имени узла можно добавлять связанные крючки:
fxp0:hook1.hook2
Адрес вроде «.:» или «.» всегда показывает на локальный узел. Как в имени хука, так и в имени узла использовать знаки точки и двоеточия по понятным причинам запрещено. Если узел не получил имя, к нему можно обратиться, используя его уникальный номер ID, заключенный в квадратные скобки. Например, к ID 00000002 можно обратиться так «[00000002]:».
Каждый хук также имеет уникальное имя, отражающее его цель и использующееся только в контексте данного узла. Поэтому на разных узлах можно создавать крючки с одинаковым названием. Для некоторых типов (например, ksockets) формат имени не может быть произвольным и строго определен. Относительный адрес состоит только из имен хуков.
Еще один важный момент. На сегодня существует 15 типов узлов, имеющих свои характеристики и соответственно назначения. Изучив особенности каждого типа, легко выбрать узел для решения конкретной задачи. Например, тип узла echo всегда принимает подключения через любой хук. Полученный пакет просто отправляется назад в виде ответа. Такой тип узла полезен при отладке. Теперь смотрим описание узла ng_ether — «Ethernet netgraph node type«. Тип Ethernet означает, что данный узел фактически является netgraph-копией физического интерфейса Ethernet с возможностью перехватывать и отправлять фреймы с этого интерфейса. Его можно использовать, например, для реализации PPP поверх Ethernet (PPPoE). Узел состоит из трех хуков: lower (или divert), upper и orphans, которые отвечают за определенный уровень работы. Или вот еще узел ng_bridge – «Ethernet bridging netgraph node type». Не трудно догадаться, что этот тип позволяет организовать сетевой мост на Ethernet интерфейсе.
Каждый тип и конкретный модуль может иметь большое количество параметров и настроек, поэтому реализовано управление при помощи управляющих команд. Такие сообщения делятся на основные, поддерживаемые всеми модулями (определены в netgraph/ng_message.h), и индивидуальные, полное их описание есть только в конкретном man (кстати, иногда недостоверное).
//
А не было бы более логичным опубликовать эту заметку в разделе BSD?
//
Слишком мало информации, чтобы сформировать какое-либо мнение о Netgraph. Про адресацию — достаточно доходчиво. В целом если приложить к статье превод статьи Коббса http://citrin.ru/netgraph/ — то неплохо.
//
Чуть позже будет и продолжение. Не успеваю за всем.