		RSHAPER - shape incoming traffic
		================================

This is a module for versions 2.0, 2.2 and 2.4 of the Linux kernel, it
is  meant  to  limit  the  incoming bandwidth  for  packets  aimed  at
different  hosts.  With  "incoming"  I mean  traffic  that enters  the
shaping host; if  that host is a gateway between  target hosts and the
rest of  the Internet,  all the  traffic of the  target hosts  will be
shapeable.

I see two interesting uses for this tool:

	* Limiting   the bandwidth available  to permanently connected
		hosts by installing rshaper on  their gateway. This is
		interesting  for ISP  who offer  housing  and want  to
		differentiate the offer.

	* Limiting download bandwidth  from students' boxes or similar
		setups, by installing  the   rshaper directly  on  the
		target computer. This  requires that the user of  that
		computer can not gain superuser privileges.

While  the former issue can be  addressed with the conventional shaper
driver, the    latter  can't be  easily   addressed by   the  standard
shaper. As a matter of facts,  I have not been able  to use the shaper
to  address   the former situation,   either;   this because effective
filtering can only be achieved through  source-routing, but when I had
to deal  with  this problem, the  shaper  only existed for Linux-2.1
while my production setup was constrained to be 2.0.

While running rshaper  with 2.0 and 2.2 requires  patching the network
driver, the 2.4 "netfilter" feature helps rshaper by avoiding the need
to patch  the netword driver. Moreover, with netfilter the rshaper can
also shape outgoing traffic.

		INSTALLATION
		============

First of  all "make". You'll end  up with an  "rshaper.o" module, that
can  be loaded  to your  kernel.  If your  kernel sources  are not  in
/usr/src/linux, you must tell make where they are by setting KERNELDIR
in  the environment or  specifying it  on the  make command  line. For
example:

	make KERNELDIR=/usr/src/linux-2.4

As suggested,  the network driver you  are using needs  to be slightly
modified  if you  run version  2.0 or  2.2 of  the kernel.   The exact
changes  to these  kernels depend  on your  particular setup,  and are
described in the following section.

		THEORY OF OPERATION
		===================

The  idea is easy:  whenever  a packet is   received through a network
interface, the rshaper module delays notification of the packet to the
network subsystem of Linux according to the expected data flow for the
involved host.  The same  mechanism can be  used for  outgoing packets
under  2.4. If you  use version  2.4, you  can skip  the rest  of this
section, otherwise please read on.

With 2.0 and 2.2, the network driver must be modified in order to call
the  shaper's receive  function  instead of  the standard  netif_rx().
Therefore, you should modify two lines of your network device driver.

In case you use a  NE2000 clone or another 8390-based ethernet device,
you can use the patch  included in this package as "8390-2.X.c.patch",
where 2.X  is your  kernel version (2.0  or 2.2).   If you are  new to
patches, please refer to the last section.

If your ethernet driver is not an 8390-based  one, you have to do your
own changes (while I might  offer patches for  other devices, I am too
lazy to do it, generally).

The code is simple:

  (1) in global space add the following line:
          int (*net_shaper_rx_hook)(struct sk_buff *skb) = NULL;

  (2) Only for Linux-2.2 (not for Linux-2.0), add this too:
          EXPORT_SYMBOL(net_shaper_rx_hook)
      this line must appear after the definition of the hook.

  (3) in the receive function of the driver change
           netif_rx(skb)
  to
           if (net_shaper_rx_hook)
                   (*net_shaper_rx_hook)(skb);
           else
                   netif_rx(skb);

	NOTE 1: using non-8390-based modularized drivers with Linux-2.2
	---------------------------------------------------------------

In version 2.2  of the Linux kernel, no symbol  is exported by default
when loading a module. That's  why you need to use the "EXPORT_SYMBOL"
macro.   However,  using the  macro  may  be  not enough:  the  symbol
"EXPORT_SYMTAB" must  be defined in order  for the symbol  table to be
exported.

To  define the symbol,  compile the  module with  "-DEXPORT_SYMTAB" or
define the  macro with "#define  EXPORT_SYMTAB" in the  module itself.
This  step  is  not needed  for  8390.c  (the  driver used  by  NE2000
compatible devices) because that module already exports some symbols.

	NOTE 2: using non-modularized drivers
	-------------------------------------

If your ethernet  driver(s) is linked in the  kernel image, instead of
being a module,  you must also arrange for  "net_shaper_rx_hook" to be
exported to modules, so that  the "rshaper.o" module will find it.  To
do  this, apply  the  patch "ksyms-2.X.c.patch"  (again,  2.X is  your
kernel version) to kernel/ksysms.c in the kernel sources.

Please  don't apply  ksysms-2.X.c.patch if  your network  driver  is a
module.


	NOTE 3: using more than one network interface
	---------------------------------------------

