LINUX.ORG.RU
решено ФорумAdmin

Не работает BPF-классификатор для tc

 , , , ,


1

2

Разбираюсь с шейпером на таком простом примере:

# шейпим исходящий трафик, корневая дисциплина — HTB
tc qdisc add dev enp3s0 root handle 1: htb default 99 r2q 1000

# корневой класс на ~20-мегабитный линк
tc class add dev enp3s0 parent 1: classid 1:1 htb rate 18000kbit burst 10k

# дочерний класс, допустим, сюда мы хотим засунуть ICMP
tc class add dev enp3s0 parent 1:1 classid 1:11 htb rate 100kbit ceil 18000kbit prio 1 quantum 2000

# дочерний класс по умолчанию для неклассифицированного трафика
tc class add dev enp3s0 parent 1:1 classid 1:99 htb rate 100kbit ceil 18000kbit prio 2 quantum 2000              

# навешиваем fq_codel на дочерние классы
tc qdisc add dev enp3s0 parent 1:11 handle 11: fq_codel
tc qdisc add dev enp3s0 parent 1:99 handle 99: fq_codel

# собственно, фильтр для ICMP
tc filter add dev enp3s0 parent 1: bpf run bytecode "$(tcpdump -ienp3s0 -ddd 'ip proto 1' | tr '\n' ',')" flowid 1:11

Счётчики для 1:11 после такого лежат в нулях, весь трафик валит в 1:99. Если фильтр заменить на обычный u32, то всё ОК:

tc filter add dev enp3s0 parent 1: u32 match ip protocol 1 0xff flowid 1:11

Самое плохое то, что всё это на BPF раньше работало. Не могу понять, что поменялось или сломалось при очередном апгрейде.

Arch, ядро v4.7.6, стоковое.

cast vel, mky.

tcpdump -ienp3s0 -ddd 'ip proto 1'

Ну не знаю.

xt_bpf например хочет фильтр без учета L2, а tcpdump это просто так не позволяет. Я бы проверил это так

ip li set tunl0 up
....
tcpdump -y raw -ddd 'ip proto 1'

vel ★★★★★ ()
Последнее исправление: vel (всего исправлений: 1)
  > zgrep -i bpf /proc/config.gz
  > find /lib/modules/`uname -r` -iname "*bpf*"
  > lsmod | grep -i bpf
?????
!PROFIT!

не уверен, но как-то так ..

Самое плохое то, что всё это на BPF раньше работало. Не могу понять, что поменялось или сломалось при очередном апгрейде.

теги: Arch, Arschloch, внезапно и неожиданно..

или немного о пользе stable release :) может стоит глянуть на

> sudo sysctl -a | grep -i bpf
> find /proc/sys/net/ -iname "*bpf*"

выглядит-то всё довольно мило на первый взгляд стороннего наблюдателя :)

anonymous ()
Ответ на: комментарий от vel

Ну не знаю.

вроде результат норм:

>  sudo tcpdump -i1 -ddd 'ip proto 1' | tr '\n' ',' ; echo
6,40 0 0 12,21 0 3 2048,48 0 0 23,21 0 1 1,6 0 0 262144,6 0 0 0,

> sudo tcpdump -i1 -ddd 'ip proto 1'
6
40 0 0 12
21 0 3 2048
48 0 0 23
21 0 1 1
6 0 0 262144
6 0 0 0
anonymous ()
Ответ на: комментарий от anonymous
# lsmod | grep bpf
cls_bpf                16384  86

# listmod | grep bpf
/usr/lib/modules/4.7.6-1-ARCH/kernel/net/sched/cls_bpf.ko.gz
/usr/lib/modules/4.7.6-1-ARCH/kernel/net/sched/act_bpf.ko.gz
/usr/lib/modules/4.7.6-1-ARCH/kernel/net/netfilter/xt_bpf.ko.gz

# sysctl -a | grep -i bpf
kernel.unprivileged_bpf_disabled = 0
net.core.bpf_jit_enable = 1
net.core.bpf_jit_harden = 0

# find /proc/sys/net/ -iname "*bpf*"
/proc/sys/net/core/bpf_jit_enable
/proc/sys/net/core/bpf_jit_harden

tc ругался бы, если бы ему чего-то не хватало в ядре. Наверное.

post-factum ★★★★★ ()
Ответ на: комментарий от vel

Да вроде ж как работало. Я когда-то настроил и забыл.

Можешь у себя на каком-то ядре проверить?

post-factum ★★★★★ ()
Ответ на: комментарий от post-factum

Это netfilter, он тут ни к чему.

потому и «хохмы ради». то, что u32 работает, - уже намёк на некую специфику для bpf. ошибки в записях не вижу. остаётся

