Operations 12 min read

How to Use Linux TC for Precise Bandwidth and Burst Control

This guide explains Linux traffic control (TC), covering its core components, queueing disciplines, classes, filters, burst parameters, and provides step‑by‑step command examples to limit download speeds for individual IPs or subnets.

ITPUB
ITPUB
ITPUB
How to Use Linux TC for Precise Bandwidth and Burst Control

Introduction

Linux traffic control (TC) provides a flexible framework for shaping outbound network traffic. By defining bandwidth limits, rate ceilings, and burst behavior, TC can prevent a single host from monopolizing a shared link.

TC Architecture

TC is built from three core components:

Queueing Discipline (qdisc) : Determines how packets are queued and dequeued on an interface. The simplest qdisc, pfifo, queues packets FIFO without modification.

Class : Represents a traffic‑shaping policy (e.g., a guaranteed rate). Classes can be arranged hierarchically, allowing parent classes to allocate bandwidth to child classes.

Filter : Classifies packets into classes based on criteria such as IP address, fwmark, or u32 matches.

Common qdisc types include FIFO, RED, SFQ, Token Bucket, CBQ, and the hierarchical token bucket (HTB), which is the preferred replacement for CBQ.

Key Parameters

rate : Guaranteed bandwidth for a class.

ceil : Maximum bandwidth a class may borrow; must be at least equal to its rate and to the ceil of any child classes.

prio : Priority value; lower numbers indicate higher priority when bandwidth is contested.

burst / cburst : Amount of data that can be transmitted at the interface’s line rate before the shaping limit takes effect. These values should be at least as large as the corresponding values of child classes.

Typical Configuration Workflow

Assuming eth0 is the outbound interface, the following steps create a root HTB qdisc, define a parent class, add child classes, attach a fair‑queueing discipline, and install filters.

Add a root HTB qdisc that will host all classes:

tc qdisc add dev eth0 root handle 1: htb default 1

Create a parent class that sets the overall bandwidth ceiling for the interface:

tc class add dev eth0 parent 1:0 classid 1:30 htb rate 2mbit ceil 4mbit prio 2

Add a child class for a specific application or IP group:

tc class add dev eth0 parent 1:30 classid 1:31 htb rate 0.5mbit ceil 2mbit prio 3

Attach a fair‑queueing discipline (SFQ) to the child class to prevent a single flow from monopolizing the class:

tc qdisc add dev eth0 parent 1:31 handle 31: sfq perturb 10

Insert a filter that maps marked packets to the child class. The example uses an fwmark set by iptables:

tc filter add dev eth0 parent 1: protocol ip prio 31 handle 31 fw flowid 1:31

Marking Packets with iptables

Packets can be marked in the mangle table and then matched by TC filters using the fwmark classifier.

iptables -t mangle -I FORWARD -i !eth1 -p tcp --sport 80 -s xxx.xxx.xxx.xxx -j MARK --set-mark 31

Practical Examples

Example 1 – Limit a single IP

tc qdisc add dev eth0 root handle 1: htb r2q 1</code>
<code>tc class add dev eth0 parent 1: classid 1:1 htb rate 30mbit ceil 60mbit</code>
<code>tc filter add dev eth0 parent 1: protocol ip prio 16 u32 match ip dst 192.168.1.2 flowid 1:1

This limits traffic to 192.168.1.2 to 30 Mbit with a maximum burst up to 60 Mbit.

Example 2 – Limit a /24 subnet and share bandwidth

tc qdisc add dev eth0 root handle 1: htb r2q 1</code>
<code>tc class add dev eth0 parent 1: classid 1:1 htb rate 50mbit ceil 1000mbit</code>
<code>tc filter add dev eth0 parent 1: protocol ip prio 16 u32 match ip dst 192.168.111.0/24 flowid 1:1</code>
<code>tc qdisc add dev eth0 parent 1:1 handle 10: sfq perturb 10

The subnet 192.168.111.0/24 receives a total of 50 Mbit (up to 1000 Mbit if unused), and the SFQ discipline prevents any single host from consuming the entire share.

Command Reference

Common TC command syntax:

tc qdisc [add|change|replace|link] dev DEV [parent qdisc-id|root] [handle qdisc-id] qdisc [qdisc‑specific parameters]
tc class [add|change|replace] dev DEV parent qdisc-id [classid class-id] qdisc [qdisc‑specific parameters]
tc filter [add|change|replace] dev DEV [parent qdisc-id|root] protocol PROTO prio PRIORITY filtertype [filter‑specific parameters] flowid FLOW-ID

Show current configuration (including statistics):

tc -s -d qdisc show dev eth0</code>
<code>tc -s -d class show dev eth0</code>
<code>tc filter show dev eth0

Delete the root qdisc when cleaning up:

tc qdisc del dev eth0 root
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

networkLinuxtraffic controltcbandwidth shaping
ITPUB
Written by

ITPUB

Official ITPUB account sharing technical insights, community news, and exciting events.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.