If your  network interfaces are  of different kinds, change  (3) above
must  be applied  to all  the drivers  involved with  shaping traffic,
while change (1) must be applied differently:

  (1a) only one network driver must have this line:
          int (*net_shaper_rx_hook)(struct sk_buff *skb) = NULL;

  (1b) every other driver must have:
          extern int (*net_shaper_rx_hook)(struct sk_buff *skb);

  (2) if using version 2.2, only in the driver of (1a) above add:
          EXPORT_SYMBOL(net_shaper_rx_hook)

  (3) if needed, follow NOTE 1 above, only for the driver 

The module with modification (1a) must  be loaded before the ones with
modification  (1b),  otherwise  loading will   fail  with ``unresolved
symbol "net_shaper_rx_hook"''



		CONFIGURATION (USING RSHAPERCTL)
		================================

After  reloading  your  modules   or rebooting,  you   must load   the
"rshaper.o"  module.   To   configure   the   bandwidth,    then,  use
"./rshaperctl". For example:

           rshaperctl 192.168.1.2 6400 10

Limits the  incoming bandwidth for the  host to 6400  bytes per second
and queues  packets as long as  the queue is shorter  than 10 seconds.
If the  third argument is missing,  it defaults to  5 seconds.

Version 1.06  of the tool adds  an internal limitation to  the size of
the queue, in  order to try preventing memory  saturation.  The amount
of pending data is limited  by the macro RSHAPER_LIMIT_KB which can be
defined at  compile time  and defaults  to half a  meg. Note  that the
memory requirements of the queue can be far greater than the amount of
IP data being  hosted, as rshaper has its own  data structures to keep
track of the packets.

To remove  the limit  associate to an host, just use  0 as the allowed
bandwidth:

	   rshaperctl 192.168.1.2 0

From version  1.04 onwards, it  is  possible to use computer  names in
addition to IP numbers.

You can also limit the bandwidth  allocated to a network of computers.
To this aim, you  can  add a netmask  to  the  IP address.  Both   the
following forms work:

	   rshaperctl 192.168.1.16/255.255.255.240  19200
	   rshaperctl 192.168.1.16/28 19200

"rshaperctl", when   called   without arguments,   shows   the current
configuration. Two options can be passed to rshaperctl:

	-n   (numeric): don't decode IP numbers to name when reporting
		configuration information
	-t   (no-title): don't print the title line in the report. This
		is useful if you feed the output to a script

Any  other  option  makes  rshaperctl  print  an  help  message.  More
information about rshaperctl is available as a man page: rshaperctl.8.

		SHAPING OUTGOING TRAFFIC
		========================

As suggested above, in kernel  2.4 is possible to manage both incoming
and  outgoing  packets.   The  load-time  parameter  "mode"  specifies
whether the module handles  received packets, transmitted ones or both
directions. It is an integer parameter that can be set to:

	0: Outgoing 
	1: Incoming (default)
	2: 2 directions

other values make the module barf and refuse to load. For example, for
bidirectional shaping use:

	insmod rshaper.o mode=2

When rshaper  works in mode 2,  the same bandwidth  limit is enforced
for both directions.

Mode 2,  bidirectional shaping, can be interesting  for leaf computers
where you  want to  limit both download  and upload speed.  However, a
router should not  use mode 2. When a packet  is forwarded through the
router and matches a shaping rule,  it will be shaped twice: both when
entering  the computer  and when  leaving  from it.  This in  practice
reduces  the available  bandwidth  to less-than-half  and reduses  the
effective length of the queue.

We know how to fix the problem, but are reluctant to add computational
overhead for every packet, so  the simple rule is: "routers should not
use mode 2, that would make no sense for them anyways".

		PATCHES (for users of Linux-2.0 and 2.2)
		========================================

Patch files are the output of "diff -c" or "diff -u" (preferred). They
describe how to change the original  file to obtain  a new one. A good
feature of patches is that they  are human-readable, so you can always
know what is going on.

To apply a patch, feed it to the standard  input of the patch command.
The command  receives  a few  options on   its command-line,  the most
needed being "-p". "-p" tells patch to discard path components: "patch
-p1" for example discards one path-component in the file names it find
in the patch   file before looking   for  files. You  should pass  the
correct "-p"  option according to  what your current directory is when
you apply the patch file.

Specifically,  to  apply  the  "8390-2.X.c"  patch  included  in  this
distribution:

    cd /your/kernel/src; patch -p0 < /.../8390-2.X.c.patch
or
    cd /your/kernel/src/drivers/net; patch -p2 < /.../8390-2.X.c.patch


		DISCLAIMER
		==========

This is not very refined, a  lot of interesting things can be done and
aren't;  check  shaper.c   distributed  with  Linux-2.2  or  netfilter
distributed with  Linux-2.4 to see some  of the fine  details that are
missing from there.


		LICENSE
		=======

The code  is released according  to the GPL,  in the hope you  find it
useful.

Enjoy
/alessandro and rodolfo
