Set up Linux network traffic shaping with tc and QoS for bandwidth management

Advanced 45 min Apr 28, 2026 76 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Learn how to implement advanced network traffic control on Linux using tc (traffic control) and HTB (Hierarchical Token Bucket) queueing disciplines. This tutorial covers bandwidth limiting, QoS policies, and traffic prioritization for optimal network performance.

Prerequisites

  • Root or sudo access
  • Basic networking knowledge
  • Understanding of Linux command line

What this solves

Network traffic shaping controls bandwidth usage and prioritizes different types of traffic on your Linux server or gateway. This prevents any single application or user from consuming all available bandwidth while ensuring critical services get the resources they need.

Step-by-step configuration

Install traffic control tools

Install the iproute2 package which contains the tc command and related traffic shaping utilities.

sudo apt update
sudo apt install -y iproute2 tc
sudo dnf install -y iproute-tc

Identify network interface

Find the network interface you want to apply traffic shaping to. This is typically eth0, ens3, or similar.

ip link show
ip addr show

Create root queueing discipline

Set up the HTB (Hierarchical Token Bucket) root queueing discipline on your network interface. Replace eth0 with your actual interface name.

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

This creates a root queueing discipline with handle 1: and sets the default class to 30 for unclassified traffic.

Configure bandwidth classes

Create hierarchical traffic classes with different bandwidth allocations. This example creates a 100Mbit total with three priority levels.

# Root class - total bandwidth limit
sudo tc class add dev eth0 parent 1: classid 1:1 htb rate 100mbit

High priority class - 50% of bandwidth, can burst to 80%

sudo tc class add dev eth0 parent 1:1 classid 1:10 htb rate 50mbit ceil 80mbit prio 1

Medium priority class - 30% of bandwidth, can burst to 60%

sudo tc class add dev eth0 parent 1:1 classid 1:20 htb rate 30mbit ceil 60mbit prio 2

Low priority class - 20% of bandwidth, can burst to 40%

sudo tc class add dev eth0 parent 1:1 classid 1:30 htb rate 20mbit ceil 40mbit prio 3

Add leaf queueing disciplines

Attach leaf queueing disciplines to each class for packet scheduling. SFQ (Stochastic Fair Queueing) ensures fair distribution within each class.

sudo tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10
sudo tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10
sudo tc qdisc add dev eth0 parent 1:30 handle 30: sfq perturb 10

Create traffic classification filters

Set up filters to classify traffic into different classes based on ports, protocols, or IP addresses.

# SSH traffic (port 22) - high priority
sudo tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dport 22 0xffff flowid 1:10

HTTP/HTTPS traffic (ports 80, 443) - medium priority

sudo tc filter add dev eth0 protocol ip parent 1:0 prio 2 u32 match ip dport 80 0xffff flowid 1:20 sudo tc filter add dev eth0 protocol ip parent 1:0 prio 2 u32 match ip dport 443 0xffff flowid 1:20

SMTP traffic (port 25) - high priority

sudo tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dport 25 0xffff flowid 1:10

FTP traffic (port 21) - low priority

sudo tc filter add dev eth0 protocol ip parent 1:0 prio 3 u32 match ip dport 21 0xffff flowid 1:30

Configure IP-based traffic shaping

Apply different bandwidth limits to specific IP addresses or subnets for more granular control.

# Limit specific IP to 10Mbit
sudo tc class add dev eth0 parent 1:1 classid 1:40 htb rate 10mbit ceil 15mbit
sudo tc qdisc add dev eth0 parent 1:40 handle 40: sfq perturb 10
sudo tc filter add dev eth0 protocol ip parent 1:0 prio 4 u32 match ip src 192.168.1.100/32 flowid 1:40

Limit subnet to 20Mbit total

sudo tc class add dev eth0 parent 1:1 classid 1:50 htb rate 20mbit ceil 25mbit sudo tc qdisc add dev eth0 parent 1:50 handle 50: sfq perturb 10 sudo tc filter add dev eth0 protocol ip parent 1:0 prio 5 u32 match ip src 192.168.2.0/24 flowid 1:50

Add DSCP-based QoS classification

Configure traffic shaping based on DSCP (Differentiated Services Code Point) markings for enterprise QoS compliance.

# Voice traffic (DSCP EF - 46) - highest priority
sudo tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip tos 0xb8 0xfc flowid 1:10

Video traffic (DSCP AF41 - 34) - high priority

sudo tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip tos 0x88 0xfc flowid 1:10

Best effort traffic (DSCP 0) - low priority

sudo tc filter add dev eth0 protocol ip parent 1:0 prio 3 u32 match ip tos 0x00 0xfc flowid 1:30

Create traffic shaping startup script

Create a script to automatically apply traffic shaping rules at boot time.

#!/bin/bash

Network interface

INTERFACE="eth0"

Remove existing rules

tc qdisc del dev $INTERFACE root 2>/dev/null

Create root qdisc

tc qdisc add dev $INTERFACE root handle 1: htb default 30

Root class

tc class add dev $INTERFACE parent 1: classid 1:1 htb rate 100mbit

Priority classes

