Я не знаю, как Linux обрабатывает правила Netfilter на уровне кода операции. Но многопортовый подход может выполнять несколько проверок за одну операцию.
Так как 1 Гбит/с не так много для процессора (даже медленного ), неудивительно, что вам нужны крайние случаи. Но оба подхода даже при одинаковой пропускной способности могут генерировать совершенно разные нагрузки. Поскольку это материал ядра, он, вероятно, даже не показан в /proc/loadavg
. Таким образом, вам придется запустить приложение с интенсивным использованием ЦП -в той же системе и измерить его производительность, чтобы увидеть реальную разницу.
Но я думаю, что ваше сравнение несколько несправедливо, потому что мультипорт проверяет один раз для -p tcp
, тогда как мультируль делает ту же самую проверку 65536 раз. Таким образом, вы бы сделали что-то вроде этого:
iptables -N tcp_ports
iptables -A INPUT -p tcp -j tcp_ports
for ((i=1;i<65536;i++)); do iptables -A tcp_ports --sport $i...
Я просто понимаю, что вы не можете пропустить проверку TCP, потому что это требование для --dport
. Но это одна из причин, почему подход с несколькими правилами работает медленнее.
Я не уверен, что мультипорт предназначен для таких случаев, как ваш. Для сравнения были созданы огромные списки ipset
. Так что это может быть то, что вы на самом деле ищете.
ipset create foo bitmap:port range tcp:10000-19999
ipset add foo tcp:10000-19999
iptables -A INPUT -p tcp -m set --match-set foo dst
Поместите это в файл с именемmy_map_command
:
#!/usr/bin/awk -f
FNR==NR{map[$1]=$2}
FNR!=NR{
printf "%s%s",map[$1],OFS
for (i=2; i<=NF; i++) printf "%s%s",$i,OFS
printf "\n"
}
Затем запустите:
chmod u+x my_map_command
Вызовите свой скрипт как:
./my_map_command map.tsv data.tsv
Несколько файлов карты:
./my_map_command <(cat map1.tsv map2.tsv) data.tsv
Назначить переменную между аргументами файла:
awk '!data{map[$1]=$2; next} $1 in map{$1=map[$1]} 1' map1 map2... data=1 data
map
до тех пор, пока не будет задан флаг data=1
аргумент ), поменять поле в данных на сопоставленное значение awk '
!data {
map[field,$1]=$2
maps[field]
next
}
{
for (i in maps)
if ((i,$i) in map)
$i=map[i,$i]
}
1' field=1 map1 field=2 map2 data=1 data
data
сопоставляется со значением изmap1
data
сопоставляется со значением изmap2
Команда csvjoin
из пакета csvkit может использоваться для достижения аналогичного поведения:
$ csvjoin -tH -c 1,1 data.tsv map.tsv 2> /dev/null
a,b,c,b2
1,a,3,foo
2,b,2,bar
3,a,10,baz
2,c,2,bar
2,a,8,bar
Переупорядочить/удалить столбцы очень просто, и это можно сделать с помощью csvcut
из того же пакета.
Стандарт join(1)
тоже можно использовать, но он требует сортировки данных (и карты, если она не отсортирована):
$ join -j1 -t ' ' <(sort -k1 data.tsv) map.tsv
1 a 3 foo
2 a 8 bar
2 b 2 bar
2 c 2 bar
3 a 10 baz
В обоих случаях одновременно может выполняться только одно сопоставление, поэтому для множественных отображений требуется передача по конвейеру в следующий вызов.
Или просто используйте уже знакомый вам язык для опроса табличных данных:sql ;
Синтаксис прост:q "<SQL Query>"
или q -t "…"
, если ваши файлы имеют формат tsv, или -d …
для других разделителей. Ваш запрос будет:
SELECT m.c2, d.c2, d.c3
FROM data.tsv AS d INNER JOIN map.tsv AS m
ON d.c1==m.c1
q - text as data
(упаковановезде)представляет собой удобный инструмент для применения возможностей SQL к любым табличным данным с разделителями. Даже STDIN работает, просто укажите « -» вместо имени файла, подумайте JOIN - as m
, чтобы заменить map.tsv чем-то, что вы передаете.
Приятный "бонус"q
:Вы можете использовать SQL ORDER
, GROUP
, а также производить вычисления! Показывая все это:
q 'SELECT m.c2 AS I, d.c2, d.c3, ROUND(d.c3*0.4, 2) as b
FROM data.tsv AS d INNER JOIN - AS m
ON d.c1==m.c1
ORDER BY I' < map.tsv
bar b 2 0.8
bar c 2 0.8
⋮
Примечание :Имя "q" полностью не гуглится, поэтому при поиске добавляйте "текст -как -данные" или "harelba" (автора ).