Difference between revisions of "Traffic shaping with tc"

From OpenVZ Virtuozzo Containers Wiki
Jump to: navigation, search
m (Limiting packets per second rate from VE: use source tag)
(VE -> container, CT)
Line 1: Line 1:
Sometimes it's necessary to limit traffic bandwidth from and to a [[VE]].
+
Sometimes it's necessary to limit traffic bandwidth from and to a [[container]].
 
You can do it using ordinary <code>tc</code> tool.
 
You can do it using ordinary <code>tc</code> tool.
  
 
== Packet routes ==
 
== Packet routes ==
First of all, a few words about how packets travel from and to a [[VE]].
+
First of all, a few words about how packets travel from and to a [[container]].
Suppose we have [[Hardware Node]] (HN) with a VE on it, and this VE talks
+
Suppose we have [[Hardware Node]] (HN) with a container (CT) on it, and this
to some Remote Host (RH). HN has one "real" network interface <tt>eth0</tt> and,  
+
container talks to some Remote Host (RH). HN has one "real" network interface
 +
<tt>eth0</tt> and,  
 
thanks to OpenVZ, there is also "virtual" network interface <tt>venet0</tt>.
 
thanks to OpenVZ, there is also "virtual" network interface <tt>venet0</tt>.
Inside the VE we have interface <tt>venet0:0</tt>.
+
Inside the container we have interface <tt>venet0:0</tt>.
  
 
<pre>
 
<pre>
 
     venet0:0              venet0    eth0
 
     venet0:0              venet0    eth0
VE >------------->-------------> HN >--------->--------> RH
+
CT >------------->-------------> HN >--------->--------> RH
  
 
     venet0:0              venet0    eth0
 
     venet0:0              venet0    eth0
VE <-------------<-------------< HN <---------<--------< RH
+
CT <-------------<-------------< HN <---------<--------< RH
 
</pre>
 
</pre>
  
 
== Limiting outgoing bandwidth ==
 
== Limiting outgoing bandwidth ==
We can limit VE outgoing bandwidth by setting the <tt>tc</tt> filter on <tt>eth0</tt>.
+
We can limit container outgoing bandwidth by setting the <tt>tc</tt> filter on <tt>eth0</tt>.
 
<pre>
 
<pre>
 
DEV=eth0
 
DEV=eth0
Line 27: Line 28:
 
tc qdisc add dev $DEV parent 1:1 sfq perturb 10
 
tc qdisc add dev $DEV parent 1:1 sfq perturb 10
 
</pre>
 
</pre>
X.X.X.X is an IP address of VE.
+
X.X.X.X is an IP address of container.
  
 
== Limiting incoming bandwidth ==
 
== Limiting incoming bandwidth ==
Line 39: Line 40:
 
tc qdisc add dev $DEV parent 1:1 sfq perturb 10
 
tc qdisc add dev $DEV parent 1:1 sfq perturb 10
 
</pre>
 
</pre>
Note that <code>X.X.X.X</code> is an IP address of VE.
+
Note that <code>X.X.X.X</code> is an IP address of container.
  
== Limiting VE to HN talks ==
+
== Limiting CT to HN talks ==
As you can see, two filters above don't limit [[VE]] to [[HN]] talks.
+
As you can see, two filters above don't limit [[container]] to [[HN]] talks.
I mean a [[VE]] can emit as much traffic as it wishes. To make such a limitation from the [[HN]],
+
I mean a [[container]] can emit as much traffic as it wishes. To make such a limitation from the [[HN]],
 
it is necessary to use <tt>tc</tt> police on <tt>venet0</tt>:
 
it is necessary to use <tt>tc</tt> police on <tt>venet0</tt>:
 
<pre>
 
<pre>
Line 50: Line 51:
 
</pre>
 
</pre>
  
== Limiting packets per second rate from VE ==
+
== Limiting packets per second rate from container ==
To prevent dos atacks from the VE you can limit packets per second rate using iptables.
+
To prevent dos atacks from the container you can limit packets per second rate using iptables.
 
<source lang="bash">
 
<source lang="bash">
 
DEV=eth0
 
DEV=eth0
Line 57: Line 58:
 
iptables -I FORWARD 2 -o $DEV -s X.X.X.X -j DROP
 
iptables -I FORWARD 2 -o $DEV -s X.X.X.X -j DROP
 
</source>
 
</source>
Here <code>X.X.X.X</code> is an IP address of VE
+
Here <code>X.X.X.X</code> is an IP address of container.
  
 
== An alternate approch using HTB ==
 
== An alternate approch using HTB ==
Line 68: Line 69:
 
# Incoming traffic control
 
# Incoming traffic control
 
#
 
#
VE_IP1=$1
+
CT_IP1=$1
VE_IP2=$2
+
CT_IP2=$2
 
DEV=venet0
 
DEV=venet0
 
#
 
#
Line 85: Line 86:
 
tc qdisc add dev $DEV parent 1:30 handle 30: sfq perturb 10
 
tc qdisc add dev $DEV parent 1:30 handle 30: sfq perturb 10
 
#
 
#
if [ ! -z $VE_IP1 ]; then
+
if [ ! -z $CT_IP1 ]; then
     tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip dst "$VE_IP1" flowid 1:20  
+
     tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip dst "$CT_IP1" flowid 1:20  
 
fi
 
fi
if [ ! -z $VE_IP2 ]; then
+
if [ ! -z $CT_IP2 ]; then
     tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip dst "$VE_IP2" flowid 1:30  
+
     tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip dst "$CT_IP2" flowid 1:30  
 
fi
 
fi
 
#
 
#
Line 114: Line 115:
 
tc qdisc add dev $DEV parent 1:30 handle 30: sfq perturb 10
 
