Ключевые слова:freebsd, netgraph, (найти похожие документы)
From: Бесядовский Роман Александрович
Newsgroups: http://www.iplab-nnz.ru
Date: Mon, 22 Apr 2005 14:31:37 +0000 (UTC)
Subject: Data flow между системой, сетевой картой и netgraph через ноду ng_ether.
Оригинал:
http://www.iplab-nnz.ru/blog/index.php?op=ViewArticle&articleId=28&blogId=1
-----
Все разработки опробованы на компактном сервере Favourite IS на основе ОС UNIX,
предназначенном для предоставления Интернет-доступа и Интернет-сервисов.
Ссылка в Интернет: http://is.nnz.ru
Взять сервер Favourite IS на тестирование. Mail to: Boginsky@nnz.ru <mailto:Boginsky@nnz.ru.>
-----
Data flow между системой, сетевой картой и netgraph через ноду ng_ether.
Знакомство с netgraph было вызвано необходимостью подсчёта трафика -
ссылки в google упорно выдавали ng_ipacct, и чтобы настроить подсчёт
трафика нужно было понять что это такое. Прочитав понятную и доступную
статью 'All about Netgraph' http://www.daemonnews.org/200003/netgraph.html,
(русский перевод лежит здесь http://citrin.ru/netgraph/), и, посмотрев
примеры в скриптах, мне показалось, что я понял, как это настроить
для работы.
Оказалось, понял не окончательно - столкнувшись с 'нестандартным'
ng_gif я не знал с какой стороны подойти и как его прикручивать.
Note: На данный момент проблема с подсчётом трафика через ng_gif всё
ещё актуальна и её решение мне не известно. Данная заметка, содержит
моё понимание процесса прохождения данных от устройства через netgraph
и далее в 'Upper Layers' и в обратном направлении. Она появилась на
свет, в связи с тем, что прочитав man pages я не сумел понять процесс,
и поэтому пришлось лезть в исходники. То что я там нашёл и следует
ниже.
Схема прохождения данных на примере ng_ipacct.
Пакет приходит на устройство, ничинает обрабатываться.
В /usr/src/net/if_ethersubr.c
Ищем процедуру ether_input()
/* Handle ng_ether(4) processing, if any */
if (ng_ether_input_p != NULL) {
(*ng_ether_input_p)(ifp, &m);
if (m == NULL)
return;
}
.
. // Skip some C code
.
ether_demux(ifp, m)
Т.е. если определён поинтер на процедуру ng_ether_input_p, то вызываем
эту процедуру, т.е. помещаем данные в netgraph.
Важно!!! Если процедурина установил m в NULL, то прекращаем обработку
данных (см ниже)
Идём в /usr/src/netgraph/ng_ether.c
Ищем ng_ether_input (ng_ether_input_p это ссылка на ng_ether_input)
/* If "lower" hook not connected, let packet continue */
if (priv->lower == NULL)
return;
NG_SEND_DATA_ONLY(error, priv->lower, *mp); /* sets *mp = NULL */
Тут всё понятно, если Lower хук не подключен, то просто выходим.
Важно!!! При свободном lower хуке мы возвращаемся в ether_input и идёт
дальнейшая обработка данных без netgraph (т.к. m (mp - pointer на m)
не установлен в NULL).
Далее, после ng_tee мы получим эти данные на upper хук.
Ищем ng_ether_rcv_upper
/* Route packet back in */
ether_demux(priv->ifp, m);
Т.е. делаем то-же что и при отсутвии netgrapf (см первый листинг).
Все данные, получаемые через upper, обрабатываются как 'принятые' с
сетевой карты. В кавычках, т.к. туда можно просто записать данные и
они обработаются как полученные из сетки.
Теперь в обратном направлении.
В /usr/src/net/if_ethersubr.c
Ищем процедуру ether_output()
/* Handle ng_ether(4) processing, if any */
if (ng_ether_output_p != NULL) {
if ((error = (*ng_ether_output_p)(ifp, &m)) != 0) {
bad: if (m != NULL)
m_freem(m);
return (error);
}
if (m == NULL)
return (0);
}
/* Continue with link-layer output */
return ether_output_frame(ifp, m);
Опять, если m сброшен в NULL прекращаем обработку. Если вернули ошибку
- прекращаем обработку, возвращаем ошибку. В противном случае -
выкидываем через девайс.
Идём в /usr/src/netgraph/ng_ether.c
Ищем ng_ether_output
/* If "upper" hook not connected, let packet continue */
if (priv->upper == NULL)
return (0);
/* Send it out "upper" hook */
NG_SEND_DATA_ONLY(error, priv->upper, *mp);
return (error);
Т.е. если upper подключен - то данные туда. Если нет, продолжаем
работать в ether_output.
Далее от tee получаем это-же через lower и
/* Send it on its way */
return ether_output_frame(ifp, m);
Получаем то-же самое.
Т.е. словами, входящий траффик
* Данные приходят на сетевую карту
* Вызывается ether_input()
* Оттуда передаём данные в netgraph.
* Если netgraph отработал, то на выход (предпологается что netgraph
отдал данные далее)
* Если нет, передаём данные дальше -> ether_demux
И исходящий траффик
* Данные приходят из системы
* Вызываем ether_output()
* Оттуда данные в netgraph Если netgraph отработал, то на выход
(предпологается что netgraph отдал данные в сетевую карту)
* Если нет, передаём данные в сетевую карту ether_output_frame
Схема прохождения данных через систему netgraph и ноду ng_ipacct
Данные приходят сверху, синим цветом - путь до ветвления ng_tee и
далее к node подсчёта траффика, карсным - дальнейший путь данных.
Входящий трафик:
Исходящий трафик:
Бесядовский Роман Александрович
Системный администратор отдела телекоммуникаций и
Интернет решений ЗАО "Ниеншанц"