Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
FireQOS is a helper to assist you configure traffic shaping on Linux.
Please read the FireQOS tutorial to learn the basics of traffic control and FireQOS.
To download FireQOS and run:
git clone https://github.com/ktsaou/firehol.git firehol.git cd firehol.git git checkout origin/master
If you already have done this, you can update it any time with this:
cd firehol.git git checkout origin/master git pull origin master
Now you have fireqos.in and firehol.in the in the
Run FireQOS with
FireQOS has the following features:
- FireQOS is a traffic shaping helper. It has a very simple shell scripting language to express traffic shaping. You run FireQOS to setup the kernel commands. You can also run it to get status information or dump the traffic of a class. FireQOS is not a daemon and does not need to run always to apply traffic shaping.
- FireQOS applies traffic shaping on the output of any interface.
- FireQOS applies traffic shaping on the input of any interface. Shaping incoming traffic is classfull, i.e. you have all the control available, similar to outgoing traffic. This is accomplished by setting up IFB devices. FireQOS handles everything about IFB devices. Any kernel that supports them will do.
- FireQOS supports overheads calculation. This means it can perfectly shape incoming and outgoing traffic on a linux box behind an ADSL router, or on a linux box with an ADSL modem attached. ATM overheads will be calculated based on the DSL encapsulation.
- FireQOS supports both IPv4 and IPv6. Each interface can be defined as ipv4, ipv6 or both (ipv4 and ipv6 in parallel).
- FireQOS supports nested classes. Nested classes can either be direct (child classes are directly attached to their parent class), or hardware emulation (child classes are attached to a qdisc with linklayer parameters and overheads calculation, which is attached to a parent class).
- FireQOS calculates port range masks (you just give a port range, FireQOS finds the optimal combination of tc statements to accomplish the match).
- Virtually any number of interfaces, any number of classes and any number of classification rules can be configured (the way it is organized it can configure up to 5000 classes per interface).
- It classifies packets using tc (both ipv4 and ipv6), but you can also use iptables CLASSIFY targets, or MARKs.
- HTB is used for all classes.
- FireQOS allows you to tcpdump the traffic of any leaf class. This allows you to examine the traffic you have assigned to classes.
- FireQOS is standalone. It is distributed with FireHOL, but you don't need FireHOL to use it. Just one file is needed (fireqos.sh) and you are done.
- FireQOS requires a recent Linux kernel (2.6.30+) and iproute2. There is no iptables dependency, although iptables CLASSIFY targets and MARKs may be used.
# incoming traffic from my ADSL router interface eth2 adsl-in input rate 10500kbit adsl remote pppoe-llc class voip commit 100kbit pfifo match udp ports 5060,10000:10100 # asterisk sip and rtp match udp ports 16393:16402 # apple facetime class realtime commit 10% match tcp port 22,1195:1198,1753 # ssh, openvpn, pptp match udp port 53 # dns match proto GRE match icmp match tcp syn match tcp ack class clients commit 10% match tcp port 20,21,25,80,143,443,465,873,993 # mail, web, ftp, etc class default max 90% # unmatched traffic goes here ('default' is a special name) # I define torrents, bellow the default class, because I want them to slow down when # the default class is willing to get bandwidth class torrents max 90% match port 51414 # my torrent client # outgoing traffic to my ADSL router interface eth2 adsl-out output rate 800kbit adsl remote pppoe-llc class voip commit 100kbit pfifo match udp ports 5060,10000:10100 # asterisk sip and rtp match udp ports 16393:16402 # apple facetime class realtime commit 10% match tcp port 22,1195:1198,1753 # ssh, openvpn, pptp match udp port 53 # dns match proto GRE match icmp match tcp syn match tcp ack class clients commit 10% match tcp port 20,21,25,80,143,443,465,873,993 # mail, web, ftp, etc class default max 90% # unmatched traffic goes here ('default' is a special name) # I define torrents, bellow the default class, because I want them to slow down when # the default class is willing to get bandwidth class torrents max 90% match port 51414 # my torrent client
# ./sbin/fireqos.in start FireQOS v1.0 DEVELOPMENT (C) 2013 Costa Tsaousis, GPL : Setting up input on interface 'eth2' (real device 'ifb0'): : processing class 1:11 'voip' : processing class 1:12 'realtime' : processing class 1:13 'clients' : processing class 1:9999 'default' : processing class 1:15 'torrents' : Setting up output on interface 'eth2' (real device 'eth2'): : processing class 2:11 'voip' : processing class 2:12 'realtime' : processing class 2:13 'clients' : processing class 2:9999 'default' : processing class 2:15 'torrents' All Done!. Enjoy... bye...
Status information about it:
# ./sbin/fireqos.in status adsl-in FireQOS v1.0 DEVELOPMENT (C) 2013 Costa Tsaousis, GPL adsl-in: eth2 input => ifb0, type: adsl, overhead: 26 Rate: 10500Kbit/s, min: 105Kbit/s, R2Q: 8 (min rate 105Kbit/s) Values in Kbit/s CLASS voip realtim clients torrent default PRIORIT 1 2 3 5 4 COMMIT 105 1050 1050 105 105 MAX 10500 10500 10500 9450 9450 adsl-in (eth2 input => ifb0) - values in Kbit/s TOTAL voip realtim clients torrent default 46 - 7 - 39 - 50 - 5 - 42 3 80 - 9 - 60 11 75 - 6 - 65 4 103 19 3 - 79 2 56 - 3 - 50 3 84 - 5 - 70 9
FireQOS reads its configuration from
The following command line options are available:
- start, to activate shaping on all interfaces, as given in the configuration file
- stop, to remove all shaping from all interfaces
- debug, like start but it also prints all the tc commands it executes
- status name, where name is the name of an interface, as defined in the configuration file, to show the shaped traffic in realtime
In status mode, FireQOS will show you the rate of traffic on all classes, adding one line per second (similarly to
- tcpdump name class, where name is the name of an interface and class is the name of a class, both as defined in the configuration file
In tcpdump mode, FireQOS temporarily mirrors the traffic of any leaf class, to an IFB device. Then it runs
tcpdump on this interface to dump the traffic to your console. You may add any
tcpdump parameters you like to the command line, like this:
fireqos tcpdump adsl-in voip -n
This command, will start a tcpdump of all traffic in class voip. The parameter
-n is a
tcpdump parameter. You may append any
tcpdump parameters you need (for example to dump the traffic to a file, or match a subset of the traffic).
When FireQOS is running in tcpdump mode, it locks itself and will refuse to run in parallel with another FireQOS altering the QoS, or tcpdumping other traffic. This is because FireQOS reserves device
ifb0 for monitoring. If two FireQOS processes were allowed to tcpdump in parallel, your dumps would be wrong. So it locks itself to prevent such a case.
Save your configuration in /etc/firehol/fireqos.conf
It is shell script file (you can use variables, conditions, loops or whatever Linux shell scripts accept) with the following special commands:
interface device name direction [optional class parameters]
- device is the device to apply shaping to (e.g. eth0, ppp1, etc)
- name is the name you want to give (anything, just a single word). This is only used for getting status information later
direction is either the word
inputis used to shape traffic coming in an interface, while
outputis used to shape traffic going out via the interface
- the rate option in the class parameters is required for interfaces (see bellow for the definition of parameters)
interface eth0 lan-in input rate 1Gbit
this creates an input policy on eth0, capable of delivering up to 1Gbit of traffic.
IMPORTANT: To achieve best results with incoming traffic shaping, you should not use 100% of the available bandwidth at the interface level. If you use all there is, at 100% utilization of the link, the neighbor routers will start queuing packets. This will destroy prioritization. I prefer to limit my bandwidth to 85% or 90% of the total bandwidth. This will force all neighbor routers to have empty queues, so FireQOS will be the only one that controls the traffic. This way you will have total control of your incoming traffic.
In my case for example, my ADSL router has 12Mbit incoming and 880Kbit outgoing. I prefer to use 10500Kbit incomming and 800Kbit outgoing. This gives me perfect VoIP quality even when the link is actually congested.
There are the following alliases:
interface4 for an ipv4-only interface (the default),
interface6 for an ipv6-only interface and
interface46 for an interface that is has both ipv4 and ipv6 traffic.
class name [optional class parameters]
The sequence that classes appear in the configuration, defines their priority. The first class is the most important one, that will (unless otherwise limited) get all available bandwidth, if it needs to. The second one is less important than the first, the third is even less important than the second, etc.
The idea is very simple: just put the classes in the order of importance to you. Classes can also be assigned a priority with the
prio parameter. HTB supports only 8 priorities, from 0 to 7. If you use more than 8 priorities, all after the 8th will get the same priority (
All classes in FireQOS share the interface bandwidth. However, every class has a committed rate (the minimum guaranteed speed it will get if it needs to) and a ceiling (or the maximum rate this class can reach, provided there is capacity available).
Classes can be nested, like this:
interface eth0 lan rate 1Gbit class voip commit 1Mbit match udp ports 5060,10000:10100 class group servers commit 50% # the keyword 'group' defines a parent class match tcp # <<< bring traffic to the child classes class mail commit 50% # <<< 50% of its parent (class 'servers') match port 25 # <<< matches traffic of its parent class parent (class 'servers') class web commit 50% match port 80 class group end # end the group 'servers' class streaming commit 30%
Any number of nested classes can be configured.
By default FireQOS creates nested classes as classes directly attached to their parent class. This way nesting does not add any delays.
There is another mode for nesting classes, where FireQOS emulates new hardware at the group class. This may be needed, when for example you have an ADSL router that you connect to it via Ethernet. You want the LAN traffic to be at Ethernet speed, but WAN traffic at ADSL speed with proper ADSL overheads calculation. To accomplish this, you add a linklayer definition (ethernet, adsl, atm, etc) or just an
mtu to a group class. FireQOS will create a qdisc within the class, where the linklayer parameters will be assigned and the child classes will be attached to this qdisc. This adds some delay to the packets of the child classes, but allows you to emulate new hardware. Example:
interface eth0 lan output rate 1Gbit ethernet class lan match src 192.168.0.0/24 # <<< LAN traffic class group adsl rate 10Mbit ceil 10Mbit adsl remote pppoe-llc # <<< hardware emulation match all # <<< send all other traffic to this group class voip # <<< class in the adsl group match udp port 5060 class web # <<< class in the adsl group match tcp port 80,443 class group end
There is special class, called
default classes can be given explicitly in the configuration file. If it is not found in the config, FireQOS will append it at the end of an
interface or the end of a
By default a class inherits the IP version from its interface. However the IP version of a class can be overwritten using
name is the name you want to give it and is used only for displaying status information about it
the following optional class parameters are inherited from interface the class is in:
qdisc. This means, that if you define a burst at the interface level, then all classes within the interface will get this burst as the default (of course, this can be overwritten if you define the same parameter at the class too). All other optional rule parameters are not inherited from interfaces.
match [optional match parameters]
With match statements you assign traffic to its class. The match statements that appear after a class, by default classify all traffic matched to this class.
You can add as many match statements as you like.
match rules are attached to the parent of the class they appear in. Visually you see them under a class, but in reality they are attached to their class parent so that they classify the parent's traffic they match, to the class. The match statements are executed in the order they appear, although their execution order can be changed by changing their
prio. The default
prio given by FireQOS starts at 10, and increases by 10 for each
match statement encountered. So the first match in an interface is given
prio 10, the second
prio 20, etc. If one
match statement generates multiple tc filter, all filters generated by the same
match statement will have the same
match statements can also appear all together bellow the classes, so that they can be arranged to any order, without assigning
prio to each of them. In this case however, each
match statement can specify to which class it classifies the packets it matches. This is done by adding
class name to each
match statement, like this:
interface eth0 lan rate 1Gbit class voip class web class mail match udp ports 5060,10000:10100 class voip match tcp port 25 class mail match tcp port 80 class web
The above is perfectly valid.
By default a match inherits the IP version from its class. However the IP version of a match can be overwritten using
optional class parameters
The following options can be given to both interfaces and classes.
- rate [speed] or commit [speed] or min [speed]
rate defines the committed speed for this class or interface.
for interfaces this is required to be defined in the configuration file
for classes, this defaults to 1/100th of the interface capacity. When a class gets a committed rate, it means that this bandwidth will be given to this class, when it needs it. If the class does not need this bandwidth, it will be available for any other class to use.
ceil [speed] or max [speed]
ceil defines the maximum speed a class can use. Even there is available bandwidth, a class will not exceed its ceil speed.
for interfaces it defaults to the rate speed of the interface
for classes it defaults to the ceil of the their interfaces
minrate defines the default committed speed for all classes not specifically given a rate in the config file. It forces a recalculation of tc r2q.
By default (when
minrate is not given) FireQOS assigns to it the value 1/100 of the interface rate speed.
- qdisc [name] or pfifo or bfifo or sfq or fq_codel or codel or none
the qdisc defines the method to distribute class bandwidth to its sockets. It is applied within the class itself and is useful in cases a class gets saturated. For information about these, check: http://www.tldp.org/HOWTO/Traffic-Control-HOWTO/classless-qdiscs.html
qdisc can be given at the interface level, to set the default for all its classes. It is useful only for classes though.
To pass options to a qdisc, there are two methods:
options "qdisc options here". So to specify, for example sfq options you have to write
class name sfq options "perturb 10 quantum 2000". The
optionskeyword must appear just after the qdisc name.
- set the variable
FIREQOS_DEFAULT_QDISC_OPTIONS_qdiscnamein the config file. For example, for sfq, set the variable
FIREQOS_DEFAULT_QDISC_OPTIONS_sfq="perturb 10 quantum 2000". Using this variable each sfq will by default get these options. You can still specify different options for each qdisc though.
FireQOS adds by default
fq_codel. If this is not available in your kernel, it used
codel. If that is not available too, it used
- prio X or prio keep or prio last
HTB supports 8 priorities, from 0 to 7. Any number less than 0 will give priority 0. Any number above 7 will give priority 7.
By default, FireQOS gives the first class priority 0, and increases this number by 1 for each class it encounters in the config file. If there are more than 8 classes, all classes after the 8th will get priority 7. In
balanced mode (see bellow), all classes will get
prio 4 by default.
FireQOS restarts priorities for each interface and class group.
The class priority defines how the spare bandwidth is spread among the classes. Classes with higher priorities (lower
prio) will get all spare bandwidth. Classes with the same priority will get a percentage of the spare bandwidth, analogous to their committed rates.
last will make a class use the priority of the class just above / before it. So to make two consecutive classes have the same prio, just add
prio keep to the second one.
- linklayer [name] or ethernet or atm
linklayer can only be given on interfaces. It is used by the kernel to calculate the overheads in the packets.
- adsl [local or remote] [encapsulation]
adsl is a special linklayer that automatically calculates ATM overheads for the link.
- local is used when the ADSL modem is directly attached to your computer (for example a PCI card, or a USB modem), while remote is used you have an ADSL router attached to an ethernet port of your computer. These is a special case, where one is using PPPoE passthrough, so there is an ethernet ADSL modem (not router) and PPP is running on the linux box. For this special case, I don't really know what is proper to use. My guess is that this should be considered local. Experiment a bit and if you find out, let me know to update this page. In practice, this parameter lets the kernel know that the packets it sees, have already an ethernet header to them.
- encapsulation can be (all the labels on the same line, are aliases to each other):
IPoA-VC/Mux or ipoa-vcmux or ipoa-vc or ipoa-mux IPoA-LLC/SNAP or ipoa-llcsnap or ipoa-llc or ipoa-snap Bridged-VC/Mux or bridged-vcmux or bridged-vc or bridged-mux Bridged-LLC/SNAP or bridged-llcsnap or bridged-llc or bridged-snap PPPoA-VC/Mux or pppoa-vcmux or pppoa-vc or pppoa-mux PPPoA-LLC/SNAP or pppoa-llcsnap or pppoa-llc or pppoa-snap PPPoE-VC/Mux or pppoe-vcmux or pppoe-vc or pppoe-mux PPPoE-LLC/SNAP or pppoe-llcsnap or pppoe-llc or pppoe-snap
If your adsl router can give you the mtu, it would be nice to add an mtu parameter too. For detailed info, goto http://ace-host.stuart.id.au/russell/files/tc/tc-atm/
- mtu [bytes]
the MTU of the interface.
FireQOS will query the interface to find its MTU. You can overwrite this behaviour by giving this parameter to a class or interface.
- mpu [bytes]
the MPU of the interface.
FireQOS does not set a default for
mpu. You can set your own using this parameter.
- tsize [size]
FireQOS does not set a default for
tsize. You can set your own using this parameter.
- overhead [bytes]
FireQOS calculates automatically the
overhead for ADSL. For all other technologies, you can specify the overhead in the config file.
- r2q [factor]
FireQOS calculates the proper r2q, so that you can control speeds in steps of 1/100th of the interface speed (if that is possible). However, the HTB manual states that this parameter is ignored when a quantum have been set. By default, FireQOS sets quantum to interface MTU, so this is probably is ignored by kernel.
- burst [bytes]
burst is the number of bytes that will be sent at once, at ceiling speed, when a class is allowed to send traffic. It is like a 'traffic unit'. A class is allowed to send at least
burst bytes before trying to serve any other class.
burst should never be lower that the interface mtu and class groups and interfaces should never have a smaller
burst value than their childs. If you do specify a higher
burst for a child class, its parent may get stuck sometimes (the child will drain the parent).
By default, FireQOS lets the kernel decide for this parameter, which calculates the lowest possible value (the minimum value depends on the rate of the interface and the clock speed of the CPU).
burst is inherited from interfaces to classes and from group classes to their subclasses. FireQOS will not allow you to set a
burst at a subclass, higher to its parent. Setting a
burst of a subclass higher than its parent, will drain the parent class, which may be stuck for up to a minute when this happens. For this check to work, FireQOS uses just its configuration (it does not query the kernel to check how the value specified in the config file for a subclass relates to the actual value of its parent).
- cburst [bytes]
cburst is like
burst, but at hardware speed (not just ceiling speed).
By default, FireQOS lets the kernel decide for this parameter.
cburst is inherited from interfaces to classes and from group classes to their subclasses. FireQOS will not allow you to set a
cburst at a subclass, higher to its parent. Setting a
cburst of a subclass higher than its parent, will drain the parent class, which may be stuck for up to a minute when this happens. For this check to work, FireQOS uses just its configuration (it does not query the kernel to check how the value specified in the config file for a subclass relates to the actual value of its parent).
- quantum [bytes]
quantum is the amount of bytes a class is allowed to send at once, when it is borrowing spare bandwidth from other classes.
By default, FireQOS sets
quantum to interface
quantum is inherited from interfaces to classes and from group classes to their subclasses.
- priority or balanced
These parameters set the priority mode of the child classes.
priority is the default mode, where FireQOS assigns an incremental priority to each class. In this mode, the first class takes
prio 0, the second
prio 1, etc. When a class has a higher
prio than the others (higher = smaller number), this high priority class will get all the spare bandwidth available, when it needs it. Spare bandwidth will be allocate to lower priority classes, only when the higher priority ones do not need it.
balanced mode gives
prio 4 to all child classes. When multiple classes have the same
prio, the spare bandwidth available is spread among them, proportionaly to their committed rate. The value
4 can be overwritten by setting
FIREQOS_BALANCED_PRIO=X at the top of the config file, where X is the
prio you want the balanced mode to assign for all classes.
The priority mode can be set in interfaces and class groups. The effect is the same. The classes that are defined as child classes, will get by default the calculated class
prio based on the priority mode given.
These options affect only the default
prio that will be assigned by FireQOS. The default is used only if you don't give a
prio parameter to a class.
FireQOS speeds can be expressed as:
- bps, bytes per second
- kbps, Kbps, kilobytes per second
- mbps, Mbps, megabytes per second
- gbps, Gbps, gigabytes per second
- bit, bits per second
- kbit, Kbit, kilobit per second
- mbit, Mbit, megabit per second
- gbit, Gbit, gigabit per second
- a percentage, only for classes (not interfaces), that defines that percentage of the interface rate.
If you don't specify a unit, FireQOS assumes kbits per second. This is different than
tc which assumes bytes per second.
optional match parameters
- at [root|name]
By default a
match is attached to its parent class parent. For example, if its parent is a class directly under the interface, then the
match is attached to the interface and is compared against all traffic of the interface. For nested classes, a
match of a leaf, is attached to the parent class and is compared against all traffic of this parent class.
at parameter, a
match can be attached any class. The
name parameter should be a class name. The
root parameter, attaches the
match to the interface.
- class name
Defines the name of the class that will get the packets matched by this
By default it is the name of the class the
match statement appears under.
- syn or syns
Match TCP SYN packets. Note that the
tcp parameter must be specified.
If the same match statement includes more protocols than TCP, then this match will work for the TCP packets (it will be silently ignored for all other protocols).
match tcp syn or
match proto tcp,udp syn (in this example,
syn is ignored when generating the UDP filter).
- ack or acks
Same as syn, but it matches TCP ACK packets.
- proto [name [name] ...] or protocol [name [name] ...] or tcp or udp or icmp, or gre or ipv6
Match the protocol in the IP header.
- tos [id [id] ...] or ** priotity [id [id] ...]**
Match to TOS field of ipv4 or the priority field of ipv6.
id can be:
id can also be a
value/mask in any format tc accepts.
- mark [id [id] ...]
Match an iptables MARK. Matching iptables MARKs does not work on input interfaces. You can use them only on output. The IFB devices that are used for shaping inbound traffic do not have any iptables hooks to allow matching MARKs. If you try it, FireQOS will attempt to do it, but currently you will get an error from the tc command executed.
- ports [id,id,...]
- sports [id,id,...]
- dports [id,id,...]
Match ports of the IP header.
ports will create rules for matching source and destination ports (separate rules for each).
dports matches destination ports,
sports matches source ports.
- ip [net [net] ...] or net [net [net] ...] or host [net [net] ...]
- src [net [net] ...]
- dst [net [net] ...]
Match IPs of the IP header.
host will create rules for matching source and destination IPs (separate rules for each).
src matches source IPs and
dst destination IPs.
If the class these matches appear in are ipv4, then only ipv4 IPs can be used. To overwrite use
match6 ... src/dst IPV6_IP.
Similarly, the class is ipv6, then only ipv6 IPs can be used. To overwrite use
match4 ... src/dst IPV6_IP.
You can mix ipv4 and ipv6 in any way you like. FireQOS supports inheritance, to figure out every time which is the default. Example:
interface46 eth0 lan rate 1Gbit # <<< ipv4 and ipv6 enabled interface class voip # <<< ipv4 and ipv6 class, since the interface is ipv4 and ipv6 match udp port 53 # <<< ipv4 and ipv6 rule, since the class is ipv4 and ipv6 match4 src 220.127.116.11 # <<< ipv4 only rule match6 src 2002:baad:beef::1 # <<< ipv6 only rule class4 realtime # <<< ipv4 only class match src 18.104.22.168 # <<< ipv4 only rule, since the class is ipv4-only class6 servers # <<< ipv6 only class match src 2002:dead:beef::1 # <<< ipv6 only rule, since the class is ipv6-only
To convert an ipv4 interface to ipv6, just replace
interface6. All the rules in that interface, will automatically inherit the new protocol. Of course,if you use IP addresses for matching packets, make sure they are IPv6 IPs too.
- prio [id]
All match statements are attached to the interface. They forward traffic to their class, but they are actually executed for all packets are leaving the interface (note: input matches are actually output matches on an IFB device).
By default, the priority they are executed, is the priority they appear in the configuration file, i.e. the first match of the first class is executed first, then the rest matches of the first class in the sequence they appear, then the matches of the second class, etc.
It is sometimes required, to control the order of matches. For example, when you want host 22.214.171.124 to be assigned the first class, except port tcp/1234 which should be assigned the second class. Lets see it:
interface eth0 lan output rate 1Gbit class high match host 126.96.36.199 class low match host 188.8.131.52 port 1234
In this case, the first match is assigned prio 10 and the second prio 20. The second match will never match anything, since all traffic for host 184.108.40.206 is already matched by the first one.
prio allows you to change the order in which the matches are executed. FireQOS gives priority 10 to first match of every interface, 20 to second match, 30 to third match, etc. So the default is 10 x the sequence number. You can set
prio to overwrite this number.
To force executing the second match before the first, just add a lower prio to it. For example:
interface eth0 lan output rate 1Gbit class high match host 220.127.116.11 class low match host 18.104.22.168 port 1234 prio 1
Now the second match is executed before the first.