sqm-scripts & systemd-networkd

I recently found the sqm-scripts repository and decided I wanted to use it on my home router, but I could never make the service run as expected on my setup (Debian 11, systemd-networkd) with the default service definition.

Why? Because I like cake…eh…I want a controlled delay even when my family is trying their best to use all available bandwidth. This was a simple way of fixing bufferbloat so I took it! :-)

sqm-scripts will create a virtual interface for your WAN facing interface (ifb4<interface>), as traffic shaping only can be applied on outgoing traffic from an interface. It will then apply limiting on this virtual interface, and on your real outgoing interface. Pretty neat, actually!

Installing

Clone the repository somewhere and run make install.

# git clone https://github.com/tohojo/sqm-scripts.git
# cd sqm-scripts
# make install

This will copy a bunch of files to a bunch of places on your system. One important such place is /etc/sqm in which default.conf which you copy to /etc/sqm/<interface>.iface.conf (enp1s0 in my case) and customize it’s values.

Here’s my /etc/sqm/enp1s0.iface.conf:

# cat /etc/sqm/enp1s0.iface.conf
UPLINK=90000
DOWNLINK=225000
SCRIPT=piece_of_cake.qos
ENABLED=1
QDISC=cake

I have a 250/100 Mbps service, and my values are probably much lower than necessary.

Enable and start the service:

# systemctl enable --now sqm@enp1s0.service

Now test with fast.com, speedtest.net and/or dslreports.com and check the loaded/unloaded ping times, they should be very close now. You should also have a new interface named something like ifb4enp1s0, but you still apply firewall rules on your ‘real’ WAN facing interface.

Making the sqm service run as expected

I’m not sure this service definition file is exactly what equivalent to the original one, but this one runs after my network is up as expected!

# Install as sqm@.service and place it in /etc/systemd/system
# Then run systemctl daemon-reload and enable it for your internet
# facing interface.
[Unit]
Description=SQM scripts for iface %i
Wants=network-online.target
After=network.target network-online.target

[Service]
Type=oneshot
EnvironmentFile=/etc/sqm/default.conf
EnvironmentFile=-/etc/sqm/%i.iface.conf
Environment=IFACE=%i ENABLED=1
ExecStart=/usr/lib/sqm/start-sqm
ExecStop=/usr/lib/sqm/stop-sqm
RemainAfterExit=1

[Install]
WantedBy=multi-user.target

I’ve also been very clear with my systemd-networkd on when I want it to consider my network to be up – after my internet facing interface is up. One way to do this is by customizing the service file for systemd-networkd-wait-online.service like so:

# Save as /etc/systemd/system/systemd-networkd-wait-online.service.d/wait-for-main-interface.conf
[Service]
ExecStart=
ExecStart=/usr/lib/systemd/systemd-networkd-wait-online -i enp1s0

Ansible role

I wrote an Ansible role for setting this up on a Debian system. If does nothing more than what is described here, but it Feels Good™ to have it automated.