User:0xdc/Drafts/Cake

From Gentoo Wiki
Jump to:navigation Jump to:search

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

KERNEL
[*] 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
Note
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
Tip
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.

CODE
#!/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

See Also