Customize your Fritzbox to allow traffic-shaping

Summary:

Article:

Updated 07.05.2012.

Sometime in 2010 I've had patched the freetz source to add mainly two schedulers (cbq, htb), the u32 filter and a working tc (traffic control) binary. Those are common for QoS in Linux for throttle or managing your bandwidth on a special source/destination addresses, ports, ip protocols or any firewall marks.

Time has passed and most of my changes where added to the 1.2 branch and others have added different filters. Here you can get my recent patch and compiled firmware images:

My changes are currently only the addition of a proper working tc to the build script and some filters. You need to compile your own tc for a working filtering. If you use the pre-installed version from AVMs, you get a message like:

root@fritz:/var/mod/root# tc filter add dev ath0 parent 1:0 protocol ip u32 matc
h ip dst 192.168.0.21/32 classid 1:10
Unknown filter "u32", hence option "match" is unparsable

even if you've loaded the proper kernel module.

Example Usage On Traffic Shaping:

Okay, that's it. Now some notes to QoS, traffic shaping, and networking with Linux in general:

  • First, add a qdisc with tc:
    #tc qdisc add dev ath0 root handle 1:0 htb
    

    qdisc (queueing discipline) is elementary to understanding traffic control. Whenever the kernel needs to send a packet to an interface, it is enqueued to the qdisc configured for that interface. Immediately afterwards, the kernel tries to get as many packets as possible from the qdisc, for giving them to the network adaptor driver. We use classful htb in this script. The htb qdisc, or hierarchical token bucket, is a classful shaping qdisc. It packs a lot of flexibility and has numerous options available. It calculates reasonable default values for anything you do not specify, which is generally fine. And it's a lot easier to use than cbq.

  • Now, add a parent class and set your bandwidth limits:
    #tc class add dev ath0 parent 1: classid 1:1 htb rate 7mbit ceil 7mbit
    

    Classful qdiscs contain classes which allows us to set rate limits. Class 1:1 is the root class here

  • Specify the child classes for your hosts, or groups of hosts:
    #tc class add dev ath0 parent 1:1 classid 1:10 htb rate 1512kbit ceil 7mbit
    #tc class add dev ath0 parent 1:1 classid 1:11 htb rate 4mbit ceil 7mbit
    #tc class add dev ath0 parent 1:1 classid 1:12 htb rate 2mbit ceil 7mbit 
    

    This is the leaf class 1:10 attached to the root class 1:1. Shaping can be done in the leaf class not in the root class. In this example of leaf classes, we allocate 1512kbit,4mbit and 2mbit of bandwidth to each class respectively.
    rate: guaranteed (minimum bandwidth) which can be exceeded.
    ceil: burstable (maximum bandwidth) which cannot be exceeded

  • Now add a handle with fw marks. We can tell iptables and thus the kernel to mark special packets (like all packets that go or come from a defined host).
    #tc filter add dev ath0 protocol ip parent 1:0 prio 1 handle 2 fw classid 1:10
    #tc filter add dev ath0 protocol ip parent 1:0 prio 1 handle 3 fw classid 1:11
    #tc filter add dev ath0 protocol ip parent 1:0 prio 1 handle 4 fw classid 1:12
    

    We use filters to classify the packets into an output queue and attached it to our classful htb class. What the fw handle means will be meaningful in the rest of the example.

  • Add a queueing. We use sfq here:
    #tc qdisc add dev ath0 parent 1:10 handle 10: sfq quantum 1500b perturb 10
    #tc qdisc add dev ath0 parent 1:11 handle 11: sfq quantum 1500b perturb 10
    #tc qdisc add dev ath0 parent 1:12 handle 12: sfq quantum 1500b perturb 10
    

    SFQ (Stochastic Fairness Queueing) is added to each of the HTB queues and it offers equality for limiting traffic while keeping the overhead low.

    quantum: Amount of bytes a flow is allowed to dequeue during a round of the round robin process. Defaults to the MTU of the interface which is also the advised value and the minimum value. This is what manual says but I have seen that default value is assigned as 814. So maybe it is better to set it to 1500.

    perturb: Interval in seconds for queue algorithm perturbation. Defaults to 0, which means that no perturbation occurs. Do not set too low for each perturbation may cause some packet reordering. Advised value: 10.

  • Now add the fw marks to the proper packets using iptables. We use hosts here, you can also use -sport (source port), -dport to specify a desired port:
    #iptables -t mangle -A POSTROUTING -s 192.168.1.21/32 -j MARK --set-mark 2
    #iptables -t mangle -A POSTROUTING -d 192.168.1.21/32 -j MARK --set-mark 2
    
    #iptables -t mangle -A POSTROUTING -s 192.168.1.31/32 -j MARK --set-mark 3
    #iptables -t mangle -A POSTROUTING -d 192.168.1.31/32 -j MARK --set-mark 3
    
    #iptables -t mangle -A POSTROUTING -s 192.168.1.32/32 -j MARK --set-mark 4
    #iptables -t mangle -A POSTROUTING -d 192.168.1.32/32 -j MARK --set-mark 4
    

