22.06.11 @ 18:53 Oleg Cherevko wrote:

На данный момент ng_netflow, в силу его внутреннего устройства, до этого идеала далеко. У него проблемы с broadcast- и multicast-трафиком, с пакетами, отсеяными firewall'ом, с ipfw fwd, с локальным трафиком и,

С fwd можно справляться, навешивая ноду непосредственно на ng_ether, а не через файрвол, и включая соответствующие флаги в конфигурации узла, чтобы не считало дважды тот же трафик.

возможно, еще с чем-то, до чего я пока не добрался. Справедливости ради следует сказать, что все вышеперечисленное обычно не является определяющим в общем объеме трафика, так что ng_netflow для основного трафика на машине без особых изысков в конфигурации -- вполне рабочий инструмент. Но мне хочется перевести его из фазы "make it work" в фазу "make it right", (ну а затем и в "make it fast", если понадобится).

Боюст, это опять потребует архитектурных изменений :)

         msg netflow: setconfig { iface=0 conf=7 }
         msg netflow: setconfig { iface=1 conf=7 }
[...]
Посылаем 1 UDP пакет на 127.0.0.1:8192 (этот UDP-порт никто не слушает):

 >traceroute -e -q1 -M5 -m5 -p8192 127.0.0.1
traceroute to 127.0.0.1 (127.0.0.1), 5 hops max, 40 byte packets
  5  localhost (127.0.0.1)  0.062 ms

Смотрим, что появилось в netflow:

 >flowctl netflow show | fgrep -e Src -e 127.0.0.1
SrcIf SrcIPaddress DstIf DstIPaddress Pr SrcP DstP Pkts (null) 127.0.0.1 lo0 127.0.0.1 17 b171 2000 1 lo0 127.0.0.1 lo0 127.0.0.1 17 b171 2000 1 (null) 127.0.0.1 lo0 127.0.0.1 1 0000 0000 1 lo0 127.0.0.1 lo0 127.0.0.1 1 0000 0000 1

Видим ушедший пакет и icmp port unreachable ему навстречу, но и то и другое -- в виде 2-х flow, отличающихся source interface'ом.

Для сравнения, если проделать то же самое, но отправить пакет за пределы машины, на другую машину, где порт тоже никто не слушает, такого эффекта не будет:

 >traceroute -e -q1 -M5 -m5 -p8192 10.1.0.7
traceroute to 10.1.0.7 (10.1.0.7), 5 hops max, 40 byte packets
  5  10.1.0.7 (10.1.0.7)  0.182 ms
 >flowctl netflow show | fgrep -e Src -e 10.1.0.7
SrcIf SrcIPaddress DstIf DstIPaddress Pr SrcP DstP Pkts (null) 10.1.0.14 vlan3 10.1.0.7 17 b17e 2000 1 vlan3 10.1.0.7 lo0 10.1.0.14 1 0000 0000 1

Для разнообразия отправим еще пакет по адресу, на котором нет никакой машины:

 >traceroute -e -q1 -M5 -m5 -p8192 10.1.0.15
traceroute to 10.1.0.15 (10.1.0.15), 5 hops max, 40 byte packets
  5  *
 >flowctl netflow show | fgrep -e Src -e 10.1.0.15
SrcIf SrcIPaddress DstIf DstIPaddress Pr SrcP DstP Pkts (null) 10.1.0.14 vlan3 10.1.0.15 17 b194 2000 1


Мда. Изначально я было хотел попросить прокомментировать эти мои наблюдения, но так долго писал весь этот длинный текст, что аж сам понял, почему оно так себя ведет. :) Сначала в ng_netflow попадает out-пакет идущий на 127.0.0.1, у него SrcIf=(null), как и положено out-пакетам, потом он уходит в lo0 и тут же снова принимается из lo0, но SrcIf уже, понятное дело, lo0, а поскольку SrcIf входит в определение того, что такое flow, то вот и образуется

Нет, вот в этом месте неправильно.

второй flow для того же пакета, что формально правильно, но по сути неправильно, ибо в результате такой трафик учитывается дважды. Теперь вопрос, что можно с этим сделать? Ну, кроме как просто не отправлять в ng_netflow out-пакеты, идущие на lo0? Может у кого есть какие идеи?

Там на самом деле происходит следующее: у узла в конфигурации включен флаг NG_NETFLOW_CONF_ONCE (conf=7), и узел честно помечает прошедший через него пакет mbuf-тегом "пакет уже побывал на netflow-узле с id=..."; в норме это приведет к тому, что в следующий раз этот пакет будет отсеян еще до разбора, с какого он интерфейса, и с какого flow.

Однако далее пакет с этим тегом отправляется в if_lo, а там основная функция обработчик начинается вот так:

int
if_simloop(struct ifnet *ifp, struct mbuf *m, int af, int hlen)
{
        int isr;

        M_ASSERTPKTHDR(m);
        m_tag_delete_nonpersistent(m);

То есть, почти все теги первым делом удаляются, пакет как бы становится чистым, и потом "поступает на вход". И дальше, когда он снова попадает в ng_netflow, тот уже не обнаруживает на нем своей метки, и вот только тогда вступает в действие то правило, что интерфейс у flow другой.

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

исправить в /usr/src/sys/netgraph/netflow/ng_netflow.с и заменить строчку

                mtag = m_tag_alloc(MTAG_NETFLOW, MTAG_NETFLOW_CALLED,

на

mtag = m_tag_alloc(MTAG_NETFLOW, MTAG_NETFLOW_CALLED | MTAG_PERSISTENT,

Ну и как обычно, send-pr с соответствующим полем fix, особенно если ничего не сломается.

--
WBR, Vadim Goncharov

Ответить