tc class add dev $INTERFACE parent 1:1 classid 1:10 htb rate 50mbit ceil 80mbit prio 1 tc class add dev $INTERFACE parent 1:1 classid 1:20 htb rate 30mbit ceil 60mbit prio 2 tc class add dev $INTERFACE parent 1:1 classid 1:30 htb rate 20mbit ceil 40mbit prio 3

Leaf qdiscs

tc qdisc add dev $INTERFACE parent 1:10 handle 10: sfq perturb 10 tc qdisc add dev $INTERFACE parent 1:20 handle 20: sfq perturb 10 tc qdisc add dev $INTERFACE parent 1:30 handle 30: sfq perturb 10

Filters

tc filter add dev $INTERFACE protocol ip parent 1:0 prio 1 u32 match ip dport 22 0xffff flowid 1:10 tc filter add dev $INTERFACE protocol ip parent 1:0 prio 2 u32 match ip dport 80 0xffff flowid 1:20 tc filter add dev $INTERFACE protocol ip parent 1:0 prio 2 u32 match ip dport 443 0xffff flowid 1:20 echo "Traffic shaping configured successfully"
sudo chmod +x /usr/local/bin/setup-traffic-shaping.sh

Create systemd service

Create a systemd service to automatically apply traffic shaping at startup.

[Unit]
Description=Network Traffic Shaping
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/setup-traffic-shaping.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable traffic-shaping

Configure ingress traffic control

Apply traffic shaping to incoming traffic using the ingress queueing discipline with policing.

# Add ingress qdisc
sudo tc qdisc add dev eth0 ingress

Police incoming traffic to 50Mbit

sudo tc filter add dev eth0 parent ffff: protocol ip prio 1 u32 match u32 0 0 police rate 50mbit burst 10k drop

Police specific source IP to 10Mbit

sudo tc filter add dev eth0 parent ffff: protocol ip prio 2 u32 match ip src 192.168.1.100/32 police rate 10mbit burst 5k drop

Monitor and troubleshoot traffic shaping rules

View current queueing disciplines

Check the currently configured queueing disciplines and their status.

tc qdisc show dev eth0
tc qdisc show

Display traffic classes and statistics

Monitor bandwidth usage and packet statistics for each traffic class.

# Show classes with statistics
tc -s class show dev eth0

Show detailed class information

tc class show dev eth0

View active filters

Check which filters are classifying traffic and their match statistics.

# Show all filters
tc filter show dev eth0

Show filters with statistics

tc -s filter show dev eth0

Monitor real-time traffic

Use watch command to monitor traffic shaping statistics in real-time.

watch -n 1 'tc -s class show dev eth0'
watch -n 2 'tc -s qdisc show dev eth0'

Remove traffic shaping rules

Clean up traffic shaping configuration when needed.

# Remove all egress rules
sudo tc qdisc del dev eth0 root

Remove ingress rules

sudo tc qdisc del dev eth0 ingress

Remove specific class

sudo tc class del dev eth0 classid 1:40

Advanced QoS configuration

Configure burst and ceil parameters

Fine-tune burst sizes and ceiling rates for optimal performance.

# Class with custom burst parameters
sudo tc class add dev eth0 parent 1:1 classid 1:60 htb rate 25mbit ceil 50mbit burst 15k cburst 8k prio 2

Add corresponding leaf qdisc

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

Implement weighted fair queueing

Use different queueing disciplines for specific traffic types.

# Use PFIFO for low-latency traffic
sudo tc qdisc add dev eth0 parent 1:10 handle 10: pfifo limit 10

Use FQ_CODEL for general traffic

sudo tc qdisc add dev eth0 parent 1:20 handle 20: fq_codel

Verify your setup

# Check queueing disciplines
tc qdisc show dev eth0

Verify traffic classes

tc class show dev eth0

Check active filters

tc filter show dev eth0

Monitor statistics

tc -s class show dev eth0

Test bandwidth with iperf3

sudo apt install iperf3 iperf3 -c target_server_ip -t 30

Check if service is enabled

systemctl status traffic-shaping
Note: For comprehensive network monitoring and traffic analysis, consider setting up SNMP and BGP metrics monitoring with Prometheus.

Common issues

SymptomCauseFix
tc: RTNETLINK answers: File existsQdisc already configuredsudo tc qdisc del dev eth0 root then reconfigure
Traffic not being limitedWrong interface nameCheck with ip link show and update interface name
Filter not matching trafficIncorrect port or IP syntaxVerify with tc -s filter show dev eth0 and check packet counts
Rules lost after rebootNo automatic startupEnable systemd service: sudo systemctl enable traffic-shaping
Ingress shaping not workingMissing ingress qdiscAdd ingress qdisc: sudo tc qdisc add dev eth0 ingress
High latency on priority trafficIncorrect burst settingsIncrease burst parameters or use different queueing discipline

Next steps

Running this in production?

Need this managed? Running traffic shaping at scale adds complexity: capacity planning, performance tuning, integration with monitoring systems, and handling edge cases during traffic spikes. Our managed platform covers monitoring, backups and 24/7 response by default.

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle private cloud infrastructure for businesses that depend on uptime. From initial setup to ongoing operations.