Назад | Перейти на главную страницу

tc u32 - как сопоставить протоколы L2 в последних ядрах?

У меня есть хороший шейпер с хешированной фильтрацией, построенный на мосту Linux. Коротко, br0 соединяет external и internal физические интерфейсы, пакеты с тегами VLAN передаются "прозрачно" (я имею в виду, что интерфейсов VLAN нет).

Теперь разные ядра делают это по-разному. Я могу ошибаться с указанием точных диапазонов версий ядра, пожалуйста, простите меня. Спасибо.

2.6.26

Итак, в debian 2.6.26 и выше (я считаю, до 2.6.32) --- это работает:

tc filter add dev internal protocol 802.1q parent 1:0 prio 100 \
    u32 ht 1:64 match ip dst 192.168.1.100 flowid 1:200

Здесь «ядро» совпадает с двумя байтами в поле «протокол» с 0x8100, но считает начало пакета ip как «нулевую позицию» (извините за мой английский, если я немного не понимаю).

2.6.32

Опять же, в debian (я не собирал ванильное ядро) 2.6.32-5 --- это работает:

tc filter add dev internal protocol 802.1q parent 1:0 prio 100 \
    u32 ht 1:64 match ip dst 192.168.1.100 at 20 flowid 1:200

Здесь «ядро» соответствует тому же самому протоколу, но считает смещение от начала заголовка этого протокола - мне нужно добавить 4 байта к смещению (20, а не 16 для адреса dst). Это нормально, кажется более логичным, как по мне.

3.2.11, последняя стабильная версия

Это работает --- как будто тега 802.1q нет вообще:

tc filter add dev internal protocol ip parent 1:0 prio 100 \
    u32 ht 1:64 match ip dst 192.168.1.100 flowid 1:200

Проблема в том, что мне пока не удалось найти способ сопоставить тег 802.1q.

Соответствие тега 802.1q в прошлом

Я мог сделать это раньше следующим образом:

tc filter add dev internal protocol 802.1q parent 1:0 prio 100 \
    u32 match u16 0x0ed8 0x0fff at -4 flowid 1:300

Теперь я не могу сопоставить тег 802.1q с at 0, at -2, at -4, at -6 или тому подобное. Основная проблема в том, что у меня ноль хиты считать --- этот фильтр вообще не проверяется, иными словами "неправильный протокол".

Пожалуйста, помогите мне :-)

Спасибо!

Тег VLAN удален из skb в последних ядрах. Попробуйте что-то вроде этого, чтобы провести мета-матч в skb:

tc filter add dev internal protocol all parent 1:0 prio 100 basic match 'meta(vlan mask 0xfff eq 0x0ed8)' flowid 1:300

Я должен был сделать именно это. Я обнаружил, что ответ, предложенный @Thusitha, был правильным способом сделать это для новых ядер.

Протестировано с ядром Debian wheezy 3.2.0-4 и iproute (откуда берется команда tc) версии 20120521-3 + b3

Вот полный сценарий, tc filter строки почти точно соответствуют указанным @Thusitha

function qos() {
    if="$1"
    vlan1="$2"
    vlan2="$3"

    # delete previous
    tc qdisc del dev $if root >/dev/null 2>&1
    tc qdisc del dev $if ingress >/dev/null 2>&1

    # Root HTB for $if
    tc qdisc add dev $if root handle 1: htb r2q 1 default 1

    # Root class to borrow from
    tc class add dev $if parent 1: classid 1:1 htb quantum 1000000 rate 500mbit ceil 500mbit burst 64k prio 2
    tc qdisc add dev $if parent 1:1 handle 101 sfq perturb 10

    # class for vlan1
    tc class add dev $if parent 1:1 classid 1:106 htb quantum 1000000 rate 1.00mbit ceil 1.00mbit burst 6k
    tc qdisc add dev $if parent 1:106 handle 107 sfq perturb 10
    tc filter add dev $if protocol all parent 1: prio 100 basic match "meta(vlan mask 0xfff eq ${vlan1})" flowid 1:106

    # class for vlan2
    tc class add dev $if parent 1:1 classid 1:108 htb quantum 1000000 rate 1.00mbit ceil 10.00mbit burst 6k
    tc qdisc add dev $if parent 1:108 handle 108 sfq perturb 10
    tc filter add dev $if protocol all parent 1: prio 100 basic match "meta(vlan mask 0xfff eq ${vlan2})" flowid 1:108

}

qos eth1 1234 1235
qos eth2 2345 2346

Вы можете отмечать пакеты vlan с помощью ebtables.

# mark packets according to the vlan id
ebtables -i br0 -A PREROUTING -p 802_1Q --vlan-id 1 -j mark --mark-set 1
ebtables -i br0 -A PREROUTING -p 802_1Q --vlan-id 5 -j mark --mark-set 2

Затем нанесите формовку по разметке. ebtables и iptables имеют одинаковую маркировку.

Сам еще не делал этого. Так что это скорее догадка.

Я бы рекомендовал использовать wirehark для захвата того, что происходит через интерфейс, как видимого в пользовательском пространстве, и использовать это для написания фильтра. Мне интересно, возможно, интерфейс по какой-то причине удаляет теги VLAN (несмотря на то, что он настроен для прозрачного моста). Может быть, добавляются дополнительные теги или что-то в этом роде?

Попробуй выключить reorder_hdr опция на интерфейсе vlan. Если включена опция изменения порядка заголовков, то теги из фреймов удаляются. Проверить по команде ip -d link list dev vlan_iface.