QoS в Linux: 802.1p, net_prio cgroups

В реальной сети трафик окрашивается тремя способами – IPv4/IPv6 TOS(DSCP), MPLS TC Field (старое название MPLS EXP bits) и 802.1p. Поскольку mpls на текущий момент отсутствует в ванильном ядре, вопрос об окраске mpls-трафика на Linux пока нет смысла рассматривать.

В прошлой заметке было рассказано о том, как linux priority(он же internal priority или skb->priority) может быть использован для приоритезации трафика((!) а не раскраски его). В этой заметке будет рассмотрен вопрос о том, каким образом можно использовать linux priority(далее LP) для установки 802.1p(окраска трафика на втором(ethernet) уровне), а также будет показано как можно установить LP для конкретного локального процесса средством net_prio cgroup(а не с помощью классификации по типу трафика).

Использование 802.1p актуально, как минимум, в двух случаях:
– коммутатор, к которому подключен сервер(или где-то дальше) не умеет учитывать TOS/DSCP
– для раскраски non-IP трафика (например pppoe, arp)

Для написания статьи использовался дистрибутив Linux Ubuntu 14.04 (ядро 3.13.0-24.46)

802.1p: egress-qos-map, ingress-qos-map

802.1p scheme
К счастью, в тот раз не потребуется иметь дело с реальным оборудованием и патчкордами. Весь стенд состоит из linux машины с одним дополнительным netns. Базовые настройки:

# ip link add veth type veth peer name vethC //создание пары veth-интерфейсов и линка между ними
# ip link add link veth name veth.100 type vlan id 100 //создание dot1Q-сабынтерфейса
# ip link set veth up //поднятие veth-интерфейса
# ifconfig veth.100 192.0.2.1/30 up //задание IP и поднятие сабынтерфейса
# ip netns add C //создание дополнительного netns
# ip link set vethC netns C //ассоциация интерфейса vethC с netns C
# hostname C ; ip netns exec C bash //переход в netns C (выполнять в новом терминале, №2)

C:~# ip link set vethC up
C:~# ip link add link vethC name vethC.100 type vlan id 100
C:~# ifconfig vethC.100 192.0.2.2/30 up

Для задания маппинга между LP и 802.1p используется egress-qos-map. Например мы хотим сделать маппинг LP=6 в 802.1p=5 и посмотреть весь mapping:

# ip link set dev veth.100 type vlan egress-qos-map 6:5
# cat /proc/net/vlan/veth.100 
veth.100  VID: 100       REORDER_HDR: 1  dev->priv_flags: 1
         total frames received          428
          total bytes received        16768
      Broadcast/Multicast Rcvd            8

      total frames transmitted          431
       total bytes transmitted        23265
Device: veth
INGRESS priority mappings: 0:0  1:0  2:0  3:0  4:0  5:0  6:0 7:0
 EGRESS priority mappings: 6:5 

(для всех остальные значения LP(кроме 6), значение 802.1p будет равно 0)

Теперь нужно сгенерировать трафик для которого LP равен 6 и, например, 2(для сравнения), сделаем это с помощью установки поля TOS. В соответствии с таблицей TOS->LP возьмём TOS=0x14(LP=6) и 0x08(LP=2)

# ping -Q 0x14 192.0.2.2 -c 1
# ping -Q 0x08 192.0.2.2 -c 1

C:~# tcpdump -i vethC -n -nn -v -s 0 -e
00:05:05.722468 62:08:9a:f6:d6:1a > da:a8:55:50:88:e7, ethertype 802.1Q (0x8100), length 102: 
vlan 100, p 5, ethertype IPv4, (tos 0x14, ttl 64, id 17390, offset 0, flags [DF], proto ICMP (1), length 84)
    192.0.2.1 > 192.0.2.2: ICMP echo request, id 3446, seq 1, length 64
00:05:05.722489 da:a8:55:50:88:e7 > 62:08:9a:f6:d6:1a, ethertype 802.1Q (0x8100), length 102: 
vlan 100, p 0, ethertype IPv4, (tos 0x14, ttl 64, id 43594, offset 0, flags [none], proto ICMP (1), length 84)
    192.0.2.2 > 192.0.2.1: ICMP echo reply, id 3446, seq 1, length 64
00:05:25.403153 62:08:9a:f6:d6:1a > da:a8:55:50:88:e7, ethertype 802.1Q (0x8100), length 102: 
vlan 100, p 0, ethertype IPv4, (tos 0x8, ttl 64, id 17391, offset 0, flags [DF], proto ICMP (1), length 84)
    192.0.2.1 > 192.0.2.2: ICMP echo request, id 3447, seq 1, length 64
00:05:25.403181 da:a8:55:50:88:e7 > 62:08:9a:f6:d6:1a, ethertype 802.1Q (0x8100), length 102: 
vlan 100, p 0, ethertype IPv4, (tos 0x8, ttl 64, id 43595, offset 0, flags [none], proto ICMP (1), length 84)
    192.0.2.2 > 192.0.2.1: ICMP echo reply, id 3447, seq 1, length 64

