Thursday, May 26, 2011

Manual Reference Pages - TC (8)

NAME


tc - show / manipulate traffic control settings

CONTENTS

Synopsis
Description
Qdiscs
Classes
Filters
Classless Qdiscs
Configuring Classless Qdiscs
Classful Qdiscs
Theory Of Operation
Naming
Units
Tc Commands
History
See Also
Author

SYNOPSIS

tc qdisc [ add | change | replace | link ] dev DEV [ parent qdisc-id | root ] [ handle qdisc-id ] qdisc [ qdisc specific parameters ]
tc class [ add | change | replace ] dev DEV parent qdisc-id [ classid class-id ] qdisc [ qdisc specific parameters ]

tc filter [ add | change | replace ] dev DEV [ parent qdisc-id | root ] protocol protocol prio priority filtertype [ filtertype specific parameters ] flowid flow-id
tc [-s | -d ] qdisc show [ dev DEV ]
tc [-s | -d ] class show dev DEV
tc filter show dev DEV

DESCRIPTION

Tc is used to configure Traffic Control in the Linux kernel. Traffic Control consists of the following:
SHAPING
  When traffic is shaped, its rate of transmission is under control. Shaping may be more than lowering the available bandwidth - it is also used to smooth out bursts in traffic for better network behaviour. Shaping occurs on egress.
SCHEDULING
  By scheduling the transmission of packets it is possible to improve interactivity for traffic that needs it while still guaranteeing bandwidth to bulk transfers. Reordering is also called prioritizing, and happens only on egress.
POLICING
  Where shaping deals with transmission of traffic, policing pertains to traffic arriving. Policing thus occurs on ingress.
DROPPING
  Traffic exceeding a set bandwidth may also be dropped forthwith, both on ingress and on egress.
Processing of traffic is controlled by three kinds of objects: qdiscs, classes and filters.

QDISCS

qdisc is short for ’queueing discipline’ and it 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. A simple QDISC is the ’pfifo’ one, which does no processing at all and is a pure First In, First Out queue. It does however store traffic when the network interface can’t handle it momentarily.

CLASSES

Some qdiscs can contain classes, which contain further qdiscs - traffic may then be enqueued in any of the inner qdiscs, which are within the classes. When the kernel tries to dequeue a packet from such a classful qdisc it can come from any of the classes. A qdisc may for example prioritize certain kinds of traffic by trying to dequeue from certain classes before others.

FILTERS

A filter is used by a classful qdisc to determine in which class a packet will be enqueued. Whenever traffic arrives at a class with subclasses, it needs to be classified. Various methods may be employed to do so, one of these are the filters. All filters attached to the class are called, until one of them returns with a verdict. If no verdict was made, other criteria may be available. This differs per qdisc. It is important to notice that filters reside within qdiscs - they are not masters of what happens.

CLASSLESS QDISCS

The classless qdiscs are:
[p|b]fifo
  Simplest usable qdisc, pure First In, First Out behaviour. Limited in packets or in bytes.
pfifo_fast
  Standard qdisc for ’Advanced Router’ enabled kernels. Consists of a three-band queue which honors Type of Service flags, as well as the priority that may be assigned to a packet.
red Random Early Detection simulates physical congestion by randomly dropping packets when nearing configured bandwidth allocation. Well suited to very large bandwidth applications.
sfq Stochastic Fairness Queueing reorders queued traffic so each ’session’ gets to send a packet in turn.
tbf The Token Bucket Filter is suited for slowing traffic down to a precisely configured rate. Scales well to large bandwidths.

CONFIGURING CLASSLESS QDISCS

In the absence of classful qdiscs, classless qdiscs can only be attached at the root of a device. Full syntax: tc qdisc add dev DEV root QDISC QDISC-PARAMETERS
To remove, issue
tc qdisc del dev DEV root
The pfifo_fast qdisc is the automatic default in the absence of a configured qdisc.

CLASSFUL QDISCS

The classful qdiscs are:
CBQ Class Based Queueing implements a rich linksharing hierarchy of classes. It contains shaping elements as well as prioritizing capabilities. Shaping is performed using link idle time calculations based on average packet size and underlying link bandwidth. The latter may be ill-defined for some interfaces.
HTB The Hierarchy Token Bucket implements a rich linksharing hierarchy of classes with an emphasis on conforming to existing practices. HTB facilitates guaranteeing bandwidth to classes, while also allowing specification of upper limits to inter-class sharing. It contains shaping elements, based on TBF and can prioritize classes. 
PRIO The PRIO qdisc is a non-shaping container for a configurable number of classes which are dequeued in order. This allows for easy prioritization of traffic, where lower classes are only able to send if higher ones have no packets available. To facilitate configuration, Type Of Service bits are honored by default.

THEORY OF OPERATION

Classes form a tree, where each class has a single parent. A class may have multiple children. Some qdiscs allow for runtime addition of classes (CBQ, HTB) while others (PRIO) are created with a static number of children. Qdiscs which allow dynamic addition of classes can have zero or more subclasses to which traffic may be enqueued.
Furthermore, each class contains a leaf qdisc which by default has pfifo behaviour though another qdisc can be attached in place. This qdisc may again contain classes, but each class can have only one leaf qdisc.
When a packet enters a classful qdisc it can be classified to one of the classes within. Three criteria are available, although not all qdiscs will use all three:
tc filters
  If tc filters are attached to a class, they are consulted first for relevant instructions. Filters can match on all fields of a packet header, as well as on the firewall mark applied by ipchains or iptables. See tc-filters(8).
Type of Service
  Some qdiscs have built in rules for classifying packets based on the TOS field.
skb->priority
  Userspace programs can encode a class-id in the ’skb->priority’ field using the SO_PRIORITY option.
Each node within the tree can have its own filters but higher level filters may also point directly to lower classes. If classification did not succeed, packets are enqueued to the leaf qdisc attached to that class. Check qdisc specific manpages for details, however.

NAMING

All qdiscs, classes and filters have IDs, which can either be specified or be automatically assigned. IDs consist of a major number and a minor number, separated by a colon.

