Производительный роутер на FreeBSD

Осенью 2009 года наша компания запустила новое техническое решение для предоставления доступа в сеть в виде услуги с названием «Прямой интернет». Суть заключается в более эффективной реализации доступа к интернету конечному пользователю.

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

Слабым звеном являются туннелирование и шейпинг большого количества клиентов. Решить проблему туннелирования просто — избавиться от неё. При использовании vpn-аггрегатора есть 2 приемущества: мы указываем куда надо подключаться и как надо подключаться, то есть даём адрес впн-сервера и требуем авторизацию в виде логина и пароля, без которых доступа никто не получит. Без впн-аггрегатора появляется необходимость решить эти 2 задачи. Первая задача решается колдовством на центральном маршрутизаторе сети, вторая — привязкой клиентского оборудования по ip,mac и порту. Вобщем эти 2 задачи здесь не описываются, так как выходят за рамки статьи.

Итак, мы имеет с одного конца канал в Интернет, с другого — абонентская сеть, жаждущая попасть в интернет канал. Между двумя этими сущностями суждено быть 2-ум и более независимым взаимозаменяемым роутерам на FreeBSD, которые будут отфильтровывать невалидный трафик, пропускать валидных клиентов через шейпер, давая им скорость, указанную в тарифе, собирать статистику с ip пакетов, транслировать (если надо)  адреса из внутрисетевых «серых» в «белые», и пускать во внешний мир.

На стадии тестирования, решения этих задач пробовались несколькими способами. Шейпинг с помощью altq, dummynet, ng_car. Натирование — pf nat, ipfw nat. Сбор статистики — ng_netflow. Избыточность роутеров с помощью carp, синхронизация nat-сессий с помощью pfsync. Всё это тестировалось на стабильность и производительность, в сети было найдено много подобных тестов, которые мы пробовали и сравнивали, эксперементировали с настройками сетевой подсистемы FreeBSD, разные версии 7-ой и 8-ой ветки, разные аппаратные конфигурации. К сожалению, результатов всех тестов не осталось, зато есть конечный работоспособный вариант. А подобные тесты и примеры конфигураций можно найти в сети.

По окончанию тестирования стало ясно, что синхронизация nat-сессий — дело неблагодарное, на практике работает плохо. А нужно оно всего-лишь в тех случаях, если один из роутеров падает замертво, а его функции на себя автоматически берёт другой роутер, на котором есть nat-сессии всех пользователей. Таким образом никто бы не заметил падения роутера. Без синхронизации все существующие коннекты оборвутся, то есть надо просто пересоздать их заново (нажать F5 в браузере, подождать пока торрент-клиент переподключится и прочее в этом же духе).

Также мы приручили carp (реализация протокола VRRP от разработчиков OpenBSD). В итоге функции упавшего роутера берёт на себя любой из других работающих роутеров, приоритеты взятия этих функций можно регулировать вручную.

Шейпинг с помощью ng_car сначала обрадовал — он показывал самые интересные результаты, точную скорость и давал возможность управления каналами налету. Но большое количество клиентов порождало для каждого отдельный свой узел в подсистеме netgraph. Она получалась сильно ветвлённая и общая производительность системы резко падала.

Тестировались сетевые карты от Broadcom и Intel. Наилучший результат показали карты на чипах Intel 82576, которые обладают буфером входящих и исходящих пакетов в 4к и работают отложенными прерываниями (аппаратный polling).

В итоге мы остановились на использовании ipfw+dummynet для шейпинга, ng_netflow для сбора статистики, pf nat для трансляции адресов. Роутерами служат сервера Hewlett-Packard на указанных выше сетевых платах Intel. В каждом таком сервере стоит по одному четырёх-ядерному процессору Intel Xeon и 2-4 гб ОЗУ. В качестве операционной системы используется FreeBSD 8.0 Release p2 amd64.

