http://janus.ajusco.upn.mx/rshaper.txt

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 > http://janus.ajusco.upn.mx/rshaper.txt