Linux Traffic Control: How tc Shapes Bandwidth

The Linux Traffic Control (tc) subsystem regulates the flow of network packets by scheduling, prioritizing, policing, and shaping traffic as it traverses the kernel's networking stack. Bandwidth shaping is primarily achieved on egress by delaying or queuing outbound packets using specialized algorithms known as Queueing Disciplines (qdiscs), supported by classes and filters. By intercepting packets before they reach the network interface card (NIC), tc ensures that transmission rates adhere to administrator-defined limits, mitigating network congestion and eliminating bufferbloat.

The Three Core Components: Qdiscs, Classes, and Filters

The architecture of tc relies on three foundational elements that structure how network packets are categorized and scheduled:

  1. Queueing Disciplines (qdiscs): A qdisc represents the algorithm applied to a network interface's packet queue. Qdiscs can be classless (applied universally to all traffic, such as pfifo_fast, fq_codel, or tbf) or classful (capable of containing nested sub-queues with different rules, such as htb or cbq).
  2. Classes: Classes exist within classful qdiscs to partition total bandwidth into multiple virtual channels. Each class can be assigned specific parameters, such as a guaranteed minimum rate, a maximum burst rate, and a priority level.
  3. Filters (Classifiers): Filters inspect incoming or outgoing packets using criteria like source/destination IP addresses, port numbers, or protocol types (often utilizing u32 matching or ebpf). When a filter matches a packet, it directs that packet to the appropriate class for processing.

The Token Bucket Mechanism for Shaping

True traffic shaping involves delaying packets rather than simply discarding them (the latter being traffic policing). The tc subsystem accomplishes this using the Token Bucket algorithm, commonly implemented via the Token Bucket Filter (tbf) or Hierarchical Token Bucket (htb).

In this model, a virtual bucket continuously accumulates tokens at a fixed, configured rate (representing allowed bandwidth). Each token grants permission to transmit a specific number of bytes:

Hierarchical Token Bucket (htb) expands on this concept by allowing idle classes to lend unused tokens to other classes under heavy load, maximizing total link utilization while maintaining hard rate ceilings.

Egress vs. Ingress Shaping

Bandwidth shaping inherently requires control over when a packet is transmitted, making it natively suited for outbound (egress) interfaces. At the egress point, the Linux kernel holds packets in system memory buffers and feeds them to the hardware device ring buffer strictly according to the qdisc's scheduler.

Because Linux cannot directly control the rate at which external systems transmit inbound (ingress) traffic, standard qdiscs cannot delay incoming packets. To apply full bandwidth shaping to ingress traffic, tc typically redirects incoming packets to an Intermediate Functional Block (ifb) pseudo-device. Once redirected, the incoming traffic is treated as egress traffic on the ifb device, allowing the full suite of classful schedulers and token-bucket algorithms to shape the flow before it reaches higher-layer applications.