Тестирование конечного варианта проводилось на канале 800мбит/с. Через роутер проходило до 180 тысяч пакетов в секунду. Не наблюдалось ни единого отброшенного пакета или пакета с ошибкой. После чего сервер был поставлен на реальную нагрузку в 300-400 мбит/с входящего и исходящего трафика по отдельности. Проработав стабильно больше недели, нагруженность каждого сервера «на глаз» оценивалась как 40-60%. После количество серверов увеличилось, то есть каждый стал работать в режиме 20-30% своих возможностей. Ниже приведены данные с одного из работающих сейчас роутеров.

# netstat -w1 -h -d
 input        (Total)           output
 packets  errs      bytes    packets  errs      bytes colls drops
 54K     0        33M        53K     0        33M     0     0 
 54K     0        32M        53K     0        32M     0     0 
 54K     0        32M        52K     0        32M     0     0 
 54K     0        33M        53K     0        32M     0     0 
 57K     0        35M        56K     0        35M     0     0 
 54K     0        32M        52K     0        32M     0     0
# top -SPH
last pid: 71507;  load averages:  0.43,  0.31,  0.26      up 41+06:17:06  23:16:07
101 processes: 6 running, 71 sleeping, 24 waiting
CPU 0:  0.0% user,  0.0% nice, 12.8% system,  4.9% interrupt, 82.3% idle
CPU 1:  0.0% user,  0.0% nice,  8.3% system, 27.8% interrupt, 63.9% idle
CPU 2:  0.0% user,  0.0% nice, 13.2% system, 13.2% interrupt, 73.7% idle
CPU 3:  0.0% user,  0.0% nice, 18.8% system,  1.1% interrupt, 80.1% idle
Mem: 12M Active, 160M Inact, 528M Wired, 148K Cache, 418M Buf, 3229M Free
Swap: 8192M Total, 8192M Free

 PID USERNAME PRI NICE   SIZE    RES STATE   C   TIME   WCPU COMMAND
 11 root     171 ki31     0K    64K CPU3    3 914.8H 97.07% {idle: cpu3}
 11 root     171 ki31     0K    64K RUN     0 830.3H 84.38% {idle: cpu0}
 11 root     171 ki31     0K    64K RUN     1 774.6H 78.47% {idle: cpu1}
 11 root     171 ki31     0K    64K RUN     2 827.6H 64.26% {idle: cpu2}
 13 root      50    -     0K    64K sleep   2  63.6H  4.05% {ng_queue2}
 13 root      49    -     0K    64K sleep   2  62.0H  3.66% {ng_queue1}
 13 root      50    -     0K    64K sleep   0  63.7H  2.88% {ng_queue0}
 12 root     -68    -     0K   400K WAIT    0 824:22  1.17% {irq259: igb1}
 0 root     -68    0     0K   144K -       3  17.9H  0.39% {igb0 taskq}
 # netstat -i
Name    Mtu Network       Address              Ipkts Ierrs    Opkts Oerrs  Coll
igb0   1500       d8:d3:85:63:6d:1a 64828120893    15 60565734561     0     0
igb0   1500 172.16.0.0    dir5               3218463     - 914517644     -     -
igb1   1500       d8:d3:85:63:6d:1b 65338495263  607 67475218921   244     0
igb1   1500 77.232.141.0/ dir5               8597342     - 3267277473     -     -
lo0   16384                             8487     0     8487     0     0
lo0   16384 your-net      localhost             8487     -  2132159     -     -
# vmstat -i
interrupt                          total       rate
irq1: atkbd0                           4          0
irq14: ata0                      1562542          0
irq16: uhci0                          22          0
irq18: ehci0 uhci3                     2          0
cpu0: timer                   7076740658       1982
irq256: igb0                 18122121501       5077
irq257: igb0                 24209686691       6783
irq258: igb0                           2          0
irq259: igb1                 21958424484       6152
irq260: igb1                 25173771060       7053
irq261: igb1                         270          0
cpu2: timer                   7076707102       1982
cpu3: timer                   7076707117       1982
cpu1: timer                   7076715498       1982
Total                       117772436953      33000

А теперь посмотрим, что в конфигах.

Собираем своё ядро:

