14.06.11 @ 15:34 Oleg Cherevko wrote:
3) Изучение исходников ng_ipfw выявило, что когда к нему на какой-то hook приходит out-пакет (не из ipfw через "ipfw netgraph", а из недр netgraph'а), он его просто отправляет в ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL). При этом похоже, что ip_output просто тупо маршрутизирует данный пакет (у которого, напомню, dst IP -- это multicast 224.0.0.X), как если бы dst IP был обычным unicast-адресом. А поскольку в kernel forwarding table для сети 224.0.0.0/8 никакого явного маршрута нет, то вот оно и отправляется по default'у во vlan3. Хотя, это только мой wild guess на основании внешних проявлений. До углубленного штудирования исходников ip_output() я еще не добрался.
Насколько я по беглому осмотру исходников могу судить (код мультикастов мне незнаком), wild guess совершенно верный.
В любом случае, поведение неправильное. Что-то где-то надо менять. Интересуют ваши комментарии по этому поводу. Может кто-то где-то уже с подобным сталкивался? Или хорошо разбирается в нюансах внутреннего устройства TCP/IP-стека FreeBSD, и ему очевидно, почему именно оно так себя ведет и как это можно легко и непринужденно исправить?
Ведет оно себя так, потому что в netgraph пакет отправляется без информации о маршруте - она есть только в аргументах вызовов функций, при вызове ip_output() из netinet/ip_mroute.c:send_packet(). Собственно, уже ipfw, а точнее, pfil-хуки, вызывается без этой информации, просто в норме оно обычно возвращается в вызвавшую процедуру. Здесь придется править либо API вызова pfil и netgraph, чтобы туда передавалась информация о маршруте, скажем, через mbuf-теги, причем надо будет следить за локами в коде маршрутизации, а это вообще больная тема (ipfw uid/gid например до сих с проблемами из-за этого). Такое в любом случае потребует согласования с седыми гуру в arch@ - легко и непринужденно, увы, не получится.
В качестве workaround'а, по идее, можно было бы совсем отказаться от ng_ipfw и просто вешать ng_netflow (ради которого вся эта возня и затевалась изначально) прямо на все нужные интерфейсы, но тут засада в том, что на той (боевой) машине, для которой это все предназначено, работет ipfw nat, и хотелось бы, чтобы трафик при выходе в мир попадал в ng_netflow до за'NAT'ивания, а при входе из мира -- после раз'NAT'ивания. Потому, цеплять ng_netflow непосредственно на внешний интерфейс не подходит.
Для данной конкретной задачи есть workaround: отправлять в ng_netflow не сами пакеты, а их копии через ipfw ngtee (он в свежих версиях починен), чтобы не было нужды их возвращать из netgraph.
-- WBR, Vadim Goncharov