In this script we direct hosts having IP addresses 192.168.1.21,31,32 into different classes each of which has different rate. Important thing is that ath0 interface is the inner interface of the Fritzbox. For example if host 192.168.111.2 is downloading a file from a remote host, ath0 becomes an egress interface for the packets coming from the remote host. If we want to limit what these hosts send another qdisc for adsl (outside interface) and root,child classes must be added.

Graphically, it would look like this:

                                   +-----------+
                                   |    Root   |
                                   |   7Mbit   |
	 	                   +-----------+
        	 	                   |
		 	 	           |
              +----------------------------------------------------------+
	      |                            |                             |
       +----------------+           +-----------------+           +---------------+
       | Customer 1     |           | Customer 2      |           | Customer 3    |
       |    1,5Mbit     |           |    4Mbit        |           |    2Mbit      |
       +----------------+           +-----------------+           +---------------+

More On iptables:

Take a look here for more information about queues, the filter options and classes. You get information about using tc and the u32 selector, using the netfilter CLASSIFY target and also about the different qdiscs like htb, cbq (classfull), sfq and prio (classless).

Thanks for giving thoughts on creating this example here.

Example Output From A AVM! Fritzbox 7270v3:

Some output from the example above running on my FB 7270v3:

 $ ssh root@192.168.1.1
root@192.168.1.1's password: 
   __  _   __  __ ___ __
  |__ |_) |__ |__  |   /
  |   |\  |__ |__  |  /_

   The fun has just begun ...


BusyBox v1.18.5 (2012-05-06 21:01:18 MDT) built-in shell (ash)
Enter 'help' for a list of built-in commands.

root@fritz:/var/mod/root# uname -a
Linux fritz.fonwlan.box 2.6.19.2 #2 Thu Nov 18 16:35:17 CET 2010 mips GNU/Linux
root@fritz:/var/mod/root# modprobe sch_htb
root@fritz:/var/mod/root# modprobe sch_cbq
root@fritz:/var/mod/root# modprobe sch_prio
root@fritz:/var/mod/root# modprobe cls_u32
root@fritz:/var/mod/root# modprobe cls_fw
root@fritz:/var/mod/root# modprobe iptable_mangle
root@fritz:/var/mod/root# modprobe xt_MARK
root@fritz:/var/mod/root# modprobe xt_mark
root@fritz:/var/mod/root# tc qdisc add dev adsl root handle 1:0 htb
root@fritz:/var/mod/root# tc class add dev adsl parent 1: classid 1:1 htb rate 7mbit ceil 7mbit
root@fritz:/var/mod/root# tc class add dev adsl parent 1:1 classid 1:10 htb rate 5mbit ceil 7mbit
root@fritz:/var/mod/root# tc class add dev adsl parent 1:1 classid 1:11 htb rate 1mbit ceil 5mbit
root@fritz:/var/mod/root# tc filter add dev ath0 protocol ip parent 1:0 prio 1 handle 2 fw classid 1:10
root@fritz:/var/mod/root# tc filter add dev ath0 protocol ip parent 1:0 prio 1 handle 3 fw classid 1:11
root@fritz:/var/mod/root# tc qdisc add dev ath0 parent 1:10 handle 10: sfq quantum 1500b perturb 10
root@fritz:/var/mod/root# tc qdisc add dev ath0 parent 1:11 handle 11: sfq quantum 1500b perturb 10
root@fritz:/var/mod/root# iptables -t mangle -A POSTROUTING -s 192.168.1.21/32 -j MARK --set-mark 2
root@fritz:/var/mod/root# iptables -t mangle -A POSTROUTING -d 192.168.1.21/32 -j MARK --set-mark 2
root@fritz:/var/mod/root# iptables -t mangle -A POSTROUTING -s 192.168.1.31/32 -j MARK --set-mark 3
root@fritz:/var/mod/root# iptables -t mangle -A POSTROUTING -d 192.168.1.31/32 -j MARK --set-mark 3

