User:0xdc/Drafts/Cake
CAKE (Common Applications Kept Enhanced) is a traffic shaping-capable queue discipline. It is intended to be an improvement over the htb + fq_codel queue disciplines with very little configuration.
If a network connection is showing increased latency at maximum download and/or upload speed limit, then capping the bandwidth just below that limit will keep the latency low.
This is not only useful on routers, but on hypervisors and individual computers and laptops too.
Kernel Configuration
[*] Networking support --->
Networking options --->
[*] QoS and/or fair queueing --->
*** Queueing/Scheduling ***
[*] Common Applications Kept Enhanced (CAKE)
*** Classification ***
[*] Elementary classification (BASIC)
[*] Actions
[*] Redirecting and Mirroring
Device Drivers --->
[*] Network device support --->
[*] Network core driver support
[*] Intermediate Functional Block support
Shaping
root #
emerge --ask sys-apps/iproute2
To shape outgoing traffic, attach the cake qdisc to the interface:
root #
tc qdisc add dev $INTERFACE root cake bandwidth $RATE
Linux cannot shape incoming packets, so we must mirror packets to an IFB device and emulate them egressing.
First, we add the special ingress chain to the interface:
root #
tc qdisc add dev $INTERFACE ingress
Next, load the ifb module and set the new interface to "up":
root #
modprobe ifb numifbs=1
root #
ip link set dev ifb0 up
The other modules (sch_cake, cls_basic, act_mirred) will be loaded automatically when used, so there's no need for any specific commands in this document.
Then, create a filter to redirect ("steal") all incoming packets to look like they are egress packets out of the ifb interface:
root #
tc filter add dev $INTERFACE parent ffff: basic action mirred egress redirect dev ifb0
The "basic" filter has an optional "match" option which could filter out packets. Since it is left out, all packets are matched; we do not need the matchall or u32 ematch/classification modules.
Finally, attach the cake qdisc to the ifb interface:
root #
tc qdisc add dev ifb0 root cake bandwidth $RATE
Script
The following script shows an example of an 80Mbit/s down, 20Mbit/s up VDSL line over PPPoE, although with appropriate tweaks it would also work with any network interface that has traffic going in or out.
#!/bin/bash
set -e
parent=ppp0
down=76Mbit
up=19Mbit
# Load the IFB module and create a device
modprobe ifb numifbs=1
# Ensure the device is set to "up"
ip link set dev ifb0 up
# Clear any existing queues and filters
tc qdisc show dev ifb0 | grep -q "0: root" || tc qdisc del dev ifb0 root
tc qdisc show dev ${parent} | grep -q "ingress ffff:" && tc qdisc del dev ${parent} ingress # this clears the filter too
tc qdisc show dev ${parent} | grep -q "0: root" || tc qdisc del dev ${parent} root
test "${1}" = "exit" && exit 0
## Download shaping
# Create the ingress chain
tc qdisc add dev ${parent} ingress
# Redirect ingress to ifb device
tc filter add dev ${parent} parent ffff: basic action mirred egress redirect dev ifb0
# Perform cake shaping to downstream bandwidth
tc qdisc replace dev ifb0 root cake bandwidth $down
## Upload shaping
# Add cake shaping to egress
tc qdisc replace dev ${parent} root cake bandwidth $up ack-filter