QDISCS A qdisc, which potentially can have children, gets assigned a major number, called a ’handle’, leaving the minor number namespace available for classes. The handle is expressed as ’10:’. It is customary to explicitly assign a handle to qdiscs expected to have children.
CLASSES
  Classes residing under a qdisc share their qdisc major number, but each have a separate minor number called a ’classid’ that has no relation to their parent classes, only to their parent qdisc. The same naming custom as for qdiscs applies.
FILTERS
  Filters have a three part ID, which is only needed when using a hashed filter hierarchy, for which see tc-filters(8).

UNITS

All parameters accept a floating point number, possibly followed by a unit. Bandwidths or rates can be specified in:
kbps Kilobytes per second
mbps Megabytes per second
kbit Kilobits per second
mbit Megabits per second
bps or a bare number
  Bytes per second
Amounts of data can be specified in:
kb or k Kilobytes
mb or m Megabytes
mbit Megabits
kbit Kilobits
b or a bare number
  Bytes.
Lengths of time can be specified in:
s, sec or secs
  Whole seconds
ms, msec or msecs
  Milliseconds
us, usec, usecs or a bare number
  Microseconds.

TC COMMANDS

The following commands are available for qdiscs, classes and filter:
add Add a qdisc, class or filter to a node. For all entities, a parent must be passed, either by passing its ID or by attaching directly to the root of a device. When creating a qdisc or a filter, it can be named with the handle parameter. A class is named with the classid parameter.
remove A qdisc can be removed by specifying its handle, which may also be ’root’. All subclasses and their leaf qdiscs are automatically deleted, as well as any filters attached to them.
change Some entities can be modified ’in place’. Shares the syntax of ’add’, with the exception that the handle cannot be changed and neither can the parent. In other words, change cannot move a node.
replace
  Performs a nearly atomic remove/add on an existing node id. If the node does not exist yet it is created.
link Only available for qdiscs and performs a replace where the node must exist already.

HISTORY

tc was written by Alexey N. Kuznetsov and added in Linux 2.2.

SEE ALSO

tc-cbq(8), tc-htb(8), tc-sfq(8), tc-red(8), tc-tbf(8), tc-pfifo(8), tc-bfifo(8), tc-pfifo_fast(8), tc-filters(8)

AUTHOR

http://www.squarebox.co.uk/cgi-squarebox/manServer/tc.8

manipulate traffic control settings

TC(8)                         Linux                         TC(8)



NAME
       tc - show / manipulate traffic control settings

SYNOPSIS
       tc  qdisc [ add | change | replace | link ] dev DEV [ par-
       ent qdisc-id | root ] [ handle qdisc-id ]  qdisc  [  qdisc
       specific parameters ]


       tc  class [ add | change | replace ] dev DEV parent qdisc-
       id [ classid class-id ] qdisc [ qdisc specific  parameters
       ]


       tc  filter  [  add  |  change | replace ] dev DEV [ parent
       qdisc-id | root ] protocol protocol prio priority  filter-
       type [ filtertype specific parameters ] flowid flow-id

       tc [-s | -d ] qdisc show [ dev DEV ]

       tc [-s | -d ] class show dev DEV

       tc filter show dev DEV


DESCRIPTION
       Tc  is used to configure Traffic Control in the Linux ker-
       nel. Traffic Control consists of the following:


       SHAPING
              When traffic is shaped, its rate of transmission is
              under  control.  Shaping  may be more than lowering
              the available bandwidth - it is also used to smooth
              out bursts in traffic for better network behaviour.
              Shaping occurs on egress.


       SCHEDULING
              By scheduling the transmission  of  packets  it  is
              possible  to improve interactivity for traffic that
              needs it while still guaranteeing bandwidth to bulk
              transfers.  Reordering is also called prioritizing,
              and happens only on egress.


       POLICING
              Where shaping deals with transmission  of  traffic,
              policing  pertains  to  traffic  arriving. Policing
              thus occurs on ingress.


       DROPPING
              Traffic exceeding  a  set  bandwidth  may  also  be
              dropped forthwith, both on ingress and on egress.


       Processing  of  traffic  is  controlled  by three kinds of
       objects: qdiscs, classes and filters.


QDISCS
       qdisc is short for 'queueing discipline' and it is elemen-
       tary 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.

       A simple QDISC is the 'pfifo' one, which does no  process-
       ing  at  all  and  is a pure First In, First Out queue. It
       does however store  traffic  when  the  network  interface
       can't handle it momentarily.


CLASSES
       Some  qdiscs  can  contain  classes, which contain further
       qdiscs - traffic may then be enqueued in any of the  inner
       qdiscs,  which  are  within  the classes.  When the kernel
       tries to dequeue a packet from such a  classful  qdisc  it
       can  come from any of the classes. A qdisc may for example
       prioritize certain kinds of traffic by trying  to  dequeue
       from certain classes before others.


FILTERS
       A filter is used by a classful qdisc to determine in which
       class a packet will be enqueued. Whenever traffic  arrives
       at  a  class  with  subclasses, it needs to be classified.
       Various methods may be employed to do so, one of these are
       the filters. All filters attached to the class are called,
       until one of them returns with a verdict.  If  no  verdict
       was  made,  other  criteria may be available. This differs
       per qdisc.

       It is important  to  notice  that  filters  reside  within
       qdiscs - they are not masters of what happens.


CLASSLESS QDISCS
       The classless qdiscs are:

       [p|b]fifo
              Simplest  usable  qdisc,  pure  First In, First Out
              behaviour. Limited in packets or in bytes.

       pfifo_fast
              Standard qdisc for 'Advanced Router'  enabled  ker-
              nels.  Consists  of a three-band queue which honors
              Type of Service flags, as well as the priority that
              may be assigned to a packet.

       red    Random  Early  Detection simulates physical conges-
              tion by randomly dropping packets when nearing con-
              figured  bandwidth  allocation. Well suited to very
              large bandwidth applications.

       sfq    Stochastic Fairness Queueing reorders queued  traf-
              fic  so  each  'session'  gets  to send a packet in
              turn.

       tbf    The Token Bucket Filter is suited for slowing traf-
              fic  down  to  a  precisely configured rate. Scales
              well to large bandwidths.

