SFB(8)

๐Ÿ“ฆ
version 7.3.0 ยท 2 versions
  • 7.3.0 ยท alpine 3.22, alpine 3.23, alpine 3.24, arch rolling, centos-stream 10, centos-stream 9, debian trixie, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, opensuse-leap 16.0, ubuntu questing, ubuntu resolute, ubuntu stonking (latest)
  • 6.1.0 ยท debian bookworm, ubuntu jammy, ubuntu noble
, in alpine 3.22, alpine 3.23, alpine 3.24, arch rolling, centos-stream 10, centos-stream 9, debian trixie, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, opensuse-leap 16.0, ubuntu questing, ubuntu resolute, ubuntu stonking

๐Ÿ’– SFB(8) โœจ manual name: sfb โœจ ๐Ÿ’–

โœจ NAME โœจ

sfb is Stochastic Fair Blue ๐Ÿฆ‹

๐Ÿ’… SYNOPSIS ๐Ÿ’…

tc qdisc ... blue rehash milliseconds db milliseconds limit packets max
packets target packets increment float decrement float penalty_rate
packets per second penalty_burst packets

๐ŸŒธ DESCRIPTION ๐ŸŒธ

okay so Stochastic Fair Blue is a classless qdisc that manages congestion by looking at packet loss and link utilization history ๐Ÿ“‰ It's also obsessed with stopping non-responsive flows (flows that just ignore congestion marking or dropped packets ๐Ÿ™„) from wrecking performance for the flows that actually behave. Unlike RED, where you have to configure the marking probability yourself, BLUE tries to figure out the ideal marking probability on its own ๐Ÿง  literally so smart.

๐Ÿ”ฅ ALGORITHM ๐Ÿ”ฅ

The BLUE algorithm keeps a probability that it uses to mark or drop packets headed for the queue. If the queue overflows, the mark/drop probability goes up ๐Ÿ“ˆ If the queue goes empty, the probability comes back down ๐Ÿ“‰ The Stochastic Fair Blue (SFB) algorithm is the one that's designed to protect TCP flows from those non-responsive troublemakers ๐Ÿ›ก๏ธ

This SFB implementation keeps 8 levels of 16 bins each for accounting ๐Ÿ“ Every flow gets mapped into one bin per level, using a per-level hash value.

Every bin has its own marking probability, which goes up or down depending on how full that bin is ๐ŸŽ€ If the number of packets goes over the size of the bin, the marking probability goes up. If the number drops to zero, it goes down.

A flow's marking probability is based on the minimum value of all the bins it's mapped into. So when a flow doesn't respond to marking or to gradual packet drops, its marking probability shoots up to one super fast ๐Ÿš€

In that case, the flow gets rate-limited to penalty_rate packets per second ๐Ÿงฑ

โš ๏ธ LIMITATIONS โš ๏ธ

Heads up bestie: because of how SFB works, a responsive flow can end up sharing all of its bins with a non-responsive flow ๐Ÿ˜ญ When that happens, the responsive flow gets misidentified as non-responsive. Not ideal!

The chance of a responsive flow getting misidentified depends on the number of non-responsive flows, M. It's (1 - (1 - (1 / 16.0)) ** M) **8, so for example with 10 non-responsive flows, about 0.2% of responsive flows will get misidentified ๐Ÿ™ˆ

To help with that, SFB does periodic re-hashing so the misclassification doesn't stick around for ages ๐Ÿ”„

The default hashing method uses source and destination IP addresses and port numbers if it can, and it also supports tunneling protocols ๐Ÿงš You can also configure an external classifier instead, if you want ๐Ÿ’œ