tc qdisc add dev $DEV parent 1:30 handle 30: sfq perturb 10
 
#
 
#
if [ ! -z $VE_IP1 ]; then
+
if [ ! -z $CT_IP1 ]; then
     tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip src "$VE_IP1" flowid 1:20
+
     tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip src "$CT_IP1" flowid 1:20
 
fi
 
fi
if [ ! -z $VE_IP2 ]; then
+
if [ ! -z $CT_IP2 ]; then
     tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip src "$VE_IP2" flowid 1:30
+
     tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip src "$CT_IP2" flowid 1:30
 
fi
 
fi
 
#
 
#

Revision as of 12:59, 11 March 2008

Sometimes it's necessary to limit traffic bandwidth from and to a container. You can do it using ordinary tc tool.

Packet routes

First of all, a few words about how packets travel from and to a container. Suppose we have Hardware Node (HN) with a container (CT) on it, and this container talks to some Remote Host (RH). HN has one "real" network interface eth0 and, thanks to OpenVZ, there is also "virtual" network interface venet0. Inside the container we have interface venet0:0.

    venet0:0               venet0    eth0
CT >------------->-------------> HN >--------->--------> RH

    venet0:0               venet0    eth0
CT <-------------<-------------< HN <---------<--------< RH

Limiting outgoing bandwidth

We can limit container outgoing bandwidth by setting the tc filter on eth0.

DEV=eth0
tc qdisc del dev $DEV root
tc qdisc add dev $DEV root handle 1: cbq avpkt 1000 bandwidth 100mbit
tc class add dev $DEV parent 1: classid 1:1 cbq rate 256kbit allot 1500 prio 5 bounded isolated
tc filter add dev $DEV parent 1: protocol ip prio 16 u32 match ip src X.X.X.X flowid 1:1
tc qdisc add dev $DEV parent 1:1 sfq perturb 10

X.X.X.X is an IP address of container.

Limiting incoming bandwidth

This can be done by setting the tc filter on venet0:

DEV=venet0
tc qdisc del dev $DEV root
tc qdisc add dev $DEV root handle 1: cbq avpkt 1000 bandwidth 100mbit
tc class add dev $DEV parent 1: classid 1:1 cbq rate 256kbit allot 1500 prio 5 bounded isolated
tc filter add dev $DEV parent 1: protocol ip prio 16 u32 match ip dst X.X.X.X flowid 1:1
tc qdisc add dev $DEV parent 1:1 sfq perturb 10

Note that X.X.X.X is an IP address of container.

Limiting CT to HN talks

As you can see, two filters above don't limit container to HN talks. I mean a container can emit as much traffic as it wishes. To make such a limitation from the HN, it is necessary to use tc police on venet0:

DEV=venet0
tc filter add dev $DEV parent 1: protocol ip prio 20 u32 match u32 1 0x0000 police rate 2kbit buffer 10k drop flowid :1

Limiting packets per second rate from container

To prevent dos atacks from the container you can limit packets per second rate using iptables.

DEV=eth0
iptables -I FORWARD 1 -o $DEV -s X.X.X.X -m limit --limit 200/sec -j ACCEPT
iptables -I FORWARD 2 -o $DEV -s X.X.X.X -j DROP

Here X.X.X.X is an IP address of container.

An alternate approch using HTB

For details refer to the HTB Home Page

#!/bin/sh
#
# Incoming traffic control
#
CT_IP1=$1
CT_IP2=$2
DEV=venet0
#
tc qdisc del dev $DEV root
#
tc qdisc add dev $DEV root handle 1: htb default 10
#
tc class add dev $DEV parent 1: classid 1:1 htb rate 100mbit burst 15k
tc class add dev $DEV parent 1:1 classid 1:10 htb rate 10mbit ceil 10mbit burst 15k
tc class add dev $DEV parent 1:1 classid 1:20 htb rate 20mbit ceil 20mbit burst 15k
tc class add dev $DEV parent 1:1 classid 1:30 htb rate 30mbit ceil 30mbit burst 15k
#
tc qdisc add dev $DEV parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10
tc qdisc add dev $DEV parent 1:30 handle 30: sfq perturb 10
#
if [ ! -z $CT_IP1 ]; then
    tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip dst "$CT_IP1" flowid 1:20 
fi
if [ ! -z $CT_IP2 ]; then
    tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip dst "$CT_IP2" flowid 1:30 
fi
#
echo;echo "tc configuration for $DEV:"
tc qdisc show dev $DEV
tc class show dev $DEV
tc filter show dev $DEV
#
# Outgoing traffic control
#
DEV=eth0
#
tc qdisc del dev $DEV root
#
tc qdisc add dev $DEV root handle 1: htb default 10
#
tc class add dev $DEV parent 1: classid 1:1 htb rate 100mbit burst 15k
tc class add dev $DEV parent 1:1 classid 1:10 htb rate 10mbit ceil 10mbit burst 15k
tc class add dev $DEV parent 1:1 classid 1:20 htb rate 20mbit ceil 20mbit burst 15k
tc class add dev $DEV parent 1:1 classid 1:30 htb rate 30mbit ceil 30mbit burst 15k
#
tc qdisc add dev $DEV parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10
tc qdisc add dev $DEV parent 1:30 handle 30: sfq perturb 10
#
if [ ! -z $CT_IP1 ]; then
    tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip src "$CT_IP1" flowid 1:20
fi
if [ ! -z $CT_IP2 ]; then
    tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip src "$CT_IP2" flowid 1:30
fi
#
echo;echo "tc configuration for $DEV:"
tc qdisc show dev $DEV
tc class show dev $DEV
tc filter show dev $DEV

External links