Files
qos-profiles/README.md
T
zpericic 86a0d2cdd1 Initial import of qos-profiles
Role subpackages set the system-wide default qdisc and TCP congestion
control via /usr/lib/sysctl.d, without pulling in the base package:

  server   fq + bbr        bare metal, VM guests
  vmhost   fq_codel + bbr  hypervisors, container hosts
  router   fq_codel + cubic
  desktop  fq_codel + cubic

The base package applies cake per interface from
/etc/qos-profiles/<iface>.conf, layered over role defaults and
/etc/qos-profiles/defaults.conf:

- LINK_RATE with per-direction overrides, shaped to SHAPE_PERCENT
  (default 95, per direction overridable)
- outbound fairness per source host and diffserv4; inbound via ifb,
  fairness per destination host, besteffort with DSCP wash
- NAT awareness, extra cake args (shared and per direction), raw
  qdisc overrides
- config parsed without executing it, validated before any change,
  previous state undone on each run

Applied by the qos-profiles@<iface> unit (bound to the device) or the
qos-profiles-networkmanager dispatcher subpackage, installed
automatically on hosts with NetworkManager. Includes ready-made
examples for VM hosts, OVH dual-NIC servers, DC and home routers.
2026-10-10 22:41:12 +02:00

4.8 KiB

qos-profiles

Default qdisc and TCP congestion control per machine role, plus optional per-interface qdiscs (cake, with ifb for inbound traffic).

Roles

Install exactly one role subpackage:

Subpackage default_qdisc congestion control cake NAT Use for
qos-profiles-server fq bbr no bare-metal servers without guests, VM guests
qos-profiles-vmhost fq_codel bbr no hypervisors, container hosts
qos-profiles-router fq_codel cubic yes routers
qos-profiles-desktop fq_codel cubic no workstations

The sysctl file is /usr/lib/sysctl.d/60-qos-profiles-<role>.conf; override it in /etc/sysctl.d/. default_qdisc only applies to interfaces created after it is set, so reboot after installing or switching roles. Congestion control is system-wide (or per route), not per interface.

Per-interface qdiscs

Needs the qos-profiles package; the role packages don't pull it in. Create /etc/qos-profiles/<iface>.conf, see /usr/share/qos-profiles/example.conf for all variables and /usr/share/qos-profiles/examples/ for ready-made setups:

Example Setup
defaults.conf site-wide /etc/qos-profiles/defaults.conf
vmhost-routed-uplink.conf VM host, guests routed via the host uplink (EVPN)
vmhost-egress-only.conf VM host, outbound fairness only at NIC line rate
vmhost-nat-guests.conf VM/container host with masqueraded guests
ovh-public.conf dual-NIC dedicated server, public NIC
ovh-vrack-private.conf private NIC capped by the provider, outbound only
dc-router-transit.conf datacenter router, transit uplink, no NAT
router-ftth.conf fibre with Ethernet handoff, NAT
router-vdsl-pppoe.conf VDSL2 with PPPoE on ppp0, NAT, ACK filtering
router-docsis.conf cable, NAT, ACK filtering
backup-nic-raw.conf raw fq qdisc with a per-flow cap instead of cake

Minimal example:

LINK_RATE=1gbit

This shapes both directions to 95% of the link rate with cake. Outbound, traffic is shared per source host and DiffServ classes are applied (diffserv4). Inbound, traffic is shared per destination host, DSCP marks are ignored (besteffort) and cleared (wash), since they come from the internet. EGRESS_SHAPE_PERCENT and INGRESS_SHAPE_PERCENT set the percentage per direction.

Configuration is read in order, later overriding earlier:

  1. /usr/lib/qos-profiles/role-<role>.conf — installed role package
  2. /etc/qos-profiles/defaults.conf — site-wide
  3. /etc/qos-profiles/<iface>.conf — the interface

It is applied by either:

  • qos-profiles-networkmanager (installed automatically with NetworkManager) when NetworkManager brings the interface up, or
  • systemctl enable --now qos-profiles@<iface> for interfaces NetworkManager doesn't manage. It runs whenever the device appears.

Both may be active; they're serialised and idempotent. To apply changes run systemctl restart qos-profiles@<iface> or /usr/libexec/qos-profiles/qos-apply start <iface>. Stopping restores the default qdisc and removes the ifb device.

Inbound shaping replaces any existing clsact qdisc on the interface (and its tc/BPF filters).

DiffServ

diffserv4 sorts outbound packets by DSCP into bulk (CS1), best effort, video (AF4x, CS3, ...) and voice (EF, CS6, ...). Higher classes get priority only up to a share of the rate, so they can't starve the others. Marking backup or replication traffic CS1 (e.g. nftables ip dscp set cs1) makes it yield to everything else.

Topologies

  • VM host, VMs routed via the host uplink (EVPN anycast gateway): cake on the uplink NIC gives each guest an equal share. VXLAN-encapsulated traffic on the same NIC is seen by its outer header (the VTEP address), so it shares as a single host.
  • VM host, VMs bridged to a switch, routing elsewhere: the WAN bottleneck is at the router; put cake on the router WAN (qos-profiles-router). The host only needs the role package.
  • Host with separate public and private NICs: configure the public NIC only.
  • Bond or VLAN uplink: these devices have no queue of their own; put cake on the physical NIC, or set a rate explicitly.