добавляем
options         IPFIREWALL
options         IPFIREWALL_DEFAULT_TO_ACCEPT
options         IPFIREWALL_FORWARD
options         DUMMYNET
options         NETGRAPH
options         NETGRAPH_BPF
options         NETGRAPH_IFACE
options         NETGRAPH_KSOCKET
options         NETGRAPH_IPFW
options         NETGRAPH_SOCKET
options         NETGRAPH_NETFLOW
options         NETGRAPH_ETHER
device          pf
и удаляем драйвера ненужных устройств

Тюнингуем систему:

# cat /boot/loader.conf 
hw.igb.rxd=4096
hw.igb.txd=4096
укажем максимальный размер буфера пакетов
# cat /etc/sysctl.conf 
net.inet.ip.forwarding=1 #включаем форвардинг пакетов
net.inet.ip.fastforwarding=1 #эта опция действительно ускоряет форвардинг
net.inet.tcp.blackhole=2 #ядро убивает tcp пакеты, приходящие в систему на непрослушиваемые порты
net.inet.udp.blackhole=0 #как и выше, только не убивает ибо traceroute пакеты не покажут этот хоп
net.inet.icmp.drop_redirect=1 #не обращаем внимания на icmp redirect
net.inet.icmp.log_redirect=0 #и не логируем их
net.inet.ip.redirect=0 #не реагируем на icmp redirect
net.inet.ip.sourceroute=0 #отключение маршрутизации от источника
net.inet.ip.accept_sourceroute=0 #старый и бесполезный механизм
net.inet.icmp.bmcastecho=0 #защита от SMURF атак
net.inet.icmp.maskrepl=0 #не отдавать по icmp паску своей подсети
net.link.ether.inet.max_age=30 #переспрашиваем каждые 30 секунд mac адреса в своём arp пространстве
net.inet.ip.ttl=226 #почему бы не поставить ttl побольше ;)
net.inet.tcp.drop_synfin=1 #небольшая защита
net.inet.tcp.syncookies=1 #от доса
kern.ipc.somaxconn=32768 #увеличиваем размер очереди для сокетов
kern.maxfiles=204800 #увеличиваем число открытых файловых дескрипторов
kern.maxfilesperproc=200000 #кол-во ф.д. на каждоый процесс
kern.ipc.nmbclusters=524288 #увеличиваем число сетевых буферов
kern.ipc.maxsockbuf=2097152 #
kern.random.sys.harvest.ethernet=0 #не использовать трафик и прерывания
kern.random.sys.harvest.interrupt=0 #как источник энтропии для random'a
net.inet.ip.dummynet.io_fast=1 #заставляет dummynet работать побыстрее
net.inet.ip.dummynet.max_chain_len=2048 #
net.inet.ip.dummynet.hash_size=65535 #
net.inet.ip.dummynet.pipe_slot_limit=2048 #
net.inet.carp.preempt=1 #включаем carp
net.inet.carp.log=2 #пишем логи карпа
kern.ipc.shmmax=67108864 #макс. размер сегмента памяти
net.inet.ip.intr_queue_maxlen=8192 #размер очереди ip-пакетов
net.inet.ip.fw.one_pass=0 #пакеты, прошедшие пайпы не вылетают из фаервола, а дальше идут по нему
dev.igb.0.enable_lro=0 #отключение large receive offloading 
dev.igb.1.enable_lro=0
dev.igb.0.enable_aim=0 #так нет аномалий с работой сетевушек
dev.igb.1.enable_aim=0
dev.igb.0.rx_processing_limit=2048 #адаптивный polling, разрешаем прерывания с сетевухи при достижении значения
dev.igb.0.flow_control=0 #отключение контроля потока
dev.igb.1.rx_processing_limit=2048
dev.igb.1.flow_control=0

Далее идёт скрипт создания графа в netgraph для сбора netflow статистики.

# cat /etc/rc.d/ngnetflow 
#!/bin/sh
. /etc/rc.subr
 name="ngnetflow"