CONFIGURING CLASSLESS QDISCS
       In the absence of classful qdiscs,  classless  qdiscs  can
       only be attached at the root of a device. Full syntax:

       tc qdisc add dev DEV root QDISC QDISC-PARAMETERS

       To remove, issue

       tc qdisc del dev DEV root

       The  pfifo_fast  qdisc  is  the  automatic  default in the
       absence of a configured qdisc.


CLASSFUL QDISCS
       The classful qdiscs are:

       CBQ    Class Based Queueing implements a rich  linksharing
              hierarchy of classes.  It contains shaping elements
              as well as prioritizing  capabilities.  Shaping  is
              performed  using  link idle time calculations based
              on average packet size and  underlying  link  band-
              width.  The  latter  may  be  ill-defined  for some
              interfaces.

       HTB    The  Hierarchy  Token  Bucket  implements  a   rich
              linksharing  hierarchy  of classes with an emphasis
              on conforming to existing  practices.  HTB  facili-
              tates guaranteeing bandwidth to classes, while also
              allowing specification of upper  limits  to  inter-
              class  sharing. It contains shaping elements, based
              on TBF and can prioritize classes.

       PRIO   The PRIO qdisc is a  non-shaping  container  for  a
              configurable  number  of classes which are dequeued
              in order. This allows for  easy  prioritization  of
              traffic,  where lower classes are only able to send
              if higher ones have no packets available. To facil-
              itate  configuration, Type Of Service bits are hon-
              ored by default.

THEORY OF OPERATION
       Classes form a tree, where each class has a single parent.
       A  class may have multiple children. Some qdiscs allow for
       runtime addition of classes (CBQ, HTB) while others (PRIO)
       are created with a static number of children.

       Qdiscs  which  allow  dynamic addition of classes can have
       zero or more subclasses to which traffic may be  enqueued.

       Furthermore,  each  class  contains  a leaf qdisc which by
       default has pfifo behaviour though another  qdisc  can  be
       attached  in  place. This qdisc may again contain classes,
       but each class can have only one leaf qdisc.

       When a packet enters a classful qdisc it can be classified
       to  one  of  the classes within. Three criteria are avail-
       able, although not all qdiscs will use all three:

       tc filters
              If tc filters are attached to  a  class,  they  are
              consulted  first for relevant instructions. Filters
              can match on all fields of a packet header, as well
              as on the firewall mark applied by ipchains or ipt-
              ables. See tc-filters(8).

       Type of Service
              Some qdiscs have built  in  rules  for  classifying
              packets based on the TOS field.

       skb->priority
              Userspace  programs  can  encode  a class-id in the
              'skb->priority' field using the SO_PRIORITY option.

       Each  node  within  the  tree can have its own filters but
       higher level filters may  also  point  directly  to  lower
       classes.

       If classification did not succeed, packets are enqueued to
       the leaf qdisc attached to that class.  Check  qdisc  spe-
       cific manpages for details, however.


NAMING
       All qdiscs, classes and filters have IDs, which can either
       be specified or be automatically assigned.

       IDs consist of a major number and a  minor  number,  sepa-
       rated by a colon.


       QDISCS A  qdisc, which potentially can have children, gets
              assigned a major number, called a 'handle', leaving
              the  minor  number namespace available for classes.
              The handle is expressed as '10:'.  It is  customary
              to explicitly assign a handle to qdiscs expected to
              have children.


       CLASSES
              Classes residing under a qdisc  share  their  qdisc
              major number, but each have a separate minor number
              called a 'classid' that has no  relation  to  their
              parent  classes,  only  to  their parent qdisc. The
              same naming custom as for qdiscs applies.


       FILTERS
              Filters have a three part ID, which is only  needed
              when using a hashed filter hierarchy, for which see
              tc-filters(8).

UNITS
       All parameters accept a floating  point  number,  possibly
       followed by a unit.

       Bandwidths or rates can be specified in:

       kbps   Kilobytes per second

       mbps   Megabytes per second

       kbit   Kilobits per second

       mbit   Megabits per second

       bps or a bare number
              Bytes per second

       Amounts of data can be specified in:

       kb or k
              Kilobytes

       mb or m
              Megabytes

       mbit   Megabits

       kbit   Kilobits

       b or a bare number
              Bytes.

       Lengths of time can be specified in:

       s, sec or secs
              Whole seconds

       ms, msec or msecs
              Milliseconds

       us, usec, usecs or a bare number
              Microseconds.


TC COMMANDS
       The  following  commands are available for qdiscs, classes
       and filter:

       add    Add a qdisc, class or filter to  a  node.  For  all
              entities,  a parent must be passed, either by pass-
              ing its ID or by attaching directly to the root  of
              a  device.   When  creating a qdisc or a filter, it
              can be named with the handle parameter. A class  is
              named with the classid parameter.


       remove A  qdisc  can  be removed by specifying its handle,
              which may also be 'root'. All subclasses and  their
              leaf  qdiscs  are automatically deleted, as well as
              any filters attached to them.


       change Some entities can be modified  'in  place'.  Shares
              the  syntax  of  'add', with the exception that the
              handle cannot be changed and neither can  the  par-
              ent. In other words, change cannot move a node.


       replace
              Performs  a nearly atomic remove/add on an existing
              node id. If the node does not exist yet it is  cre-
              ated.


       link   Only  available  for  qdiscs and performs a replace
              where the node must exist already.



HISTORY
       tc was written by Alexey N. Kuznetsov and added  in  Linux
       2.2.

SEE ALSO
       tc-cbq(8), tc-htb(8), tc-sfq(8), tc-red(8), tc-tbf(8), tc-
       pfifo(8), tc-bfifo(8), tc-pfifo_fast(8), tc-filters(8)


AUTHOR
       Manpage maintained by bert hubert (ahu@ds9a.nl)

iproute2                 16 December 2001                   TC(8)
http://yesican.chsoft.biz/lartc/tc.html

A Practical Guide to Linux Traffic Control

4. Class Structure Revealed

Paramount to creating a useful traffic control configuration is understanding how to manipulate the class hierarchy you can attach to each root hook. You configure all aspects of the actual shaping using the tc binary. (Traffic classification can be done with the tc binary as well, but we will instead look at a more powerful method later.)

