Разбираюсь с шейпером на таком простом примере:
# шейпим исходящий трафик, корневая дисциплина — 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, стоковое.