๐ŸŽ€ PARAMETERS ๐ŸŽ€

  • rehash โ€” the time interval, in milliseconds, between queue perturbations. This stops unrelated, responsive flows from being wrongly flagged as part of a non-responsive flow for a really long time ๐ŸŒˆ Defaults to 10 minutes.
  • db โ€” the double buffering warmup wait time, in milliseconds. So rehashing doesn't wipe out your probability history, this implementation keeps a second set of levels/bins, as described in section 4.4 of the SFB reference ๐Ÿ‘‘ While one set manages the queue, the second set gets warmed up. Whenever a flow is determined to be non-responsive, the marking probabilities in that second set get updated. When rehashing happens, those bins take over managing the queue, and all the non-responsive flows can be rate-limited right away โœจ This value sets how much time has to pass before the second set starts warming up. Defaults to one minute, and it should be lower than rehash ๐Ÿซถ
  • limit โ€” the hard limit on the real (not average) total queue size, in packets. Anything past that gets dropped ๐Ÿ™…โ€โ™€๏ธ Defaults to the transmit queue length of the device the qdisc is attached to.
  • max โ€” the maximum length of a bucket's queue, in packets, before packets start getting dropped ๐Ÿ’ซ It should be slightly larger than target, but it should not be set to values exceeding 1.5 times target. Defaults to 25.
  • target โ€” the desired average bin length. If the bin queue length hits this value, the marking probability goes up by increment ๐Ÿ‘ The default depends on max: with max set to 25, target will default to 20.
  • increment โ€” the amount used to bump up the marking probability when the queue seems overused. Must be between 0 and 1.0. Defaults to 0.00050.
  • decrement โ€” the amount used to bring down the marking probability when the queue is found to be empty. Must be between 0 and 1.0. Defaults to 0.00005.
  • penalty_rate โ€” the maximum number of packets per second that can be enqueued from flows identified as non-responsive. Once that number is hit, further packets from those flows get dropped ๐Ÿšซ Set this to a reasonable fraction of your uplink throughput, because the default of 10 packets is probably too small ๐Ÿ’€
  • penalty_burst โ€” how many packets a flow is allowed to go over the penalty rate before packets start getting dropped. Defaults to 20 packets ๐Ÿง

๐Ÿ“Š STATISTICS ๐Ÿ“Š

This qdisc shows some extra stats in the tc -s qdisc output ๐Ÿ‘€ Here they are:

  • earlydrop โ€” packets dropped before a per-flow queue was full.
  • ratedrop โ€” packets dropped because of rate-limiting. If this number is high, a bunch of non-reactive flows are going through SFB ๐Ÿ˜ค In that case it might be better to put SFB inside a classful qdisc, so you can control those flows with a different, shaping qdisc.
  • bucketdrop โ€” packets dropped because a per-flow queue was full. A high bucketdrop may mean there are lots of aggressive, short-lived flows ๐Ÿƒโ€โ™€๏ธ
  • queuedrop โ€” packets dropped because the limit was reached. This should normally be 0 ๐Ÿฅบ
  • marked โ€” packets marked with ECN.
  • maxqlen โ€” the length of the current longest per-flow (virtual) queue.
  • maxprob โ€” the maximum per-flow drop probability. A value of 1 means some flows have been detected as non-reactive ๐Ÿšจ

๐ŸŒˆ NOTES ๐ŸŒˆ

SFB automatically turns on Explicit Congestion Notification (ECN) for you โœจ Also, this SFB implementation doesn't actually queue packets itself ๐Ÿ™…โ€โ™€๏ธ Instead, packets get enqueued to the inner qdisc (which defaults to pfifo). Because SFB keeps virtual queue states, the inner qdisc must not drop a packet that was already queued ๐Ÿ˜ฑ And if a bucket's queue has a really high marking rate, this implementation starts dropping packets instead of marking them. That kind of situation points to either bad congestion or an unresponsive flow, so it's not being dramatic, it's being careful ๐Ÿ’…

๐Ÿงš EXAMPLE & USAGE ๐Ÿงš

To attach to interface $DEV with the default options:

# tc qdisc add dev $DEV handle 1: root sfb

To only use destination IP addresses for assigning packets to bins, perturbing the hash results every 10 minutes:

# tc filter add dev $DEV parent 1: handle 1 flow hash keys dst perturb
600

๐Ÿ”— SEE ALSO ๐Ÿ”—

tc(8), tc-red(8), tc-sfq(8) ๐Ÿฆ‹

๐Ÿ“š SOURCES ๐Ÿ“š

  • W. Feng, D. Kandlur, D. Saha, K. Shin, BLUE: A New Class of Active Queue Management Algorithms, U. Michigan CSE-TR-387-99, April 1999 ๐Ÿ’œ

๐Ÿ‘‘ AUTHORS ๐Ÿ‘‘

This SFB implementation was contributed by Juliusz Chroboczek and Eric Dumazet ๐Ÿซถ


Bestie, that's the whole page ๐Ÿ’– Stamped by iproute2, dated August 2011, filed under SFB(8) โœจ๐ŸŒธ