4.1. A Classless qdisc

Let us take an example, using the tc binary.

tc qdisc add dev eth2 parent root handle 1:0 pfifo
Now, that is a lot to take in at once. I have added some verbosity you seldom see to further attempt to clarify what is happening here.
First, we specify that we want to work with a qdisc. Next, we indicate we wish to add a new qdisc to the Ethernet device eth2. (You can specify del in place of add to remove the qdisc in question.) Then, we specify the special parent root. We discussed the importance of the root hook earlier. It is the hook on the egress side of your Ethernet interface. The handle is the magic userspace way of naming a particular qdisc, but more on that later. Finally, we specify the qdisc we wish to add. Because pfifo is a classless qdisc, there is nothing more to do.
A graphical representation of the structure we just created is depicted below. The color blue is used to represent a qdisc. Later, you will see green used to represent a class.

It is important to discuss the naming convention for qdiscs before proceeding. qdiscs are always referred to using a combination of a major node number and a minor node number. For any given qdisc, the major node number has to be unique for the root hook for a given Ethernet interface. The minor number for any given qdisc will always be zero. By convention, the first qdisc created is named 1:0. You could, however, choose 7:0 instead. These numbers are actually in hexadecimal, so any values in within the range of 1 to ffff are also valid. For readability the digits 0 to 9 are generally used exclusively.

4.2. A Classful qdisc

Now, let us look at an example where we add a classful qdisc and a single class.

tc qdisc add dev eth2 parent root handle 1:0 htb default 1
Initially, it looks almost identical to the previous classless qdisc. The htb qdisc was used here. However, to actually benefit from using this classful qdisc, we need to add some classes. You will notice above the parameter default is specified. It is an option for htb qdiscs described later.

tc class add dev eth2 parent 1:0 classid 1:1 htb rate 1mbit
Now, we use the tc binary with the class argument, instead of the qdisc argument. The class argument allows you to create a class hierarchy. We are working with Ethernet device eth2 again. The parent parameter enables you to attach this class to either an existing classful qdisc or another class of the same type. Above we attach to the htb qdisc we just attached to the root hook earlier.
The value for the parent parameter must be the major and minor node number of the qdisc or class you wish to attach to. Earlier, the identifier 1:0 was chosen for handle of the htb qdisc. That must be used as the argument to the parent parameter so tc knows where you are assigning this class.
The classid parameter serves the same purpose for classes that the handle parameter serves for qdiscs. It is the identifier for this specific class. The major node number has already been chosen for you. It must be the same as the major node number specified for the parent argument earlier. You are free to choose any minor node number you want for the classid parameter. Traditionally numbering starts at 1, but numbers from 1 to ffff are valid. For this class the classid 1:1 was chosen, because the qdisc it is being attached to has a major node number 1 for its handle parameter.
Finally we specify the type of class and any options that class requires. In this instance, the htb class was chosen, as the htb qdisc can only have htb classes assigned to it. (This is generally true of classful qdiscs.) The rate option for htb is discussed later.
Another graphical representation, this time of an htb qdisc and an associated class in a simple hierarchy, is shown below. The qdisc is blue and the class green.

4.3. A Combined Example

Finally, we can reveal a complete example using both classful and classless qdiscs.

tc qdisc add dev eth2 parent root handle 1:0 htb default 20
tc class add dev eth2 parent 1:0 classid 1:1 htb rate 1000kbit
tc class add dev eth2 parent 1:1 classid 1:10 htb rate 500kbit
tc class add dev eth2 parent 1:1 classid 1:20 htb rate 500kbit
tc qdisc add dev eth2 parent 1:20 handle 2:0 sfq
Now we have a nested structure, with a htb classful qdisc assigned to the root hook, three htb classes, and asfq qdisc as a leaf qdisc for one htb class. The other has an implicit pfifo attached. The careful reader will notice each qdisc has a minor node number of zero, as is required.
A graphical representation of the class hierarchy just created should be beneficial.

First, notice the at the top of the hierarchy is a htb qdisc. Three classes are assigned to it. Only the first is immediately attached to it, using the parent 1:0. The other two classes are children of the first class. If you examine the tc command with the class option, you will see that the parent refers to the parent class in the hierarchy via its classid.
Each of the three htb classes attached to the htb qdisc are assigned a major node number of 1 for the classid, as the qdisc they are attached to has a handle with 1 as the major node number. The minor node number for each classid must merely be a unique number between 1 and ffff in hexadecimal.
Finally, a sfq qdisc is attached to the leaf class with classid 1:20. Notice the qdisc is added nearly the same as the htb. However, instead of being assigned to the magic root hook, the target is 1:20. The handle is chosen based on the rules discussed earlier. Briefly, the major node number must be a unique number between 1 and ffff and the minor node must be 0.
Last, the whole structure can be deleted simply by deleting the root hook as demonstrated below.

tc qdisc del dev eth2 root

4.4. Displaying qdisc and class Details

Now we can take a look at the details of the hierarchy we have created. Using the tc tool again the following output is produced.

# tc -s -d qdisc show dev eth2
qdisc sfq 2: quantum 1514b limit 128p flows 128/1024
 Sent 0 bytes 0 pkts (dropped 0, overlimits 0)

qdisc htb 1: r2q 10 default 0 direct_packets_stat 0 ver 3.16
 Sent 0 bytes 0 pkts (dropped 0, overlimits 0)
Each qdisc in your hierarchy is shown along with statistics and the details of its parameters. The information available for each qdisc varies. The number of sent bytes and packets is self explanatory. For classful qdiscs, the totals are class wide and include the dequeue totals from children and siblings.

# tc -s -d class show dev eth2
class htb 1:10 root leaf 2: prio 0 quantum 13107 rate 1Mbit ceil 1Mbit
  burst 2909b/8 mpu 0b cburst 2909b/8 mpu 0b level 0
 Sent 0 bytes 0 pkts (dropped 0, overlimits 0)
 lended: 0 borrowed: 0 giants: 0
 tokens: 28791 ctokens: 2879
