TC(8)

๐ŸŽ€ NAME ๐ŸŽ€

okay so the manual page for tc (the traffic control tool) has a whole section on this one: drr - deficit round robin scheduler ๐Ÿ’–

๐Ÿงš SYNOPSIS ๐Ÿงš

tc qdisc ... add drr [ quantum bytes ]

๐Ÿ’… DESCRIPTION ๐Ÿ’…

okay bestie, the Deficit Round Robin Scheduler is a classful queuing discipline ๐Ÿ‘‘ and it's giving a more flexible upgrade to Stochastic Fairness Queuing (SFQ) โœจ

unlike SFQ, there are no built-in queues ๐Ÿ™ˆ you have to add your own classes and then set up filters so packets get sorted into them. this is lowkey super useful if you want, say, RED qdiscs with different settings for specific traffic ๐Ÿฆ‹ also, there is no default class. if a packet can't be classified, it gets dropped ๐Ÿ’€

๐ŸŒˆ ALGORITHM ๐ŸŒˆ

every class gets its own deficit counter, and it starts out equal to quantum ๐Ÿซถ

DRR keeps an (internal) active list of classes whose qdiscs are non-empty, and this list is what drives dequeuing ๐Ÿ”ฅ a packet gets dequeued from the class sitting at the head of the list if the packet size is smaller than or equal to the deficit counter. if the counter is too small, it gets bumped up by quantum and the scheduler moves on to the next class in the active list. the way that it just keeps cycling, no cap, iconic ๐Ÿ’œ

๐Ÿ“ PARAMETERS ๐Ÿ“

  • quantum โ€” the number of bytes a flow is allowed to dequeue before the scheduler moves on to the next class ๐ŸŽ€ it defaults to the MTU of the interface, and the minimum value is 1 โœจ

๐Ÿฆ‹ EXAMPLE & USAGE ๐Ÿฆ‹

okay so to attach to device eth0 and use the interface MTU as the quantum:

# tc qdisc add dev eth0 handle 1 root drr

next up, adding two classes ๐ŸŒธ

# tc class add dev eth0 parent 1: classid 1:1 drr
# tc class add dev eth0 parent 1: classid 1:2 drr

you also need to add at least one filter to classify packets, otherwise nothing gets sorted ๐Ÿ™ˆ

# tc filter add dev eth0 protocol .. classid 1:1
bestie, real talk: like SFQ, DRR is only useful when it owns the queue ๐Ÿšจ it's a pure scheduler and does not delay packets. attaching non-work-conserving qdiscs like tbf to it does not make sense, because other qdiscs in the active list will also go inactive until the dequeue operation succeeds. to make sure it owns the queue, embed DRR within another qdisc like HTB or HFSC ๐Ÿ’–

if you want to mimic SFQ behavior, you can assign packets to the attached classes using the flow filter ๐Ÿงš

tc qdisc add dev .. drr

for i in .. 1024;do
     tc class add dev .. classid $handle:$(print %x $i)
     tc qdisc add dev .. fifo limit 16
done

tc filter add .. protocol ip .. $handle flow hash keys
src,dst,proto,proto-src,proto-dst divisor 1024 perturb 10

๐Ÿ“š SOURCE ๐Ÿ“š

  • M. Shreedhar and George Varghese "Efficient Fair Queuing using Deficit Round Robin", Proc. SIGCOMM 95. ๐Ÿซถ

๐Ÿ™ˆ NOTES ๐Ÿ™ˆ

heads up, this implementation does not drop packets from the longest queue on overrun ๐Ÿ˜ญ that's because limits get handled by the individual child qdiscs instead โœจ

๐Ÿ”— SEE ALSO ๐Ÿ”—

tc(8), tc-htb(8), tc-sfq(8) ๐Ÿ’œ

๐Ÿ‘‘ AUTHOR ๐Ÿ‘‘

sched_drr was written by Patrick McHardy, who is absolutely iconic ๐ŸŒˆ


bestie, that's the whole thing! ๐Ÿ’– this page is from iproute2, dated January 2010, and it's the TC(8) manual ๐ŸŽ€ stay fair, stay fast, and keep those queues flowing ๐Ÿ’…๐Ÿซถโœจ

๐Ÿ“ฆ where this page comes from