Configure tc-mqprio Queues Without Losing the Rollback
You will create an mqprio queuing discipline that maps socket priorities to traffic classes and hardware queue ranges, inspect the result, and remove it again. The examples use software coordination first, so they do not silently depend on a particular network card.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow 15 to 20 minutes. You need the iproute2 package, an interface with enough transmit queues for the example, and root privileges for changes. This guide was checked with tc from iproute2 6.1.0. The installed manual page is dated 24 September 2013, so hardware capabilities remain driver-specific even though the command syntax is stable here.
1. Record the interface before changing it
Choose the interface and inspect its current qdisc and queue information. Replace the placeholder with the real device name:
IFACE=eno1
tc qdisc show dev "$IFACE"
ip -details link show dev "$IFACE"
ethtool -l "$IFACE"
The first command records the current root qdisc. The other two help you check whether the device exposes at least eight transmit queues. The example below uses two traffic classes, each covering four queues, for a total range of queues 0 through 7. Do not copy that queue layout onto an interface with fewer queues.
Checkpoint
Save the output of tc qdisc show. If you need to undo the test, you should know what was present before it. Reading these details does not require sudo on most systems.
2. Understand the map before applying it
mqprio uses a priority-to-traffic-class map. The map has entries for priorities 0 through 15, in that order. In this example, priorities 0 to 3 go to class 0, priorities 4 to 7 go to class 1, and the pattern is repeated for priorities 8 to 15:
map 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
A class is not one queue. It is a group of contiguous queues. The corresponding queue declaration is queues 4@0 4@4: class 0 owns four queues starting at offset 0, while class 1 owns four starting at offset 4. Queue ranges must not overlap and must form a contiguous range.
The manual describes eight traffic classes and priorities 0 through 7 as the creation defaults, with priorities above 7 mapped to class 0. This example overrides those defaults with two classes and an explicit map, which is easier to review. It also uses hw 0, meaning that the requested values are configured in software without hardware coordination.
3. Apply a software-only configuration
Run this as root after changing IFACE. The command replaces the interface root qdisc, so existing root-qdisc behaviour changes immediately:
sudo tc qdisc replace dev "$IFACE" root handle 1: mqprio num_tc 2 map 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 queues 4@0 4@4 hw 0
There is normally no success message. An error about an invalid queue count or range means the interface does not match the example; stop and correct the queue layout rather than guessing offsets.
Checkpoint
Inspect the live configuration:
$ sudo tc -s qdisc show dev "$IFACE"
qdisc mqprio 1: root ...
The exact statistics and formatting vary. Look for an mqprio root qdisc and the two traffic classes or their queue ranges. The command shows configuration and counters; it does not prove that an application is setting the priorities you expect.
4. Connect priorities to real traffic
MQPRIO classifies the packet priority already attached to each socket or packet. A process with sufficient privileges can set a socket priority with SO_PRIORITY. Firewall rules can set priority for matching flows, and the net_prio cgroup can assign priority to sockets belonging to an application.
Do not infer traffic-class use from the existence of the qdisc. Check the application or classification rule that supplies the priority, then watch the per-qdisc counters while generating a controlled test flow:
sudo tc -s qdisc show dev "$IFACE"
sudo tc -s class show dev "$IFACE" parent 1:
If the class command reports no matching classes, use the qdisc output as the source of truth for the handle and inspect the device's supported output. Avoid changing firewall or cgroup policy as part of an initial qdisc test, because that introduces a second source of failure.
5. Request hardware offload only when the driver supports it
hw 1 asks for hardware offload. In channel mode, the full MQPRIO configuration, queue layout and quality-of-service attributes are sent to the hardware. That request can fail when the driver or device cannot represent one of the values. A failure is not evidence that the software configuration was applied.
After the software test is understood, a device-specific trial might look like this:
sudo tc qdisc replace dev "$IFACE" root handle 1: mqprio num_tc 2 map 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 queues 4@0 4@4 hw 1 mode channel
This is a service-affecting change. It has no universal success output, and tc cannot make an unsupported adapter accept the request. The dcb mode is a narrower hardware-offload choice that lets the hardware use its quality-of-service defaults. Both modes require hardware support and hw 1.
Bandwidth limits use the hardware shaper syntax, for example shaper bw_rlimit min_rate 1Gbit 100Mbit max_rate 10Gbit 1Gbit. Use this only after checking the driver's rate units and limits. A rate-limited class can deliberately change throughput, so do not add it to a production interface as a harmless verification step.
6. Remove the test configuration
Warning
Deleting the root qdisc is disruptive and may restore a device default rather than the exact qdisc you recorded. Stop any controlled traffic first. Then remove the MQPRIO qdisc:
sudo tc qdisc del dev "$IFACE" root
tc qdisc show dev "$IFACE"
If you need the previous configuration, reapply the exact command from your change record instead of assuming that deletion recreates it. If the interface is managed by NetworkManager, systemd-networkd or another network service, its next reload may also replace a manually applied qdisc. Keep the rollback command and service configuration under the same change record.
Common traps
- Too few queues:
queues 4@0 4@4needs eight queues. Inspect the device first. - Overlapping ranges: each class needs its own contiguous range. Offsets are not traffic-class numbers.
- Wrong map length:
mapdescribes priorities 0 through 15, not just the priorities you currently use. - Assuming offload:
hw 1requests coordination with hardware; it does not guarantee that the driver can implement the request. - Checking the wrong state:
tc -sreports qdisc statistics, not the source of an application's socket priority.
Done means
- The interface and its existing root qdisc were recorded.
- The map has 16 entries and the queue ranges are contiguous, non-overlapping and supported by the device.
tc -s qdisc showconfirms the intended MQPRIO configuration.- Hardware mode was attempted only after software behaviour was understood and driver support was checked.
- The original configuration or a tested rollback command is available before production use.