The detailed output for classes is similar to that of qdiscs. The information available varies depending on the type of class. The above is typical of a htb qdisc's class.
Next, we will discuss some of the more interesting qdiscs available, including pfifo, sfq, tbf, prio, htb.

PrevHomeNext
Linux Traffic Control

hfsc script

tc qdisc add dev $DEV root handle 1: hfsc default 10
tc class add dev $DEV parent 1: classid 1:1 hfsc sc rate 3072kbit ul rate 3072kbit
tc class add dev $DEV parent 1:1 classid 1:10 hfsc sc umax 1500b dmax 53ms rate 614kbit ul rate 3072kbit
tc class add dev $DEV parent 1:1 classid 1:11 hfsc sc umax 1500b dmax 30ms rate 2457kbit ul rate 3072kbit

iptables -t mangle --new-chain voip
iptables -t mangle --insert voip -o $DEV -j voip

tc filter add dev $DEV parent 1: prio 1 protocol ip handle 1 fw flowid 1:11

iptables -t mangle -A voip -p udp --sport 4569 -j MARK --set-mark 1
iptables -t mangle -A voip -p udp --dport 4569 -j MARK --set-mark 1

iptables -t mangle -A voip -p udp --sport 5060 -j MARK --set-mark 1
iptables -t mangle -A voip -p udp --dport 5060 -j MARK --set-mark 1


iptables -t mangle -A voip -p udp --sport 10000:20000 -j MARK --set-mark 1
iptables -t mangle -A voip -p udp --dport 10000:20000 -j MARK --set-mark 1




tc -s qdisc show eth0
qdisc hfsc 1: root refcnt 2 default 10
Sent 83509933 bytes 1029276 pkt (dropped 3, overlimits 6238 requeues 0)
rate 0bit 0pps backlog 0b 0p requeues 0

tc -s class show dev
class hfsc 1: root
Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
rate 0bit 0pps backlog 0b 0p requeues 0
period 0 level 2

class hfsc 1:11 parent 1:1 sc m1 0bit d 25.1ms m2 2457Kbit ul m1 0bit d 0us m2 3072Kbit
Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
rate 0bit 0pps backlog 0b 0p requeues 0
period 0 level 0

class hfsc 1:1 parent 1: sc m1 0bit d 0us m2 3072Kbit ul m1 0bit d 0us m2 3072Kbit
Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
rate 0bit 0pps backlog 0b 0p requeues 0
period 1029159 work 83510091 bytes level 1

class hfsc 1:10 parent 1:1 sc m1 0bit d 33.5ms m2 614000bit ul m1 0bit d 0us m2 3072Kbit
Sent 83510091 bytes 1029278 pkt (dropped 0, overlimits 0 requeues 0)
rate 0bit 0pps backlog 0b 0p requeues 0
period 1029159 work 83510091 bytes rtwork 82189624 bytes level 0


tc -s filter show dev
filter parent 1: protocol ip pref 1 fw
filter parent 1: protocol ip pref 1 fw handle 0x1 classid 1:11

iptables -t mangle -L voip -v -x
Chain voip (1 references)
pkts bytes target prot opt in out source destination
0 0 MARK udp -- any any anywhere anywhere udp spt:sip MARK xset 0x1/0xffffffff
0 0 MARK udp -- any any anywhere anywhere udp dpt:sip MARK xset 0x1/0xffffffff
0 0 MARK udp -- any any anywhere anywhere udp spt:iax MARK xset 0x1/0xffffffff
0 0 MARK udp -- any any anywhere anywhere udp dpt:iax MARK xset 0x1/0xffffffff
0 0 MARK udp -- any any anywhere anywhere udp spts:10000:20000 MARK xset 0x1/0xffffffff
0 0 MARK udp -- any any anywhere anywhere udp dpts:10000:20000 MARK xset 0x1/0xffffffff
0 0 MARK udp -- any any anywhere anywhere udp spt:sip-tls MARK xset 0x1/0xffffffff
0 0 MARK udp -- any any anywhere anywhere udp dpt:sip-tls MARK xset 0x1/0xffffffff
0 0 MARK udp -- any any x.x.x.18 anywhere MARK xset 0x1/0xffffffff
0 0 MARK udp -- any any anywhere x.x.x.18 MARK xset 0x1/0xffffffff
0 0 MARK udp -- any any x.x.x.24 anywhere MARK xset 0x1/0xffffffff
0 0 MARK udp -- any any anywhere x.x.x.24 MARK xset 0x1/0xffffffff

Bandwidth Shaping with Linux

On the router, the device, br0 is the bridged device that is in the internet side of things. We will use that device for shaping our internet traffic in and out of the router. I am using my home internet connection, which is Cox cable internet with 12Mbps download and 2Mbps upload or 12288 kilobits per second and 2048 kilobits per second, respectively.
First, lets setup some bash variables to point to the various commands we will use throughout the script. We will also set variables to indicate our maximum bandwidth in both directions.