rcvar=`set_rcvar`
load_rc_config $name
: ${ngnetflow_enable="NO"}
: ${ngnetflow_src="0.0.0.0:5525"}
: ${ngnetflow_dst="x.x.x.x:5525"}
start_cmd="ngnetflow_start"
stop_cmd="ngnetflow_stop"
ngnetflow_start() {
/usr/sbin/ngctl -f- <<-SEQ
mkpeer ipfw: netflow 65534 iface0
name ipfw:65534 netflow
connect ipfw: netflow: 65533 out0
msg netflow: setdlt { iface=0 dlt=12 }
msg netflow: settimeouts { inactive=30 active=600 }
mkpeer netflow: ksocket export inet/dgram/udp
name netflow:export flow-sensor
msg flow-sensor: bind inet/${ngnetflow_src}
msg flow-sensor: connect inet/${ngnetflow_dst}
SEQ
}
ngnetflow_stop() {
/usr/sbin/ngctl -f- <<-SEQ
shutdown netflow:
SEQ
}
run_rc_command "$1"

Для автозапуска этого скрипта помещаем в /etc/rc.conf строку  ngnetflow_enable="YES"

Наш граф выглядет вот так:

ng_netflow

Если сделать ipfw add netgraph 65534 ip from any to me, то трафик, попадающий под это правило будет заворачиваться в netgraph на хук 65534, попадает в ноду netflow, где происходит сбор статистики с заголовков ip-пакетов, далее трафик возвращается по хуку 65533 обратно в фаервол. К ноде netflow подключен экспорт netflow-статистике ввиде udp дейтаграмм.

Если вместо ipfw add netgraph использовать ipfw add ngtee, то трафик, проходящий это правило, будет дублироваться(!), копия которого направляться на ng_netflow.

Теперь настроим NAT.

# cat /etc/pf.conf 
set limit states 16000000
set optimization aggressive
set limit src-nodes 160000
set limit table-entries 160000
nat-anchor "ftp-proxy/*"
nat on igb1 from 10.0.0.0/8 to any -> 77.232.142.0/24 source-hash #натирование пулом адресов

Конфиг фаервола, сделанный с любовью и без лишних замарочек

# cat /etc/ipfw.conf 
ipfw='/sbin/ipfw -q'
if_in='igb0'
if_out='igb1'

#--- reseting ---
${ipfw} flush
${ipfw} pipe flush
${ipfw} table all flush
#----------------

#--- red light---
${ipfw} add deny ip from any to any 135,137,138,139,445 #fucking ports
#-----------------

#--- green light ---
${ipfw} add allow ip from any to me #me
${ipfw} add allow ip from me to any #me

${ipfw} add allow ip from 77.232.142.0/24,77.232.143.0/24 to any #адресное пространство натирующих подсетей
${ipfw} add allow ip from any to 77.232.142.0/24,77.232.143.0/24 #в них превращаются уже отфильтрованные пакеты

${ipfw} add allow ip from 77.232.128.0/20 to 10.0.0.0/8,172.25.0.0/16,77.232.128.0/20 #это на не надо, но сделано на всякий случай
${ipfw} add allow ip from 10.0.0.0/8,172.25.0.0/16,77.232.128.0/20 to 77.232.128.0/20 #чтобы вдруг не обсчитать заблудший не туда лок. трафик

${ipfw} add allow ip from any to table\(1\) #таблица 1 содержит адреса и подсети
${ipfw} add allow ip from table\(1\) to any #которые пускаем в инет в обход учёта в биллинге

#---- TABLES -----
${ipfw} table 1 add 77.232.128.0/28 #servers network
${ipfw} table 1 add 77.232.135.0/29 #servers network
${ipfw} table 1 add 77.232.128.64/27 #billing network
${ipfw} table 1 add 77.232.128.192/28 #admins network
${ipfw} table 1 add 62.231.13.168 #cyberplat
#--------------------------

#--- valid abons ---
${ipfw} add pipe tablearg ip from any to table\(126\) out xmit ${if_in} #abons shape downstream
${ipfw} add netgraph 65534 ip from any to table\(126\) out xmit ${if_in} #abons netflow downstream
${ipfw} add allow ip from any to table\(126\) #out xmit ${if_in} #allow abons downstream

