How Download Managers Implement Incoming Traffic Rate Limiting on Linux Gateways


2 views

When we talk about rate-limiting incoming traffic, we're dealing with a fundamental networking constraint: you can't directly control how fast a remote server sends data to you. Unlike outgoing traffic shaping where you control the sending rate, incoming traffic control requires indirect methods.

TCP's slow-start algorithm does provide some indirect influence over incoming traffic rates. By deliberately delaying ACK packets or manipulating the advertised window size, a receiver can influence the sender's transmission rate. Here's how this works in practice:


// Example of delaying ACKs in Linux
echo 1 > /proc/sys/net/ipv4/tcp_delack_min
echo 100 > /proc/sys/net/ipv4/tcp_delack_max

Download managers implement speed limits through several techniques:

  • Controlling the TCP receive window size
  • Artificially delaying ACK packets
  • Limiting the number of concurrent connections
  • Implementing application-level throttling

For PPPoE gateway scenarios, we can use tc (traffic control) with ifb (Intermediate Functional Block) to shape incoming traffic:


# Load ifb module
modprobe ifb numifbs=1
ip link set dev ifb0 up

# Redirect ingress traffic to ifb
tc qdisc add dev ppp0 handle ffff: ingress
tc filter add dev ppp0 parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev ifb0

# Apply rate limiting on ifb
tc qdisc add dev ifb0 root handle 1: htb default 10
tc class add dev ifb0 parent 1: classid 1:1 htb rate 1mbit
tc class add dev ifb0 parent 1:1 classid 1:10 htb rate 1mbit

For more granular control, we can modify TCP window settings:


# Reduce default and maximum receive window sizes
echo "4096 16384 32768" > /proc/sys/net/ipv4/tcp_rmem
echo 4096 > /proc/sys/net/ipv4/tcp_window_scaling

Verify your traffic shaping with these commands:


tc -s qdisc show dev ifb0
iftop -i ppp0
nload -u m ppp0

When implementing rate-limiting for incoming traffic, we face a fundamental TCP protocol constraint: receivers cannot directly dictate the sender's transmission rate. However, practical solutions exist through indirect flow control mechanisms that influence the sender's behavior.

Download managers implement incoming rate limiting through several clever techniques:


// Pseudo-code demonstrating download manager throttling
void processIncomingData(Packet p) {
    long currentTime = System.currentTimeMillis();
    long elapsed = currentTime - lastPacketTime;
    
    if (elapsed < minPacketInterval) {
        // Artificially delay TCP ACK
        Thread.sleep(minPacketInterval - elapsed);
    }
    sendACK();
    lastPacketTime = currentTime;
}

For PPPoE-connected Linux gateways, we can leverage several kernel mechanisms:

1. tc (Traffic Control) with HTB


# Rate limit incoming traffic to 1Mbps
tc qdisc add dev ppp0 root handle 1: htb default 10
tc class add dev ppp0 parent 1: classid 1:1 htb rate 1mbit
tc filter add dev ppp0 protocol ip parent 1:0 prio 1 u32 \
    match ip dst 192.168.1.0/24 flowid 1:1

2. Leveraging TCP Window Size

Modifying the TCP window size effectively slows down the sender:


# Set system-wide TCP receive window
sysctl -w net.ipv4.tcp_rmem="4096 87380 4194304"

The TCP slow start algorithm can be exploited for rate limiting by:

  • Artificially limiting the initial window size
  • Delaying ACK packets strategically
  • Dropping packets to trigger congestion control

// Example of delayed ACK implementation
void handleIncomingSegment(Segment seg) {
    if (shouldThrottle()) {
        // Wait before sending ACK
        wait(randomThrottleInterval());
    }
    sendACK(seg);
}

When acting as a PPPoE gateway, additional factors come into play:

  1. MTU size limitations (typically 1492 bytes vs Ethernet's 1500)
  2. PPPoE header overhead affecting throughput calculations
  3. Interface-specific tc rules application

Essential commands to verify your rate limiting:


# Show current tc rules
tc -s qdisc ls dev ppp0

# Real-time bandwidth monitoring
iftop -i ppp0 -f "port 80 or port 443"

# Detailed TCP statistics
ss -t -i -n sport = :80