TC="/usr/sbin/tc"
IPT="/usr/sbin/iptables"
IP="/usr/sbin/ip"
INSMOD="/sbin/insmod"
RMMOD="/sbin/rmmod"
DNLD_BANDWIDTH="12288kbit"
UPLD_BANDWIDTH="2048kbit"
Next, lets setup the download shaping by adding a queuing discipline (qdisc) to device br0 and tell the qdisc the maximum throughput.
TCA="${TC} class add dev br0"
TFA="${TC} filter add dev br0"
TQA="${TC} qdisc add dev br0"
${TQA} root handle 1: htb
${TCA} parent 1: classid 1:1 htb rate ${DNLD_BANDWIDTH}
Next, we are going to setup 2 classes. Each class will be setup with a guaranteed bandwidth and a maximum bandwidth if the other class is underutilized. The first class will have a guaranteed download bandwidth of 8Mbps. The second class will have a guaranteed download bandwidth of 4Mbps. Both classes will be able to utilize up to 12Mbps depending on how active the other class is.
{TCA} parent 1:1 classid 1:10 htb rate 8192kbit ceil ${DNLD_BANDWIDTH} prio 1
{TCA} parent 1:1 classid 1:11 htb rate 4096kbit ceil ${DNLD_BANDWIDTH} prio 2
{TQA} parent 1:10 handle 10: sfq perturb 10
{TQA} parent 1:11 handle 11: sfq perturb 10
Now we need to setup a filter for each class. This is ensure only packets marked with the filter’s tag will be restricted. The mark is denoted by the ip handle. Here we will use 10 and 11, to match the classids of the classes we just defined.
${TFA} parent 1:0 prio 2 protocol ip handle 10 fw flowid 1:10
${TFA} parent 1:0 prio 2 protocol ip handle 11 fw flowid 1:11
Now to setup the upload shaping, we have to create a imq device.
${INSMOD} imq
${INSMOD} ipt_IMQ
${IP} link set imq0 up
Next, we need to setup a qdisc, classes, and filters for our 2 classes. Just like we did for download, only this time using the imq0 device and the upload bandwidths. The first class will have a guaranteed upload bandwidth of ~1.3Mbps and the second class will have a guaranteed upload bandwidth of 700Kbps.
TCAU="${TC} class add dev imq0"
TFAU="${TC} filter add dev imq0"
TQAU="${TC} qdisc add dev imq0"
${TQAU} root handle 1: htb
${TCAU} parent 1: classid 1:1 htb rate ${UPLD_BANDWIDTH}
${TCAU} parent 1:1 classid 1:10 htb rate 1348kbit ceil ${UPLD_BANDWIDTH} prio 1
${TCAU} parent 1:1 classid 1:11 htb rate 700kbit ceil ${UPLD_BANDWIDTH} prio 2
${TQAU} parent 1:10 handle 10: sfq perturb 10
${TQAU} parent 1:11 handle 11: sfq perturb 10
${TFAU} parent 1:0 prio 2 protocol ip handle 10 fw flowid 1:10
${TFAU} parent 1:0 prio 2 protocol ip handle 11 fw flowid 1:11
Finally, now that all our shaping is setup, we need to use iptables to mark packets to indicate which packets to shape. My internal network is 192.168.1.0/24. So we only mark packets headed for the internet and leave internal traffic alone. The first class will be restricted to a single IP address. The second class will be restrict to a group of IPs using CIDR notation (32 DHCP addresses from the router).
# download
${IPT} -t mangle -A POSTROUTING -s ! 192.168.1.0/24 -d 192.168.1.2 -j MARK --set-mark 10
${IPT} -t mangle -A POSTROUTING -s ! 192.168.1.0/24 -d 192.168.1.128/27 -j MARK --set-mark 11
# upload
${IPT} -t mangle -A PREROUTING -j IMQ --todev 0
${IPT} -t mangle -A PREROUTING -d ! 192.168.1.0/24 -s 192.168.1.2 -j MARK --set-mark 10
${IPT} -t mangle -A PREROUTING -d ! 192.168.1.0/24 -s 192.168.1.128/27 -j MARK --set-mark 11
Note: I would really like to use iptables range of address notation (e.g. -m iprange –src-range 192.168.1.3-192.168.1.254), but current builds of DD-WRT do not seem to work with that notation. I posted to the DD-WRT forums and I’ll I got was IP ranges are not supported. So for my own purposes, I just have giant script with many iptables commands, one for each IP address I want to shape.
To make it easy to start, stop, restart, I wrote an init.d style script for the above. I use it as part of the DD-WRT custom firewall script.

#!/bin/bash
TC="/usr/sbin/tc"
IPT="/usr/sbin/iptables"
IP="/usr/sbin/ip"
INSMOD="/sbin/insmod"
RMMOD="/sbin/rmmod"
DNLD_BANDWIDTH="12228kbit"
UPLD_BANDWIDTH="2048kbit"
DNLD_CLASS10_BANDWIDTH="8192kbit"
DNLD_CLASS11_BANDWIDTH="4096kbit"
UPLD_CLASS10_BANDWIDTH="1348kbit"
UPLD_CLASS11_BANDWIDTH="700kbit"
[ -x ${TC} ] || exit 1
[ -x ${IPT} ] || exit 1
[ -x ${IP} ] || exit 1
[ -x ${INSMOD} ] || exit 1
[ -x ${RMMOD} ] || exit 1
case "${1}" in
    start)
        echo -n "Starting bandwidth shaping service ... "
        # download
        TCA="${TC} class add dev br0"
        TFA="${TC} filter add dev br0"
        TQA="${TC} qdisc add dev br0"
        ${TQA} root handle 1: htb
        ${TCA} parent 1: classid 1:1 htb rate ${DNLD_BANDWIDTH}
        ${TCA} parent 1:1 classid 1:10 htb rate ${DNLD_CLASS10_BANDWIDTH} ceil ${DNLD_BANDWIDTH} prio 1
        ${TCA} parent 1:1 classid 1:11 htb rate ${DNLD_CLASS11_BANDWIDTH} ceil ${DNLD_BANDWIDTH} prio 2
        ${TQA} parent 1:10 handle 10: sfq perturb 10
        ${TQA} parent 1:11 handle 11: sfq perturb 10
        ${TFA} parent 1:0 prio 2 protocol ip handle 10 fw flowid 1:10
        ${TFA} parent 1:0 prio 2 protocol ip handle 11 fw flowid 1:11
        # upload
        ${INSMOD} imq
        ${INSMOD} ipt_IMQ
        ${IP} link set imq0 up
        TCAU="${TC} class add dev imq0"
        TFAU="${TC} filter add dev imq0"
        TQAU="${TC} qdisc add dev imq0"
        ${TQAU} root handle 1: htb
        ${TCAU} parent 1: classid 1:1 htb rate ${UPLD_BANDWIDTH}
        ${TCAU} parent 1:1 classid 1:10 htb rate ${UPLD_CLASS10_BANDWIDTH} ceil ${UPLD_BANDWIDTH} prio 1
        ${TCAU} parent 1:1 classid 1:11 htb rate ${UPLD_CLASS11_BANDWIDTH} ceil ${UPLD_BANDWIDTH} prio 2
        ${TQAU} parent 1:10 handle 10: sfq perturb 10
        ${TQAU} parent 1:11 handle 11: sfq perturb 10
        ${TFAU} parent 1:0 prio 2 protocol ip handle 10 fw flowid 1:10
        ${TFAU} parent 1:0 prio 2 protocol ip handle 11 fw flowid 1:11
        # download
        ${IPT} -t mangle -A POSTROUTING -s ! 192.168.1.0/24 -d 192.168.1.2 -j MARK --set-mark 10
        ${IPT} -t mangle -A POSTROUTING -s ! 192.168.1.0/24 -d 192.168.1.128/27 -j MARK --set-mark 11
        # upload
        ${IPT} -t mangle -A PREROUTING -j IMQ --todev 0
        ${IPT} -t mangle -A PREROUTING -d ! 192.168.1.0/24 -s 192.168.1.2 -j MARK --set-mark 10
        ${IPT} -t mangle -A PREROUTING -d ! 192.168.1.0/24 -s 192.168.1.128/27 -j MARK --set-mark 11
        echo "done"
    ;;
    stop)
        echo -n "Stopping bandwidth shaping service ... "
        # download
        ${IPT} -t mangle -D POSTROUTING -s ! 192.168.1.0/24 -d 192.168.1.2 -j MARK --set-mark 10
        ${IPT} -t mangle -D POSTROUTING -s ! 192.168.1.0/24 -d 192.168.1.128/27 -j MARK --set-mark 11
        # upload
        ${IPT} -t mangle -D PREROUTING -d ! 192.168.1.0/24 -s 192.168.1.2 -j MARK --set-mark 10
        ${IPT} -t mangle -D PREROUTING -d ! 192.168.1.0/24 -s 192.168.1.128/27 -j MARK --set-mark 11
        ${IPT} -t mangle -D PREROUTING -j IMQ --todev 0
        ${TC} qdisc del dev br0 root
        ${TC} qdisc del dev imq0 root
        ${IP} link set imq0 down
        ${RMMOD} ipt_IMQ
        ${RMMOD} imq
        echo "done"
    ;;
    restart)
        ${0} stop
        sleep 1
        ${0} start
    ;;
    status)
        ${TC} qdisc show dev br0
        ${TC} class show dev br0
        ${TC} filter show dev br0
        ${TC} qdisc show dev imq0
        ${TC} class show dev imq0
        ${TC} filter show dev imq0
    ;;
    *)
        echo "Usage: ${0} {start|stop|restart|status}"
        exit 1
    ;;
