We loosely follow the TSN VLAN configuration guide.
These steps must be performed as root (e.g., by using sudo).
This configuration is only necessary for AVB talkers (senders).
Set up VLAN
intf=eth0 # network interface to use
vlan=5 # VLAN id
First, we can check if the network interface has QoS capabilities:
ethtool -l $intf should show multiple entries for rx and tx, respectively.
Add a new VLAN type network link with certain parameters:
ip link add link ${intf} name ${intf}.${vlan} type vlan id ${vlan} mvrp on egress-qos-map 2:2 3:3
- mvrp on: specifies that this VLAN should be registered using the Multiple VLAN Registration Protocol.
- egress-qos-map 2:2 3:3: defines a mapping of Linux internal packet priority to VLAN header prio field for outgoing frames.
Bring up this link using ip link set ${intf}.${vlan} up
Settings can be queried with cat /proc/net/vlan/${intf}.${vlan}.
Configure queuing disciplines (qdiscs)
MQPRIO qdisc
Add the MQPRIO qdisc to the root qdisc to expose hardware queues in the TC system. The command below configures MQPRIO for the Intel I210 ethernet controller with 4 transmission queues:
tc qdisc add dev ${intf} parent root handle 6666 mqprio
num_tc 3
map 2 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2
queues 1@0 1@1 2@2
hw 0
- num_tc 3: Number of traffic classes to use. You cannot have more classes than queues.
- map ...: The priority to traffic class map. Maps priorities 0..15 to a specified traffic class. In our case priorities 0 and 1 are mapped to traffic class 2, priority 2 is mapped to traffic class 1, priority 3 is mapped to traffic class 0.
- queues 1@0 1@1 2@2: Provide count@offset of queue range for each traffic class. In the format, count@offset. Queue ranges for each traffic classes cannot overlap and must be a contiguous range of queues.
- hw 0: Set to 1 to support hardware offload. If arguments are provided that the hardware can not support then an error is returned.
Credit-based traffic shaping (CBS)
CBS needs to be configured as described on the manual page.
$port_transmit_rate: bandwidth of port, e.g. 1000000 (1 Gbit/s)$max_frame_size: maximum burst of traffic in bytes (MTU usually 1500, except for "jumbo frames")$idleslope: used bandwidth in kbits/s (e.g. 50000 for 169600032 bits)$max_interference_size = $max_frame_size$sendslope = $idleslope - $port_transmit_rate$hicredit = $max_interference_size * $idleslope /$port_transmit_rate$locredit = $max_frame_size * $sendslope / $port_transmit_rate
Calculate bandwidth (bits/s), e.g. with:
channels=8
samplerate=48000
bitdepth=32
bandwidth=$((channels*samplerate*bitdepth))
The bandwidth defines the CBS parameters:
idleslope=$((bandwidth/1000))
port_transmit_rate=1000000
max_frame_size=1500
max_interference_size=$max_frame_size
sendslope=$((idleslope-port_transmit_rate))
hicredit=$((max_interference_size*idleslope/port_transmit_rate))
locredit=$((max_frame_size*sendslope/port_transmit_rate))
Set CBS for class A with tc qdisc replace dev $intf parent 6666:1 handle 7777 cbs locredit $locredit hicredit $hicredit sendslope $sendslope idleslope $idleslope offload 1 and for class B with tc qdisc replace dev $intf parent 6666:2 handle 8888 cbs locredit $locredit hicredit $hicredit sendslope $sendslope idleslope $idleslope offload 1
ETF qdiscs
Configure the ETF qdiscs as children of CBS qdiscs, see manual page.
tc qdisc add dev $intf parent 7777:1 etf \
clockid CLOCK_TAI \
delta 500000 \
offload
tc qdisc add dev $intf parent 8888:1 etf \
clockid CLOCK_TAI \
delta 500000 \
offload
The qdisc configuration can be inspected with tc qdisc show dev ${intf}.