From cc436932c6c082383da1d40aff9621d5f6fc68e3 Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Sun, 11 Oct 2026 12:08:49 +0200 Subject: [PATCH 1/2] sysctl: Use fq instead of pfifo_fast as the default qdisc fq paces locally generated TCP traffic at the rate the TCP stack computed for the socket. Data then leaves in an even stream instead of line-rate bursts, which are likely to overflow the small buffers of access points and switch ports in front of slow links (for example a laptop on wifi). fq also keeps a separate queue per flow and serves them in turn. When the local link is saturated, a single bulk transfer can no longer delay all other flows on the interface, as it can with the shared FIFO of pfifo_fast. Note: fq is meant for hosts that terminate TCP connections. On a router, fq_codel may be the better choice: forwarded packets have no local socket, so fq cannot pace them, while the CoDel part of fq_codel actively keeps queueing delay low. --- etc/kmod/whitelist.conf | 1 + etc/sysctl.d/90-default-qdisc.conf | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 etc/sysctl.d/90-default-qdisc.conf diff --git a/etc/kmod/whitelist.conf b/etc/kmod/whitelist.conf index 3a3a1705..4e9f3685 100644 --- a/etc/kmod/whitelist.conf +++ b/etc/kmod/whitelist.conf @@ -154,6 +154,7 @@ whitelist realtek # Realtek PHY driver whitelist rng_core # H/W Random Number Generator (RNG) driver whitelist rpcsec_gss_krb5 # Sun RPC Kerberos 5 module whitelist sb_edac # MC Driver for Intel Sandy Bridge and Ivy Bridge memory controllers +whitelist sch_fq # Fair Queue Packet Scheduler whitelist sch_prio # Simple 3-band priority qdisc whitelist sch_sfq # Stochastic Fairness qdisc whitelist sha3_generic # SHA-3 Secure Hash Algorithm diff --git a/etc/sysctl.d/90-default-qdisc.conf b/etc/sysctl.d/90-default-qdisc.conf new file mode 100644 index 00000000..cf52e1e1 --- /dev/null +++ b/etc/sysctl.d/90-default-qdisc.conf @@ -0,0 +1,19 @@ +# Use fq instead of pfifo_fast as the default qdisc. +# +# fq paces locally generated TCP traffic at the rate the TCP stack +# computed for the socket. Data then leaves in an even stream instead of +# line-rate bursts, which are likely to overflow the small buffers of +# access points and switch ports in front of slow links (for example a +# laptop on wifi). +# +# fq also keeps a separate queue per flow and serves them in turn. When +# the local link is saturated, a single bulk transfer can no longer delay +# all other flows on the interface, as it can with the shared FIFO of +# pfifo_fast. +# +# Note: fq is meant for hosts that terminate TCP connections. On a router, +# fq_codel may be the better choice: forwarded packets have no local +# socket, so fq cannot pace them, while the CoDel part of fq_codel actively +# keeps queueing delay low. + +net.core.default_qdisc = fq From bca3707ccee0a50e48f3ee6bfb092637a69fbeef Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Sun, 11 Oct 2026 13:09:01 +0200 Subject: [PATCH 2/2] mxrouter: Use fq_codel on router interfaces Set fq_codel on the physical interfaces of the router when they are brought up, instead of relying on the global default qdisc, which suits hosts better than routers. On multiqueue devices, keep mq as root and attach fq_codel to each tx queue. --- etc/kmod/whitelist.conf | 1 + mxrouter/mxrouterctl | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/etc/kmod/whitelist.conf b/etc/kmod/whitelist.conf index 4e9f3685..70375fbf 100644 --- a/etc/kmod/whitelist.conf +++ b/etc/kmod/whitelist.conf @@ -155,6 +155,7 @@ whitelist rng_core # H/W Random Number Generator (RNG) driver whitelist rpcsec_gss_krb5 # Sun RPC Kerberos 5 module whitelist sb_edac # MC Driver for Intel Sandy Bridge and Ivy Bridge memory controllers whitelist sch_fq # Fair Queue Packet Scheduler +whitelist sch_fq_codel # Fair Queue CoDel discipline whitelist sch_prio # Simple 3-band priority qdisc whitelist sch_sfq # Stochastic Fairness qdisc whitelist sha3_generic # SHA-3 Secure Hash Algorithm diff --git a/mxrouter/mxrouterctl b/mxrouter/mxrouterctl index 934ecfaa..3e55e7ff 100755 --- a/mxrouter/mxrouterctl +++ b/mxrouter/mxrouterctl @@ -423,10 +423,27 @@ sub radvd { our $want_if = {'lo' => 1}; # includes lo, veth and physical devices but not vlan devices our $want_veth; +# Use fq_codel, which suits forwarded traffic, instead of the global default +# qdisc. Keep mq on multiqueue devices and use fq_codel per tx queue. +sub set_qdisc_fq_codel { + my ($dev) = @_; + my $tx_queues = grep /^tx-/, scandir("/sys/class/net/$dev/queues"); + if ($tx_queues > 1) { + sys('tc', 'qdisc', 'replace', 'dev', $dev, 'root', 'handle', '1:', 'mq'); + for my $i (1 .. $tx_queues) { + sys('tc', 'qdisc', 'replace', 'dev', $dev, 'parent', sprintf('1:%x', $i), 'fq_codel'); + } + } else { + sys('tc', 'qdisc', 'replace', 'dev', $dev, 'root', 'fq_codel'); + } +} + sub configure_if { my ($want_if) = @_; for my $if (keys %$want_if) { - netif_is_up($if) or sys('ip', 'link', 'set', $if, "up"); + netif_is_up($if) and next; + sys('ip', 'link', 'set', $if, "up"); + -d "/sys/class/net/$if/device" and set_qdisc_fq_codel($if); } }