${ipfw} add pipe tablearg ip from table\(127\) to any in recv ${if_in} #abons shape upstream
${ipfw} add netgraph 65534 ip from table\(127\) to any in recv ${if_in} #abons netflow upstream
${ipfw} add allow ip from table\(127\) to any #in recv ${if_in} #allow abons upstream
#-------------------

#--- DENY ALL and ip.fw.one_pass=0 ---
${ipfw} add 65534 deny ip from any to any #по умолчанию фаерволл открытый
делаем его закрытым, то есть всё что не описано в правилах выше - не пускаем
#-------------------------------------

Эффективность работы dummynet достигается такой конструкцией:

${ipfw} add pipe tablearg

Это позволяет не плодить правила в фаерволе, из-за увеличения количества которых резко падает производительность шейпера.

Далее по крону отрабатывает скрипт, который формирует динамические пайпы с указанной пропускной способностью:

ipfw pipe $номер_пайпы config mask dst-ip 0xffffffff bw $скоростьkbits

Добавляет в таблицы №126 и 127 пары (ip-адрес клиента, номер пайпы):

ipfw table 126 add $ip $номер

Этот скрипт писал мой коллега на perl'e. Скрипт обеспечивает добавление новых и удаление старых пайп для тарифных планов. Добавление и удаление текущих клиентов из таблиц 126, 127 с изменением у клиента $номер в случае смены тарифа. IP-адреса и скорости клиентов выгружаются с биллинга и обрабатываются каждые 5-10 минут.