> sudo tc qdisc show dev  ${net_iface}
, удалить всё, кроме дефолта
qdisc pfifo_fast 0: root refcnt 2 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
и попробовать заново..

anonymous ()
Ответ на: комментарий от anonymous

Хохмы ради попробовал, естественно, без толку.

Меня смущает немного вывод strace: http://termbin.com/b4cj

open("/usr/lib/tc//f_bpf.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)

vel, как думаешь, так и надо? Не нашёл в гугле ничего похожего.

post-factum ★★★★★ ()
Ответ на: комментарий от post-factum

на 4.4.23 оно нормально работает

root@gw2:/etc/htb# htb.init start
root@gw2:/etc/htb# tc -s filter show dev eth0
filter parent 1: protocol ip pref 100 bpf 
filter parent 1: protocol ip pref 100 bpf handle 0x1 flowid 1:10 bytecode '6,40 0 0 12,21 0 3 2048,48 0 0 23,21 0 1 1,6 0 0 262144,6 0 0 0'

root@gw2:/etc/htb# ping -q -s 1000 -c 10 10.0.0.251
PING 10.0.0.251 (10.0.0.251) 1000(1028) bytes of data.

--- 10.0.0.251 ping statistics ---
10 packets transmitted, 10 received, 0% packet loss, time 9000ms
rtt min/avg/max/mdev = 0.428/0.474/0.561/0.046 ms
root@gw2:/etc/htb# tc -s class show dev eth0
class htb 1:10 parent 1:2 leaf 10: prio 0 rate 32Kbit ceil 32Kbit burst 15Kb cburst 1640b 
 Sent 10420 bytes 10 pkt (dropped 0, overlimits 0 requeues 0) 
 rate 0bit 0pps backlog 0b 0p requeues 0 
 lended: 10 borrowed: 0 giants: 0
 tokens: 55929687 ctokens: 2335937
root@gw2:/etc/htb# htb.init start
root@gw2:/etc/htb# ping -s 1000 -c 30 -i 0.01 10.0.0.251
PING 10.0.0.251 (10.0.0.251) 1000(1028) bytes of data.
1008 bytes from 10.0.0.251: icmp_seq=1 ttl=64 time=0.497 ms
1008 bytes from 10.0.0.251: icmp_seq=2 ttl=64 time=0.363 ms
1008 bytes from 10.0.0.251: icmp_seq=3 ttl=64 time=91.6 ms
1008 bytes from 10.0.0.251: icmp_seq=4 ttl=64 time=332 ms
1008 bytes from 10.0.0.251: icmp_seq=5 ttl=64 time=572 ms
1008 bytes from 10.0.0.251: icmp_seq=6 ttl=64 time=813 ms
1008 bytes from 10.0.0.251: icmp_seq=7 ttl=64 time=1041 ms
1008 bytes from 10.0.0.251: icmp_seq=8 ttl=64 time=1041 ms
1008 bytes from 10.0.0.251: icmp_seq=9 ttl=64 time=1022 ms
1008 bytes from 10.0.0.251: icmp_seq=10 ttl=64 time=1041 ms
1008 bytes from 10.0.0.251: icmp_seq=11 ttl=64 time=1022 ms
1008 bytes from 10.0.0.251: icmp_seq=12 ttl=64 time=1031 ms
1008 bytes from 10.0.0.251: icmp_seq=13 ttl=64 time=1041 ms
1008 bytes from 10.0.0.251: icmp_seq=14 ttl=64 time=1042 ms
1008 bytes from 10.0.0.251: icmp_seq=15 ttl=64 time=1022 ms
1008 bytes from 10.0.0.251: icmp_seq=16 ttl=64 time=1031 ms
1008 bytes from 10.0.0.251: icmp_seq=17 ttl=64 time=1022 ms
1008 bytes from 10.0.0.251: icmp_seq=18 ttl=64 time=1031 ms
1008 bytes from 10.0.0.251: icmp_seq=19 ttl=64 time=1041 ms
1008 bytes from 10.0.0.251: icmp_seq=20 ttl=64 time=1042 ms
1008 bytes from 10.0.0.251: icmp_seq=21 ttl=64 time=1031 ms
1008 bytes from 10.0.0.251: icmp_seq=22 ttl=64 time=1042 ms
1008 bytes from 10.0.0.251: icmp_seq=23 ttl=64 time=1022 ms
1008 bytes from 10.0.0.251: icmp_seq=24 ttl=64 time=1031 ms
1008 bytes from 10.0.0.251: icmp_seq=25 ttl=64 time=1041 ms
1008 bytes from 10.0.0.251: icmp_seq=26 ttl=64 time=1041 ms
1008 bytes from 10.0.0.251: icmp_seq=27 ttl=64 time=1022 ms
1008 bytes from 10.0.0.251: icmp_seq=28 ttl=64 time=1041 ms
1008 bytes from 10.0.0.251: icmp_seq=29 ttl=64 time=1022 ms
1008 bytes from 10.0.0.251: icmp_seq=30 ttl=64 time=1041 ms

--- 10.0.0.251 ping statistics ---
30 packets transmitted, 30 received, 0% packet loss, time 6103ms
rtt min/avg/max/mdev = 0.363/887.665/1042.202/323.442 ms, pipe 5
root@gw2:/etc/htb# tc -s class show dev eth0
class htb 1:10 parent 1:2 leaf 10: prio 0 rate 32Kbit ceil 32Kbit burst 15Kb cburst 1640b 
 Sent 31260 bytes 30 pkt (dropped 0, overlimits 0 requeues 0) 
 rate 0bit 0pps backlog 0b 0p requeues 0 
 lended: 30 borrowed: 0 giants: 0
 tokens: 49525181 ctokens: -4068569

open(«/usr/lib/tc//f_bpf.so», O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)

IMHO это нормально - там же есть плагины

vel ★★★★★ ()
Ответ на: комментарий от vel

на 4.4.23 оно нормально работает

3.16.7 + iproute2-ss140804 и 3.16.7 + iproute2-ss160518 - норм.

anonymous ()
Ответ на: комментарий от post-factum

Поставил 4.4 LTS — работает. Ну, приехали, б!@#ь, тепер бисектить ядро :(.

будт добр, отпиши по результатам, если нароешь чего путного. может кто-то сваял кривой конфиг ядра?

p.s.: ДрямсЪ! :poz:

anonymous ()
Ответ на: комментарий от vel

Угу, подтверждаю, тоже проверил. Есть идеи? Может, теперь синтаксис какой-то другой?

post-factum ★★★★★ ()
Ответ на: комментарий от post-factum

Короче, в 4.8.0 все работает! Но оочень хитро!

работает для попадания в класс 1:10

tc filter add dev eth0 parent 1:  bpf run bytecode "$(tcpdump -ieth0 -s 65552 -ddd 'icmp' | tr '\n' ',')"

Догадайся почему :)

vel ★★★★★ ()
Последнее исправление: vel (всего исправлений: 1)
Ответ на: комментарий от post-factum

65552 -> 0x10010 это есть класс 1:10 (u16)1 : (u16)0x10

код, который генерит tcpdump, возвращает размер буфера как результат в случае совпадения фильтра, что по «новым» правилам является классом пакета.

Так что можно писать bpf-фильтры которые сразу классифицирую трафик ( но не средствами tcpdump ).

мысль Не работает BPF-классификатор для tc (комментарий) была правильной

vel ★★★★★ ()
Последнее исправление: vel (всего исправлений: 1)
Ответ на: комментарий от vel

Не по тем ли новым правилам для старого поведения нужно возвращать -1?

post-factum ★★★★★ ()
Ответ на: комментарий от vel

Ну и коммиты в ядре, которые поменяли поведение:

  • 045efa82ff563cd4e656ca1c2e354fa5bf6bbda4
  • 3a461da1d03e7a857edfa6a002040d07e118c639
post-factum ★★★★★ ()
Ответ на: комментарий от vel

спасибо за разъяснения. всё как всегда: сидим на LTS/release и ждём вменяемую документацию..

работает для попадания в класс 1:10
65552 -> 0x10010 это есть класс 1:10 (u16)1 : (u16)0x10
Так что можно писать bpf-фильтры которые сразу классифицирую трафик ( но не средствами tcpdump )

туплю с утреца, извините. нужно ли для примера в шапке ТС-а «подбирать» snaplen под classid? -s 65553 (для classid 1:11)?

tc filter add dev eth0 parent 1: bpf run bytecode «$(tcpdump -ieth0 -s 65552 -ddd 'icmp' | tr '\n' ',')»

flowid игнорирется полностью? спасибо.

anonymous ()
Ответ на: комментарий от post-factum

git iproute2, man tc-bpf "(classid|flowid)":

provides the default traffic control class identifier for this eBPF/cBPF classifier. The default  class  identifier  can  also  be overwritten by the return code of the eBPF/cBPF program. A default return code of -1 specifies the here provided default class identifier to be used. A return code of the eBPF/cBPF program of 0 implies that no match took place, and a return code other  than these  two  will  override  the default classid. ...

мдэ..

anonymous ()
Ответ на: комментарий от anonymous

Что характерно, я это видел, но почему-то подумал, что оно относится только к eBPF, потому что cBPF так себя раньше не вёл. Ну и ассемблер нужно было проверить в связи с этим, а не просто на циферки смотреть, да.

post-factum ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.