Rate limiting with tc
Lidi no longer includes an internal bandwidth limiter. Instead, network traffic shaping is handled by the Linux tc (traffic control) utility, which provides more precise and flexible control over network throughput.
Why use tc for rate limiting?
Using tc provides:
Accurate control of actual network throughput
Support for complex network topologies
Better handling of packet overheads
Integration with kernel networking stack
More granular control per interface and protocol
Prerequisites
To use tc, your user needs the CAP_NET_ADMIN capability. There are several ways to configure this:
Option 1: Add to netdev group (recommended)
sudo usermod -aG netdev $USER
Log out and log back in for changes to take effect.
Option 2: Add capabilities to tc binary
sudo setcap cap_net_admin+ep /sbin/tc
Option 3: Use sudo
Run tc commands with sudo or configure sudoers to allow tc without password.
Basic tc configuration for Lidi
Lidi typically sends UDP traffic on a specific port (default: 5000) to a specific destination IP. Here is a basic tc configuration:
Setup rate limiting
# Create HTB qdisc on loopback interface
sudo tc qdisc add dev lo root handle 1: htb default 99
# Create default class (unlimited traffic)
sudo tc class add dev lo parent 1: classid 1:99 htb rate 1gbit
# Create limited class for Lidi UDP traffic
sudo tc class add dev lo parent 1: classid 1:10 htb rate 100mbit burst 32kbit
# Filter UDP traffic to Lidi port
sudo tc filter add dev lo parent 1: protocol ip prio 1 u32 \
match ip protocol 17 0xff \
match ip dport 5000 0xffff \
flowid 1:10
Replace 100mbit with your desired bandwidth limit and 5000 with your Lidi UDP port.
Teardown
sudo tc qdisc del dev lo root
Advanced configuration
Multiple ports
If you use multiple UDP ports (for multithreading), add multiple filters:
sudo tc filter add dev lo parent 1: protocol ip prio 1 u32 \
match ip protocol 17 0xff \
match ip dport 5000 0xffff \
flowid 1:10
sudo tc filter add dev lo parent 1: protocol ip prio 1 u32 \
match ip protocol 17 0xff \
match ip dport 5001 0xffff \
flowid 1:10
Different rates per port
You can create separate classes for different ports with different rates:
# Class for port 5000 at 100mbit
sudo tc class add dev lo parent 1: classid 1:10 htb rate 100mbit
# Class for port 5001 at 50mbit
sudo tc class add dev lo parent 1: classid 1:20 htb rate 50mbit
# Filters
sudo tc filter add dev lo parent 1: protocol ip prio 1 u32 \
match ip protocol 17 0xff \
match ip dport 5000 0xffff \
flowid 1:10
sudo tc filter add dev lo parent 1: protocol ip prio 1 u32 \
match ip protocol 17 0xff \
match ip dport 5001 0xffff \
flowid 1:20
Monitoring tc rules
View current tc configuration:
sudo tc qdisc show dev lo
sudo tc class show dev lo
sudo tc filter show dev lo
View statistics:
sudo tc -s qdisc show dev lo
Integration with Lidi tests
The test suite includes a TcUdpShaper class in features/steps/tc_shaper.py that automates tc configuration for testing. This class:
Sets up HTB qdisc with filtered UDP rate limiting
Targets specific UDP destination ports
Provides setup() and teardown() methods for test fixtures
Requires CAP_NET_ADMIN capability
Example usage in tests:
from features.steps.tc_shaper import TcUdpShaper
shaper = TcUdpShaper(rate="100mbit", port=5000)
shaper.setup()
# Run tests...
shaper.teardown()
Troubleshooting
Check if tc is available:
which tc
Check if you have CAP_NET_ADMIN:
capsh --print
Common issues:
Operation not permitted: User lacks CAP_NET_ADMIN capabilityFile exists: qdisc already exists, remove it first withtc qdisc delNo effect: Verify you are shaping the correct interface (lo for local, eth0 for network)