Как видно из подсвеченных строчек, 802.1p маркировка установлена для TOS=0x14 и не установлена(равна 0) для TOS=0x08. icmp-reply для TOS=0x14 идёт без 802.1p маркировки потому что для интерфейса vethC.100(с которого уходит ответ) не задан egress-qos-map.

Теперь используем ingress-qos-map для задания LP тому или иному значению 802.1p, который потом можно учитывать. Воспользуемся ранее заданным egress-qos-map для интерфейса veth.100 (6:5), а на ответном интерфейсе(vethC.100) установим ingress-qos-map 5:4 (т.е. для трафика, приходящего с 802.1p=5 LP будет равен 4) и посчитаем трафик с LP=4 с помощью nftables(не смотря на то, что nftables присутствует в ядре 3.13, user space утилита для его конфигурирования отсутсвует в ubuntu 14.04, её можно собрать или взять из user-ppa).

C:~# ip link set dev vethC.100 type vlan ingress-qos-map 5:4
C:~# /etc/nftables/ipv4-filter //инициализация nftables filter
C:~# nft add rule ip filter input meta priority 5 iifname vethC.100 counter
C:~# nft add rule ip filter input meta priority 4 iifname vethC.100 counter
C:~# nft add rule ip filter input meta priority 0 iifname vethC.100 counter

# ping -Q 0x14 192.0.2.2 -c 2 //трафик уходит с veth.100 в строну vethC.100 с 802.1p=5
# ping -Q 0 192.0.2.2 -c 1

C:~# nft list table filter
table ip filter {
  chain input {
    type filter hook input priority 0;
    meta priority :0005 iifname "vethC.100" counter packets 0 bytes 0
    meta priority :0004 iifname "vethC.100" counter packets 2 bytes 168
    meta priority none :0000 iifname "vethC.100" counter packets 1 bytes 84
  }
  ...
}

net_prio cgroup

Cgroups в Linux это механизм применения какого-либо ограничения или действия к группе процессов(ограничивать по памяти/cpu, изолировать друг от друга, осуществлять приоритезацию/классификацию трафика). По отношению к трафику есть 2 cgroup – net_cls и net_prio. Как видно из заголовка, речь пойдёт о net_prio.

# modprobe netprio_cgroup //загрузка модуля ядра
# mkdir /sys/fs/cgroup/net_prio //точка монтирования cgroup
# mount -t cgroup -o net_prio none /sys/fs/cgroup/net_prio //монтирование net_prio cgroup
# cd /sys/fs/cgroup/net_prio ; mkdir LP6 ; cd LP6 //создание группы процессов с названием LP6
# echo "veth.100 6" > net_prio.ifpriomap //Для всего трафика, уходящего в интерфейс veth.100 от процессов этой группы устанавливать LP=6
# cat net_prio.ifpriomap //просмотр карты приоритетов
lo 0
eth0 0
veth 0
veth.100 6

Для того, чтобы ассоциировать процесс с cgroup можно его запускать с помощью cgexec:

# cgexec -g net_prio:LP6 ping 192.0.2.2 -c 1
PING 192.0.2.2 (192.0.2.2) 56(84) bytes of data.
64 bytes from 192.0.2.2: icmp_seq=1 ttl=64 time=0.044 ms

C:~# tcpdump -i vethC -e -v -n -s 0
14:56:20.767687 62:08:9a:f6:d6:1a > da:a8:55:50:88:e7, ethertype 802.1Q (0x8100), length 102: 
vlan 100, p 5, ethertype IPv4, (tos 0x0, ttl 64, id 17410, offset 0, flags [DF], proto ICMP (1), length 84)
    192.0.2.1 > 192.0.2.2: ICMP echo request, id 32311, seq 1, length 64
14:56:20.767714 da:a8:55:50:88:e7 > 62:08:9a:f6:d6:1a, ethertype 802.1Q (0x8100), length 102: 
vlan 100, p 0, ethertype IPv4, (tos 0x0, ttl 64, id 43614, offset 0, flags [none], proto ICMP (1), length 84)
    192.0.2.2 > 192.0.2.1: ICMP echo reply, id 32311, seq 1, length 64

Второй способ – ассоциация запущенного процесса с net_prio cgroup:

# echo TASK_PID > /sys/fs/cgroup/net_prio/LP6/tasks

Чтобы посмотреть к каким cgroup принадлежит тот или иной процесс есть псевдофайл cgroup:

# cat /proc/32313/cgroup 
12:hugetlb:/
11:perf_event:/
10:blkio:/
9:freezer:/
8:devices:/
7:memory:/
6:cpuacct:/
5:cpu:/
4:cpuset:/
3:net_prio:/LP6
2:name=systemd:/user/1000.user/1.session

Важно понимать, что net_prio cgroup это способ задания не 802.1p, а LP(linux priority). Применение этого механизма для задания 802.1p лишь один из возможных сценариев использования.

Advertisements

One thought on “QoS в Linux: 802.1p, net_prio cgroups

  1. Pingback: QoS в Linux: pfifo, prio, tc filter, SO_PRIORITY socket | Net-Labs.in

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s