esac
exit 0
http://roback.cc/wp/2009/09/bandwidth-shaping-with-linux/#Introduction

Traffic shaping with tc

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

Contents

[hide]

[edit] 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

[edit] 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.

[edit] 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.

[edit] 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

[edit] 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.

[edit] 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
 
http://wiki.openvz.org/Traffic_shaping_with_tc 

HIERARCHICAL FAIR SERVICE CURVE

HIERARCHICAL FAIR SERVICE CURVE
 

HISTORY & INTRODUCTION

HFSC - Hierarchical Fair Service Curve was first presented at SIGCOMM'97. Developed as a part of ALTQ (ALTernative Queuing) on NetBSD, found its way quickly to other BSD systems, and then a few years ago became part of the linux kernel. Still, it's not the most popular scheduling algorithm - especially if compared to HTB - and it's not well documented from enduser's perspective. This introduction aims to explain how HFSC works without going to deep into math side of things (although some if it will be inevitable). In short HFSC aims to:

1)
guarantee precise bandwidth and delay allocation for all leaf classes (realtime criterion)
2)
allocate excess bandwidth fairly as specified by class hierarchy (linkshare & upperlimit criterion)
3)
minimize any discrepancy between the service curve and the actual amount of service provided during linksharing
The main "selling" point of HFSC is feature (1), which is achieved by using nonlinear service curves (more about what it actually is later). This is particularly useful in VoIP or games, where not only guarantee of consistent bandwidth is important, but initial delay of a data stream as well. Note that it matters only for leaf classes (where the actual queues are) - thus class hierarchy is ignored in realtime case.
Feature (2) is well, obvious - any algorithm featuring class hierarchy (such as HTB or CBQ) strives to achieve that. HFSC does that well, although you might end with unusual situations, if you define service curves carelessly - see section CORNER CASES for examples.
Feature (3) is mentioned due to the nature of the problem. There may be situations where it's either not possible to guarantee service of all curves at the same time, and/or it's impossible to do so fairly. Both will be explained later. Note that this is mainly related to interior (aka aggregate) classes, as the leafs are already handled by (1). Still - it's perfectly possible to create a leaf class w/o realtime service, and in such case - the caveats will naturally extend to leaf classes as well.
 

Bandwidth Limiting with IP Masquerade

Bandwidth Limiting with IP Masquerade - Howto


Contents
  Introduction
  Requirements
  Setting Bandwidth
  Marking Packets for Limiting
  Bandwidth Monitoring
  Conclusion

Introduction

This document is meant for IP Masquerade users who want to limit specific host's bandwidth.
The example made throughout the document is a aDSL line (640Kbits download / 160Kbits  upload) where
the DHCP hosts of the subnet are bandwidth limited and also forced through a cachine proxy.

My router specs are as follows:

Distribution:
Debian 2.2 (stable)
Technically, its Debian 3.0 (unstable), buy only the sysinit scripts, bind, sendmail, dhcp, nfs, samba and X are kept at the bleeding edge. (All the major 'Services').
Hardware:
CPU: 466Mhz Celeron
RAM: 192MB
DISK: 40GB 7200 RPM Maxtor ATA100, 2GB IBM 5400 RPM ATA33

Services:
DHCP Server
DNS Server
Mail Server
IP Masquerade (port fowarding also)
Caching Proxy (Squid)
Samba server
NFS Server

Requirements

The requirements here will only pertain to setting up bandwidth limiting and NOT IP Masquerading, DHCP Server, NFS Server, etc.

Kernel Requirements:

All IPTABLES support needed for IP Masquerade plus
  CONFIG_IP_NF_CONNTRACK
  CONFIG_IP_NF_TARGET_MARK --> This is for marking packets. We are going to mark the packets we want limited with this

QoS and/or fair queueing
  CONFIG_NET_SCH_CBQ
  CONFIG_NET_CLS_FW