Теперь мы имеет оттюнингованную для роутинга систему, которая способна не просто прокачать через себя около гигабита в секунду, но и успев зашейпить каждого клиента, собрать с него netflow и занатировать. Один такой аггрегат способен успешно работать с 3000-4000 клиентами одновременно, 800/800 мбит/с трафика и пропускать через себя 180 килопакетов в секунду на каждом интерфейса. На впн-сервере (pptp под linux'ом) у нас бывает по 400-600 пользователей, сервер такой же аппаратной конфигурации более 100мбит/с выдаёт с трудом.

Comments

  • avatar

    J.Bond

    Posted 3 years ago.

    Спасибо за статью - оч позновательно и полезно. Как раз на подобную задачу "наступил", платформы и задачи сопастовимы, а вот с платами пришлось пока остаться на bge 🙁
    Правда при реализации под 8.1. всплыли некоторые моменты... Ну то, что у bge ключи другие и параметры другие - это понятно, а вот то, что в ipfw3 под 8.1 в соответствующей ветке отсутствует net.inet.ip.dummynet.max_chain_len это было сюрпризом.
    И еще подскажите в вашей террминалогии if_in, if_out как соотносятся с более принятыми ext_if, int_if, т.е. кто из них смотрит в инет, а кто в сторону клиентов.

  • avatar

    bonzo

    Posted 3 years ago.

    если требуется пропускать через роутер более, чем 150-200мегабит/с в каждом направлении (более 40kpps через каждую плату), лучше прикупить em'ки или igb'шки

    тут if_in = int_if; if_out = ext_if

    кстати, недавно приходилось чуть поднагрузить один такой сервер. Результат 860мбит/с входящая и 670мбит/с исходящая. На реальном абонентском трафике. Ошибок, дропов и коллизий на интерфейсах не было. Пинг до сервера вырос с 0.1мс до 1.5мс

  • avatar

    drmin

    Posted 2 years, 10 months ago.

    Спасибо. Отличная статья.
    Но у меня не получилось поднять бордер-роутер на FreeBSD 8.1 Release#7 и четырех портовой сетевой картой с чипом 82576 (igb).
    Скопированы конфиги с рабочего бордера на 7.2 и с сетевыми em (двухпортовые 82571). Нат на ipfw , bgp, сетевые попарно в lagg, трафика проходит около 1.2 Гбпс.
    Когда переключаюсь на 8.1 с igb сервер падает в "корку".
    Вы не пробовали обновляться на 8.1? У вас не было подобных проблем на 8.0 с сетевыми igb?

  • avatar

    J.Bond

    Posted 2 years, 10 months ago.

    На подходе новый сервер с igb и как раз будем ставить 8.1посмотрю.

    Сейчас работает как раз с em - проблем нет, до этого стояло на bge.

  • avatar

    connect

    Posted 2 years, 10 months ago.

    Добрый день bonzo! А биллинг каким образом выгружает даанные для скрипта на perl'e? Сам скрипт можно увидеть?

  • avatar

    bonzo

    Posted 2 years, 10 months ago.

    drmin, всё работает на 8.0-p2 и igb без сбоев и ребутов уже полгода. Где-то через месяц будем добавлять еще несколько таких роутеров, тогда попробую 8.1
    с транками на freebsd с продакшне у нас ничего нет, может быть вместо lagg попробовать netgraph (ng_one2many, ng_fec)?

    J.Bond, какие задачи Ваш аггрегат выполняет? и как с показателями (pps, interrupts)

    connect, По крону раз в 5 минут sql запросом получаем ip-адрес и скорости абонентов. Это записывается plain-text'ом в файл, который потом каждый из роутеров тоже по крону с помощью scp получает себе. Скрипт будет чуть попозже, всё таки небольшое описание для него требуется.

  • avatar

    Igorlp

    Posted 2 years, 7 months ago.

    А почуму камни Intel Xeon, а операционка FreeBSD 8.0 Release p2 amd64?

  • avatar

    napTu

    Posted 2 years, 6 months ago.

    Спасибо, поставил у себя пару костылей из статьи, оптимизировал фаервол и как то неожиданно нагрузка уменьшилась в два раза, а ППС увеличился в полтора раза. Теперь в чнн загрузка не более 50%, а трафик 70тыс ппс. Раньше на 40-50тыс страшно было смотреть.
    Для оптимизации использовал утилитку pmcstat, из которой и выяснил что основную нагрузку несет ipfw

  • avatar

    mlevel

    Posted 2 years, 4 months ago.

    А можно детальнее про CARP? Очень хочется увидеть пример...

  • avatar

    bonzo

    Posted 2 years, 3 months ago.

    схему избыточности carp можно по разному сделать. Например:
    1. при падении сервера, его задачу берёт на себя следущий по цепочке.
    минусы: если нагрузка на каждый роутер более 50%, то взявший на себя нагрузку упавшего станет перегруженным
    2. на несколько работающих роутеров ставить один ожидащий. Он возьмёт на себя работу любого упавшего роутера.
    минусы: если упало более одного роутера с нагрузкой >50%, бекапный роутер будет в перегрузе. Но вероятность такого случая мала.

    На примере 4-ёх роутеров (только для нижних интерфейсов) конфиг для 1-ого примера:
    cloned_interfaces="carp0 carp1 carp2 carp3"
    ifconfig_carp0="vhid 1 pass xxx1 advskew 0 172.16.255.1 netmask 255.255.0.0"
    ifconfig_carp1="vhid 2 pass xxx2 advskew 60 172.16.255.2 netmask 255.255.0.0"
    ifconfig_carp2="vhid 3 pass xxx3 advskew 40 172.16.255.3 netmask 255.255.0.0"
    ifconfig_carp3="vhid 4 pass xxx4 advskew 20 172.16.255.4 netmask 255.255.0.0"

    и так на каждом из 4-ёх только меняем значение advskew, это весы. У кого меньше, тот возмёт на себя работу в случае падения.
    роутер1 (0-60-40-20) (мастер 172.16.255.1)
    роутер2 (20-0-60-40) (мастер 172.16.255.2)
    роутер3 (40-20-0-60) (мастер 172.16.255.3)
    роутер4 (60-40-20-0) (мастер 172.16.255.4)
    т.е., если упал роутер1, мастером 172.16.255.1 станет роутер 2. И так далее. Если упалт роутер4, его функции берёт роутер1.

    Пример 2:
    роутер1:
    cloned_interfaces="carp0"
    ifconfig_carp0="vhid 1 pass xxx1 advskew 0 172.16.255.1 netmask 255.255.0.0"
    роутер2:
    cloned_interfaces="carp0"
    ifconfig_carp0="vhid 2 pass xxx2 advskew 0 172.16.255.2 netmask 255.255.0.0"
    роутер3:
    cloned_interfaces="carp0"
    ifconfig_carp0="vhid 3 pass xxx3 advskew 0 172.16.255.3 netmask 255.255.0.0"

    роутер4-бекапный:
    cloned_interfaces="carp0 carp1 carp2"
    ifconfig_carp0="vhid 1 pass xxx1 advskew 20 172.16.255.1 netmask 255.255.0.0"
    ifconfig_carp1="vhid 2 pass xxx2 advskew 20 172.16.255.2 netmask 255.255.0.0"
    ifconfig_carp2="vhid 3 pass xxx3 advskew 20 172.16.255.3 netmask 255.255.0.0"

  • avatar

    bonzo

    Posted 2 years, 3 months ago.

    Igorlp
    >>А почуму камни Intel Xeon, а операционка FreeBSD 8.0 Release p2 amd64?
    http://ru.wikipedia.org/wiki/X86-64

    napTu,
    насчёт костылей: конструкцию ipfw add netgraph я заменил на ipfw add ngtee. netgraph - фаерволл перенаправляет трафик в нетграф на обсчёт, потом его снова получает. ngtee - фаерволл делает копию пакетов и шлёт в нетграф. Теоретически это более ресурсоёмки. На практике под 8.0-release эффект +2kpps на 70-80kpps. Возможно, что на таких нагрузках роутеру легче продублировать, чем успеть сделать обсчёт трафика.

    Пробовал 8.1-release, потом 8.1-stable, 8.2-release. Netgraph ведёт себя странно.
    И общая проблема, которая мещает сделать транк на 2 и более гигабита - однопоточная работа подсистемы dummynet. То есть, при нагрузке 92-94kpps в одну сторону, dummynet использует 100% одного ядра цп.

  • avatar

    napTu

    Posted 2 years, 2 months ago.

    bonzo,
    у меня фаервол вообще не занимается заворотом трафика в netflow, netflow скрипт просто включен на интерфесе и собирает весь трафик

    mkpeer em0: tee lower left
    connect em0: em0:lower upper right
    mkpeer em0:lower netflow left2right iface0
    name em0:lower.left2right netflow
    connect em0:lower netflow: right2left iface1
    mkpeer netflow: ksocket export inet/dgram/udp
    msg netflow:export connect inet/127.0.0.1:4440
    msg netflow: settimeouts { inactive=30 active=60 }

    FreeBSD 8.1-RELEASE-p2

    По dummynet сильно помогла просто оптимизация фаервола, до двух гигабит пока далековато, так что не скажу точно.
    Сейчас dummynet не показывает нагрузку, хоть и набирает время использования cpu 132.9H.
    Для сравнения, каждый из трех тредов em0_rx0 накопил 63.8H использования.
    Есть опыт что при каком то пороговом значении ппс нагрузка dummynet сильно подскакивает и вот именно на этом моменте мне сильно помогла оптимизация фаервола..
    что странно, сейчас net.inet.ip.dummynet.io_fast=0
    Но это не дает пропуск пакетов для шейперов более 12/24 и т.д мегабит (каждые 12мегабит это каждая 1000 параметра ядра kern.hz )

  • avatar

    2ihi

    Posted 2 years, 2 months ago.

    автору статьи спасибо, но хотелось бы посмотреть на полный вывод top -SCH в часы пиковых нагрузок, имею мнение что тормоза (или вернее затык на ~800мбс) вызваны процессом swi1:net, что собственно начинает расти из
    ${ipfw} add netgraph 65534 ip from any to table\(126\) out xmit ${if_in} #abons netflow downstream

    так же при использовании add netgraph необходим ключик one_pass=1 что при добавлении и удалении шейпирующих правил в фаервол (без таблиц) вызывает панику ядра, да и пакетики начинают по фаерволу искать жестко deny или allow что соответственно так же вызывает увеличение нагрузки как минимум на 30% на пустом месте.

    лично для себя, имея ввиду вышеописанное вижу уход от связки нетграфа с фаерволом, а именно снятие статы непосредственно с интерфейсов с применением минимума нод, натить на внешних ифейсах, а стату брать с внутреннего, вот правда проблема если маршрутизатор используется не только в качестве шлюза в инет, но и в различные пиринги - куда траф считать то и не нужно, и каналы там 10G, тогда можно ковырять схему снятия статы с целевого ифейса, где присутствует PF NAT, чем собственно и занимаюсь, проблема заставила меня загуглить и выйти к вам 🙂

    вобщем если интересно будет чего получилось у меня, по окончании настройки и тестов поделюсь.

  • avatar

    2ihi

    Posted 2 years, 2 months ago.

    Да, про тормоза dummynet - не поленитесь сделать:

    #procstat -at | grep dummynet
    0 100083 kernel dummynet 0 16 sleep -.
    #cpuset -l 0 -t 100083

    решает проблемы 100% cpu use на интелах. После ввода в строй сервер на ксеонах узнал что думми может жрать больше 15% одну корку, до этого сервер был на оптеронах.

  • avatar

    2ihi

    Posted 2 years, 2 months ago.

    И так, друзья, решил я слушать все на локальном ифейсе без лишних заморочек стату брать с ng_iface (что бесспорно будет быстрее чем любые другие способы сбора), по внешним интерфейсам трафик будет софтверно разделяться на основе таблиц маршрутизации (у меня они оч длинные, порядка нескольких тыщ записей на каждом аплинке), если интересно - результат работы вышлю мылом, ну а всем на поругание придумал механизм анализа включения конкретного ИП адреса в сеть принятую с внешнего ифейса:

    1. ИП из лога складываем по xor с ИП сети
    2.результат по & множим с маской
    если результат =0 то ИП принадлежит сетке, если не 0, то ип не из сетки..

    кто что скажет, может оптимальней предложит и тд..

    кусок на сях, писал прям тут, за работоспособность не отвечаю, но вроде должно работать:

    main ()
    {
    int a=192,b=168,c=17,d=0;
    int a1=192,b1=168,c1=17,d1=215;
    int m1=255,m2=255,m3=255,m4=0;

    a=((a ^ a1) & m1);
    b=((b ^ b1) & m2);
    c=((c ^ c1) & m3);
    d=((d ^ d1) & m4);
    int res=((a | b) | (c | d));

    printf ("блаблабла если 0 то ип из сетки, если нет то ип НЕ из сети=%d",res);

    }

  • avatar

    stechkh

    Posted 1 year, 6 months ago.

    Полагаю 1Gbit/s для igb и 4 intel core @3GHz не предел, даже с маскарадингом.
    (http://myfreebsd.ru/freebsd_as_server/uchet-kolichestva-sessij-translyacii-ip-adresov-sessii-nat)
    А реально ли получить 10 Gbit/s чистой маршрутизации?

  • avatar

    ~NiX~

    Posted 1 year, 5 months ago.

    Да реально и это тоже далеко не предел ...
    и не только чистой маршрутизацией у меня
    шейпинг + роутинг это до 7 гигабит выше просто не хватает ресурсов роутера... а если брать 10Гигабит чистой маршрутизации то точно так же все будет работать если нормально система заточена ....

  • avatar

    adsh

    Posted 5 months, 21 days ago.

    add deny ip from any to any 135,137,138,139,445

    Номера портов могут быть только у UDP/TCP.

  • avatar

    ivasian

    Posted 5 months, 15 days ago.

    А как можно протестировать шейпинг? Для этого требуется имитировать поток данных с разными ip source, чтобы создавалось требуемое количество очередей. Чем это можно сделать?

    Источник : bonzo.me/freebsd-router

Запись опубликована в рубрике *Lan&Wan, *Unix,*Linux. Добавьте в закладки постоянную ссылку.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Я не спамер This plugin created by Alexei91