root@fritz:/var/mod/root# iptables -L -v -n -t mangle
Chain PREROUTING (policy ACCEPT 972 packets, 163K bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain INPUT (policy ACCEPT 90 packets, 9157 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 882 packets, 154K bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 80 packets, 9218 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 962 packets, 163K bytes)
 pkts bytes target     prot opt in     out     source               destination         
  497 59308 MARK       all  --  *      *       192.168.1.21         0.0.0.0/0           MARK set 0x2 
  420 99530 MARK       all  --  *      *       0.0.0.0/0            192.168.1.21        MARK set 0x2 
    0     0 MARK       all  --  *      *       192.168.1.31         0.0.0.0/0           MARK set 0x3 
    0     0 MARK       all  --  *      *       0.0.0.0/0            192.168.1.31        MARK set 0x3 

root@fritz:/var/mod/root# tc qdisc show
qdisc pfifo_fast 0: dev cpmac0 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
qdisc pfifo_fast 0: dev eth0 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
qdisc pfifo_fast 0: dev wifi0 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
qdisc htb 1: dev ath0 r2q 10 default 0 direct_packets_stat 48
qdisc sfq 10: dev ath0 parent 1:10 limit 128p quantum 1500b perturb 10sec 
qdisc sfq 11: dev ath0 parent 1:11 limit 128p quantum 1500b perturb 10sec 
qdisc pfifo_fast 0: dev dsl bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
qdisc pfifo_fast 0: dev adsl bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1

You can cleary see here, that the adsl device is the outer device and ath0 the internal wifi device.

root@fritz:/var/mod/root# ifconfig -a
adsl      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:2000  Metric:1
          RX packets:233247 errors:0 dropped:0 overruns:0 frame:0
          TX packets:140986 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:32 
          RX bytes:315767964 (301.1 MiB)  TX bytes:31354942 (29.9 MiB)

ath0      Link encap:Ethernet  HWaddr 00:24:FE:A3:A4:DF  
          UP BROADCAST RUNNING ALLMULTI MULTICAST  MTU:2290  Metric:1
          RX packets:141230 errors:0 dropped:0 overruns:0 frame:0
          TX packets:233524 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:28987383 (27.6 MiB)  TX bytes:311652335 (297.2 MiB)

cpmac0    Link encap:Ethernet  HWaddr 00:24:FE:C2:EA:24  
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

dsl       Link encap:Point-to-Point Protocol  
          inet addr:192.168.1.1  P-t-P:192.168.1.1  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP ALLMULTI MULTICAST  MTU:1500  Metric:1
          RX packets:205505 errors:0 dropped:0 overruns:0 frame:0
          TX packets:118918 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100 
          RX bytes:275433723 (262.6 MiB)  TX bytes:22115357 (21.0 MiB)

eth0      Link encap:Ethernet  HWaddr 00:24:FE:C2:EA:24  
          UP BROADCAST ALLMULTI MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:128 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

guest     Link encap:Ethernet  HWaddr 00:24:FE:C2:EA:24  
          inet addr:192.168.179.1  Bcast:192.168.179.255  Mask:255.255.255.0
          UP BROADCAST RUNNING ALLMULTI MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:59 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:3002 (2.9 KiB)

lan       Link encap:Ethernet  HWaddr 00:24:FE:C2:EA:24  
          inet addr:192.168.1.1  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING ALLMULTI MULTICAST  MTU:1500  Metric:1
          RX packets:141220 errors:0 dropped:0 overruns:0 frame:0
          TX packets:206163 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:27009883 (25.7 MiB)  TX bytes:278418218 (265.5 MiB)

lan:0     Link encap:Ethernet  HWaddr 00:24:FE:C2:EA:24  
          inet addr:169.254.1.1  Bcast:169.254.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING ALLMULTI MULTICAST  MTU:1500  Metric:1

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:451 errors:0 dropped:0 overruns:0 frame:0
          TX packets:451 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:50335 (49.1 KiB)  TX bytes:50335 (49.1 KiB)

sit0      Link encap:IPv6-in-IPv4  
          NOARP  MTU:1480  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

wifi0     Link encap:Ethernet  HWaddr 00:24:FE:A3:A4:DF  
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:411881 errors:0 dropped:0 overruns:0 frame:84051
          TX packets:231626 errors:106 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:93869129 (89.5 MiB)  TX bytes:318838401 (304.0 MiB)
          Interrupt:80 Memory:c0400000-c0410000 

root@fritz:/var/mod/root# 

Screenshots

And for the end, some screenshots:
A screenshot of the Frtizbox Configuration Interface:

Frtizbox GUI

A screenshot of the Freetz Configuration Interface:

Freetz GUI

Comments

Sun, 14/08/2011 - 20:39

1st of all, this patch works like a charm on freetz/fritzbox7170.
I use it to shape my upload bandwidth on dsl interface.

Now I tried to do same trick on FB7340 but ran into a problem:
I can't slow down dsl interface anymore!
All modules load fine, classification works, I see traffic ending up in different classes, but no bandwidth limiting and packet drops. (excess low prio traffic should be dropped!)

All stuff in kernel seems to be present, the classic command below to slowdown an interface works ok on both LAN interface and ADSL interface, but not on DSL interface:

tc qdisc add dev dsl root tbf rate 220kbit latency 50ms burst 1540

(I'm not able to use shaping on adsl interface: can't classify packets because of weird ptp encapsulation used)

Hints welcome...

zab
Mon, 15/08/2011 - 08:45

Nice to hear you've had success with your FB7170, since you are the first one to comment =). So maybe more people give it a try now!

I've no clue about your problem on the FB7340 since i still use my 7270, but i'll look into it, maybe i can come up with something, ..

Tue, 23/08/2011 - 05:19

Although both tcpdump and wireshark don't understand packets on adsl interface (bogus ip header length), tc filter commands work fine on adsl interface, and I moved shaping stuff to that interface
One caveat: On adsl interface, packets are NATted to outside public address, so private source address are no longer available to prioritize internal hosts

ikrzysztof (not verified)
Mon, 15/08/2011 - 07:28

I'm trying apply patch and have a some warnings:
krzysztof@ikrzysztof-laptop:~/Pobrane/freetz-1.1.3$ patch -i freetz-1.1.3.patchpatching file Config.in
Hunk #1 succeeded at 992 with fuzz 2 (offset 627 lines).
patching file Config.in
Hunk #1 FAILED at 26.
1 out of 1 hunk FAILED -- saving rejects to file Config.in.rej
The next patch would create the file Config.in,
which already exists! Assume -R? [n] y
patching file Config.in
Hunk #1 FAILED at 1.
File Config.in is not empty after patch, as expected
1 out of 1 hunk FAILED -- saving rejects to file Config.in.rej

What is going on?

zab
Mon, 15/08/2011 - 08:33

hey there!
Such errors usually come up if you chose an improper level for patching.

The '-p' option instructs patch to ignore parts of the path name so that it can identify the files correctly. Thats necessary, because within the patch files the files to be patched are identified by path names which may be different on your computer rather than on my one where the patch was created.

The proper usage for patching all files would be:

 xen@ radon /home/xen/freetz/freetz-1.1.3 509
 $ patch -p1 < freetz-1.1.3.patch 
patching file kernel/Config.in
patching file make/Config.in
patching file make/iproute2/Config.in
patching file make/iproute2/iproute2.mk
patching file make/iproute2/Makefile.in
patching file make/iproute2/patches/001-Makefile.patch
 xen@ radon /home/xen/freetz/freetz-1.1.3 510
 $ 

Just make sure you have the patch file in the root directory of your freetz source.

Spirit (not verified)
Mon, 06/08/2012 - 18:29

Hi,

Nice article and very helpfull!
I'd love to limit bandwidth for one computer.
I am using a fritzbox 7270 v2 and v3.
While I tried to compile the latest trunk with your patch for the 7270v2, it was compiling after a few changes but when I tried to enter even one command, then the Fritzbox is rebooting without any reason.
I used your precompiled freetz image and after a few "tc" commands the same thing happens...I'm really scared to enter commands, cause I never know when it "crashes" and reboots.
Any idea?

zab
Tue, 09/10/2012 - 13:12

See the patch file, i've added a build script and my server as a mirror for a working iproute2 package. I've tried several one, newer ones didn't build for me.

electrofritz (not verified)
Sat, 20/10/2012 - 02:07

Very interesting and useful article!

Having not worked with traffic shaping before I decided for the first run (and before I build my own freetz including my usual suite of freetz packages) to give your pre-build freetz image a try on my 7270v3 (AVM). It all worked nicely until the second tc qdisc call:

<modprobe stuff, all ok>
root@fritz:/var/mod/root# tc qdisc add dev ath0 root handle 1:0 htb
root@fritz:/var/mod/root# tc class add dev ath0 parent 1: classid 1:1 htb rate 14mbit ceil 14mbit
root@fritz:/var/mod/root# tc class add dev ath0 parent 1:1 classid 1:10 htb rate 2mbit ceil 14mbit
root@fritz:/var/mod/root# tc filter add dev ath0 protocol ip parent 1:0 prio 1 handle 2 fw classid 1:10
root@fritz:/var/mod/root# tc qdisc add dev ath0 parent 1:10 handle 10: sfq quantum 1500b perturb 10
RTNETLINK answers: No such file or directory

I am at a loss as to why the 1:10 class which got defined is not ok now...
Any idea or hint?
Thanks!

hippie2000 (not verified)
Sat, 11/05/2013 - 14:54

thanks for the nice article,

this is a frequently requested missing feature in the box

Note that for the Fusiv models 7340/90 there may be some restrictions with iptables due to hardware accelerated routing...

If someone wants to code a universal freetz webinterface (not an easy task) join our irc channel ##fritzbox on freenode.net (yes two ##). Best idle there until someone can help. Some freetz coders hang around there too.

John Costa (not verified)
Wed, 26/11/2014 - 00:43

Hi, I just bought an HD Pro X the other day. I saw you post on Line 6 and thought I would be able convert all my patches and start using my new tool.............When I got to you website and tried to download your utility I was only able to down load the HD500 to HD Pod (Table top). I looked all over and couldn't find anything else......Did I miss something? Please tell me there is an utility that will convert to 500 to Pro(x). If so please feel free to send me an email with the correct link.........jc

Alex (not verified)
Thu, 09/08/2018 - 19:46

Hello I've been using 1.0.4.31 version and was wondering how I can go the the latest one? Is there any instructions?

zab
Thu, 09/08/2018 - 19:54

Export your blog urls using the settings option.
Remove all blogs.
Re-add all blogs.
Already downloaded binary files will not be re-downloaded if they are still at the same place or if you change the download location in the details window to match the location to the new location of your files.