Now I usually compile all the IPTABLES and QoS and/or fair queueing stuff as modules, but lsmod only shows those above as in use.

Software Requirements:

IPTABLES --> http://www.iptables.org/
iproute2   --> ftp://ftp.inr.ac.ru/ip-routing/  --> Most distributions come with this defaultly installed

Setting Bandwidth

I set my bandwidth in a shell script for the purpose of having it set on boot time and for ease and stopping and starting.
#!/bin/bash
#
#  All Rates are in Kbits, so in order to gets Bytes divide by 8
#  e.g. 25Kbps == 3.125KB/s
#
TC=/sbin/tc
DNLD=150Kbit              # DOWNLOAD Limit
DWEIGHT=15Kbit         # DOWNLOAD Weight Factor ~ 1/10 of DOWNLOAD Limit
UPLD=25KBit                # UPLOAD Limit
UWEIGHT=2Kbit           # UPLOAD Weight Factor

tc_start() {

    $TC qdisc add dev eth0 root handle 11: cbq bandwidth 100Mbit avpkt 1000 mpu 64
    $TC class add dev eth0 parent 11:0 classid 11:1 cbq rate $DNLD weight $DWEIGHT allot 1514 prio 1 avpkt 1000 bounded
    $TC filter add dev eth0 parent 11:0 protocol ip handle 4 fw flowid 11:1

    $TC qdisc add dev eth1 root handle 10: cbq bandwidth 10Mbit avpkt 1000 mpu 64
    $TC class add dev eth1 parent 10:0 classid 10:1 cbq rate $UPLD weight $UWEIGHT allot 1514 prio 1 avpkt 1000 bounded
    $TC filter add dev eth1 parent 10:0 protocol ip handle 3 fw flowid 10:1

}

tc_stop() {

    $TC qdisc del dev eth0 root
    $TC qdisc del dev eth1 root

}

tc_restart() {

    tc_stop
    sleep 1
    tc_start

}

tc_show() {

    echo ""
    echo "eth0:"
    $TC qdisc show dev eth0
    $TC class show dev eth0
    $TC filter show dev eth0
    echo ""

    echo "eth1:"
    $TC qdisc show dev eth1
    $TC class show dev eth1
    $TC filter show dev eth1
    echo ""

}

case "$1" in

  start)

    echo -n "Starting bandwidth shaping: "
    tc_start
    echo "done"
    ;;

  stop)

    echo -n "Stopping bandwidth shaping: "
    tc_stop
    echo "done"
    ;;

  restart)

    echo -n "Restarting bandwidth shaping: "
    tc_restart
    echo "done"
    ;;

  show)
   
    tc_show()
    ;;

  *)

    echo "Usage: /etc/init.d/tc.sh {start|stop|restart|show}"
    ;;

esac

exit 0

Now lets go through that.
At the top are some variables which make it easier to change the entire script with on change.
THIS SCRIPT IS ONLY ** ONE ** RULESET.
You can add as many rules as you like. I don't run a ISP, I only needed to restrict a few people.

This scripts assumes 2 things.
eth0 ==> is local network e.g. 192.168.0.0/24
eth1 ==> is Internet network e.g. Your ISP

Stop, Restart, and Show are self explanitory. I will not explain them.

Start:
$TC qdisc add dev eth0 root handle 11: cbq bandwidth 100Mbit avpkt 1000 mpu 64
$TC class add dev eth0 parent 11:0 classid 11:1 cbq rate $DNLD weight $DWEIGHT allot 1514 prio 1 avpkt 1000 bounded
$TC filter add dev eth0 parent 11:0 protocol ip handle 4 fw flowid 11:1

$TC qdisc add dev eth1 root handle 10: cbq bandwidth 10Mbit avpkt 1000 mpu 64
$TC class add dev eth1 parent 10:0 classid 10:1 cbq rate $UPLD weight $UWEIGHT allot 1514 prio 1 avpkt 1000 bounded
$TC filter add dev eth1 parent 10:0 protocol ip handle 3 fw flowid 10:1

First the top 3 three lines are for the Download bandwidth.

The first line creates and "PARENT" qdisc:
  --> $TC qdisc add dev eth0 root handle 11: cbq bandwidth 100Mbit avpkt 1000 mpu 64
man tc for more information, but basically its the device definition. 100Mbit Netgear card.
Next line creates the child qdisc with will have the actual download limit in it.
  --> $TC class add dev eth0 parent 11:0 classid 11:1 cbq rate $DNLD weight $DWEIGHT allot 1514 prio 1 avpkt 1000 bounded
man tc and friends again if you need any more definition than that. Personally I don't know what all it means or any optimal settings.
I just used the suggested man page defaults.
The last line and VERY important line, sets the handle on the child qdisc.
It sets the handle to 4.  Later we will use iptables to MARK the download packets with a 4 mark, and thats how the child qdisc will know
which packets to limit and which to let alone.

The Bottom three lines are for the uploading bandwidth.
Its the same as the download, but the device has changed from eth0 to eth1, the variables have changed from $DNLD to UPLD etc, and
the handle has changed from 4 to 3.

Marking Packets for Limiting

Ok now you are ready to mark packets as they come through in order to limit them.
I just added the next few lines to my rc.firewall.

# Mark packets to route
# Upload marking
$IPTABLES -t mangle -A FORWARD -s 192.168.0.128/29 -j MARK --set-mark 3
$IPTABLES -t mangle -A FORWARD -s 192.168.0.6 -j MARK --set-mark 3

# Download marking
$IPTABLES -t mangle -A POSTROUTING -s ! 192.168.0.0/24 -d 192.168.0.128/29 -j MARK --set-mark 4
$IPTABLES -t mangle -A POSTROUTING -s ! 192.168.0.0/24 -d 192.168.0.6 -j MARK --set-mark 4

Here I mark the following hosts:
192.168.0.6
192.168.0.128/29 =>
        192.168.0.128
        192.168.0.129
        192.168.0.130
        192.168.0.131
        192.168.0.132
        192.168.0.133
        192.168.0.134
        192.168.0.135

I hope no one needs help with Subnet masks. :)
Downloads are marked 4 and uploads are marked 3

29 means
http://szabilinux.hu/bandwidth/index.html