RSHAPER - shape incoming traffic
" a, Z! b* k$ _! V! n6 ] d0 Q ================================2 C) |, G Q1 ~( N
1 y' Z2 b8 I3 GThis is a module for versions 2.0, 2.2 and 2.4 of the Linux kernel, it
0 t {/ [5 @% Q9 I. ^+ o |is meant to limit the incoming bandwidth for packets aimed at( @, q3 g1 i# L: O" o j
different hosts. With "incoming" I mean traffic that enters the7 D6 c8 l/ ^" h. [
shaping host; if that host is a gateway between target hosts and the
0 v$ ~9 d, l( G- s. c; D! s3 brest of the Internet, all the traffic of the target hosts will be
, f9 l7 p) k4 j4 h1 tshapeable.7 H4 v6 e: O$ N: P+ M
0 \4 V. N0 E% ~0 w) ?, TI see two interesting uses for this tool:
+ s3 G. n% {) v2 b2 H; D/ J( H
; T6 A# S- ?4 z1 C* v( }) D * Limiting the bandwidth available to permanently connected
) Y6 ]; X5 u" i! r1 v& E hosts by installing rshaper on their gateway. This is9 ?/ w) ^; H- f2 ]
interesting for ISP who offer housing and want to
/ B% k. E" ^' }; K differentiate the offer.
# C. e3 X% W4 p/ Q5 v7 T% t3 m6 Y2 y) E1 {- H
* Limiting download bandwidth from students' boxes or similar
L% o' {, c+ `/ V% n setups, by installing the rshaper directly on the8 D/ @) p+ ?% X, c
target computer. This requires that the user of that
! n7 K; T' U/ n: _. f9 Z6 U computer can not gain superuser privileges.
) e" d B; Q. ?+ m4 Q
2 o& p4 L5 @, w" a/ s6 tWhile the former issue can be addressed with the conventional shaper
, o- R" Z% g/ m7 `6 i: sdriver, the latter can't be easily addressed by the standard
$ @4 J; L: b5 e! r( J B1 Tshaper. As a matter of facts, I have not been able to use the shaper" q$ v4 D& ?7 d$ g2 a
to address the former situation, either; this because effective
- i/ B# i z+ |filtering can only be achieved through source-routing, but when I had- W1 \) @0 N) a+ J" }2 |
to deal with this problem, the shaper only existed for Linux-2.1" S, ~" k' J W/ X% h
while my production setup was constrained to be 2.0." Q' R0 L. B2 W6 n( v+ l
2 C) p3 P' H3 W" ], R" a! j
While running rshaper with 2.0 and 2.2 requires patching the network
/ V) [: F9 F0 P2 A$ |7 C: j. Fdriver, the 2.4 "netfilter" feature helps rshaper by avoiding the need2 k' l6 \& r: A% G. B" g; M: j
to patch the netword driver. Moreover, with netfilter the rshaper can
% V( S) i6 g! Z7 ^* j# aalso shape outgoing traffic.2 I0 _3 o Y- n0 z- U' a* u7 ?
. P# r) Z8 Z1 J) {6 w! z2 d
INSTALLATION% p) |* ?- m" S k5 S
============# x- N% V* D, o
* V* h6 d% B+ tFirst of all "make". You'll end up with an "rshaper.o" module, that3 a y$ l7 i- S
can be loaded to your kernel. If your kernel sources are not in
% {, ]8 T- t: g3 ?! L+ |: ~. Y/usr/src/linux, you must tell make where they are by setting KERNELDIR: b' p: f& o! X) B- ~& J* F
in the environment or specifying it on the make command line. For
|) L3 c* X) w/ W$ k2 Mexample:5 Q W/ G% v7 X
. ?" t+ Q) e, [$ _ make KERNELDIR=/usr/src/linux-2.4
8 X! C- N5 g, j1 Q9 q+ D( S" l, I' I1 n% w/ { |4 T. M ?
As suggested, the network driver you are using needs to be slightly3 S1 J' l2 X8 P7 ^1 m8 l6 ^
modified if you run version 2.0 or 2.2 of the kernel. The exact
5 w* i9 Z! ]/ c0 |% K! Tchanges to these kernels depend on your particular setup, and are
# C. E |9 f& L s* @. k' zdescribed in the following section.
$ @+ l# P) v4 A/ [. w0 \
9 X3 s) g& e. N4 v/ [ THEORY OF OPERATION
* c/ v9 G3 i" X& Y5 @ ===================: ?' F/ d% c9 K2 l" `# C( J1 F
$ A! }7 r# A, {0 E
The idea is easy: whenever a packet is received through a network( K6 }, D4 `4 F. O! Q
interface, the rshaper module delays notification of the packet to the
3 @+ [' Z3 J7 j0 \1 c+ z6 G0 pnetwork subsystem of Linux according to the expected data flow for the0 ^9 k+ n& a) o, Z; g" k
involved host. The same mechanism can be used for outgoing packets H6 D* [8 e: F s
under 2.4. If you use version 2.4, you can skip the rest of this2 g- {- [! V- B- |9 ?
section, otherwise please read on.
! g. H4 t4 x9 H5 K$ R$ s8 \! r' }7 \, } U# X- V8 F9 y
With 2.0 and 2.2, the network driver must be modified in order to call+ q4 @3 a) C2 C9 B: r! c" J& R$ N1 R) K
the shaper's receive function instead of the standard netif_rx().& s$ |/ `8 ^7 ?1 [6 g: H
Therefore, you should modify two lines of your network device driver.9 b8 C# ~3 e$ y4 Z
6 E7 C! q) Z* s0 `+ l( e$ t
In case you use a NE2000 clone or another 8390-based ethernet device,+ }9 N5 u8 }5 ]# b: W4 Q+ r4 d
you can use the patch included in this package as "8390-2.X.c.patch",
% m; [( s+ s8 e( w8 _where 2.X is your kernel version (2.0 or 2.2). If you are new to/ A. C3 r0 M* D( k7 Q
patches, please refer to the last section.( x8 g8 b+ |% _4 L& u2 K+ K8 ^
0 @# Z7 n+ f% g/ e7 q a
If your ethernet driver is not an 8390-based one, you have to do your
# p2 y! v: V1 k, [% Y( F2 }own changes (while I might offer patches for other devices, I am too. z5 r7 z7 m' d
lazy to do it, generally).! w; y$ n. T: e& S) J/ v& x' q% z
) Z" B4 D3 r2 o/ x- J
The code is simple:
& h$ _" G$ _6 q. t9 c# K, m9 s8 ~% }, ]
(1) in global space add the following line:
$ }0 l; n( I1 U) b# ?7 E0 ~ int (*net_shaper_rx_hook)(struct sk_buff *skb) = NULL;
9 F; \; x$ u5 e4 C4 Z! J: G" G( c* d8 U% I7 J4 S! @0 V; w9 b8 o- h
(2) Only for Linux-2.2 (not for Linux-2.0), add this too:
" f+ d- @% X4 ^3 F* H+ v K EXPORT_SYMBOL(net_shaper_rx_hook)! c6 Q& m1 @+ z0 G1 L, r/ U
this line must appear after the definition of the hook.+ t, J5 D q; |7 @1 @# U, f
7 s( U. \6 U5 v+ `1 y
(3) in the receive function of the driver change
P T3 X3 {+ E7 h3 y% H8 G netif_rx(skb)
$ P( {3 L! |' n b- \0 O to
' }/ U' p9 B8 {) @- u3 o if (net_shaper_rx_hook). F; N9 @: b. a. n7 Z
(*net_shaper_rx_hook)(skb);
! l& _( A' E, w7 o9 J. h* n else
: q3 W4 {! t- Q# P4 v: c netif_rx(skb);
6 b9 |& k7 q, H0 j& C3 S# W. W
1 W8 |3 r5 T" l/ U. d( Q! U- o0 N& Y* ^ NOTE 1: using non-8390-based modularized drivers with Linux-2.2
9 o; k9 U. c. n ---------------------------------------------------------------
/ l% h" x0 }" D$ J) O7 b0 r/ @4 d& O3 u, y
In version 2.2 of the Linux kernel, no symbol is exported by default$ ]" \, Q- Q% a" \
when loading a module. That's why you need to use the "EXPORT_SYMBOL"
( O1 i! N- O: O* \macro. However, using the macro may be not enough: the symbol( K$ F. }9 F" m1 E
"EXPORT_SYMTAB" must be defined in order for the symbol table to be( _8 o1 G5 I4 j. k u5 c6 C7 y
exported.( c. Y1 G9 U) X- e; [6 @
( p- G \% Y. ]$ P3 p4 P4 L
To define the symbol, compile the module with "-DEXPORT_SYMTAB" or
0 l( ?) V6 a3 n! zdefine the macro with "#define EXPORT_SYMTAB" in the module itself.' _% a6 Q1 F* ~$ [' O1 X: N
This step is not needed for 8390.c (the driver used by NE2000
^- d3 k, O7 v1 y2 ccompatible devices) because that module already exports some symbols.1 `% c! T4 s5 J( n; Y3 W& y
4 k/ n( H, [/ z0 L& h: M/ w
NOTE 2: using non-modularized drivers. J. H( x, X" r
-------------------------------------
0 n4 a6 C. P! |2 \- n& _: W# a, v7 r: o2 y
If your ethernet driver(s) is linked in the kernel image, instead of, K& R4 H- u5 E2 a m. d- v
being a module, you must also arrange for "net_shaper_rx_hook" to be: \. w/ W9 J- X8 l; e' L8 @
exported to modules, so that the "rshaper.o" module will find it. To+ f; ^+ v* j7 `, H7 V" _5 j6 K
do this, apply the patch "ksyms-2.X.c.patch" (again, 2.X is your6 V! M% D; Z e+ E" v0 |3 _9 \) b2 u3 ^
kernel version) to kernel/ksysms.c in the kernel sources., n* S9 g6 }9 F4 f7 |+ x0 m
: z, M) I; p: |) vPlease don't apply ksysms-2.X.c.patch if your network driver is a
# @% A( P5 H2 wmodule./ A }& w. {9 x+ |- N: u, [
5 j9 h% a0 l& v1 D3 j
( J( o- d" k6 _# J% p6 g
NOTE 3: using more than one network interface4 s6 f1 n; r8 p# S/ @8 f
---------------------------------------------0 q% j. g X+ {8 B% F3 ?- P
( M5 }/ C( B" f6 G: z2 ?& j9 H: ?
If your network interfaces are of different kinds, change (3) above. b: j$ k; l; K% F* [8 @! f
must be applied to all the drivers involved with shaping traffic,
4 g# y9 J: Y5 Q) ]' N: f a- vwhile change (1) must be applied differently:5 h+ H3 ^4 g n6 y, B/ ?5 S* |! b
. M& h$ P) s# f- W( [- r; _ (1a) only one network driver must have this line:
! G9 G+ t' X7 N' z1 G. v3 Q int (*net_shaper_rx_hook)(struct sk_buff *skb) = NULL;
/ I: Q2 H- J- \/ h) X4 \* Z- M: g
- a/ B6 P/ ]7 h2 r6 X7 r (1b) every other driver must have:& y. f; w# f) p
extern int (*net_shaper_rx_hook)(struct sk_buff *skb);
% t( _- g! e7 g3 Z K: U
/ S9 Y1 P# l- U# T$ T- ?$ y (2) if using version 2.2, only in the driver of (1a) above add:, c. n+ n0 N+ F5 o A
EXPORT_SYMBOL(net_shaper_rx_hook)/ a5 v3 n$ C! A, ?- d# X# v/ J
7 Q8 [! N9 Z" e" R$ k1 X
(3) if needed, follow NOTE 1 above, only for the driver : [6 g7 y6 l2 ]( g
* o( o n+ m6 ]+ ^ J; E5 `
The module with modification (1a) must be loaded before the ones with
+ s- u* g( B& lmodification (1b), otherwise loading will fail with ``unresolved
$ y2 p0 k3 J8 c8 |symbol "net_shaper_rx_hook"''/ s0 w7 ?! f; N' |4 d" Q
8 l- U3 [: G) C: _% E/ N* F
- d0 I4 z2 Q- C
7 N* x- ~: v+ A: d' s CONFIGURATION (USING RSHAPERCTL)
, r! e* y# ]; C; j+ a$ D ================================
% R$ d' w2 v& \# k$ f, l# G. @( m- Q9 X6 U$ j; ^9 g1 d$ Q
After reloading your modules or rebooting, you must load the0 K7 A) b0 `- v$ J* z' |9 m
"rshaper.o" module. To configure the bandwidth, then, use4 |; t; P3 D+ ?4 ?. b
"./rshaperctl". For example:& G R* Q* w0 K7 N. r
* }+ H9 e! P! } T) Z rshaperctl 192.168.1.2 6400 10( a. Y$ m' K6 v( w
1 [; J. m9 r* S5 z
Limits the incoming bandwidth for the host to 6400 bytes per second9 e+ e% \& m+ I
and queues packets as long as the queue is shorter than 10 seconds.$ y1 p* w, M4 S$ `" n9 ]9 J8 C% f
If the third argument is missing, it defaults to 5 seconds., g) B& y4 t9 y3 Q2 z5 B2 W/ J- k
" P+ e" |( S# h4 K1 o( `. m \
Version 1.06 of the tool adds an internal limitation to the size of
4 f# d! X1 r9 Xthe queue, in order to try preventing memory saturation. The amount
, X/ C V9 k" d( M5 R0 m4 |6 sof pending data is limited by the macro RSHAPER_LIMIT_KB which can be1 a8 K2 z( d( d# F" w7 K
defined at compile time and defaults to half a meg. Note that the
+ ?$ w6 Y7 \$ Smemory requirements of the queue can be far greater than the amount of
1 N* `5 X# g5 Q# A% n+ [6 MIP data being hosted, as rshaper has its own data structures to keep
/ c, f/ S0 a0 b( H% P2 ~- ]5 T( Ztrack of the packets.! ~3 [ D' y9 \1 ?5 s
6 K3 a/ D5 t$ H' `0 Y+ MTo remove the limit associate to an host, just use 0 as the allowed
/ ~, C0 H6 V3 J: G9 qbandwidth:
% |: V! J: m' ?! H% ]- X1 S" S1 f" `# @2 n9 Q6 a, z
rshaperctl 192.168.1.2 0
) @4 a" ~ J1 K \# T i0 G% ?; G- A- m: G" X: S: Y1 {
From version 1.04 onwards, it is possible to use computer names in$ |2 \; s9 B# \: E
addition to IP numbers.
N* f1 d% V4 @8 j8 b/ C0 g2 C* g( l' h6 j' l
You can also limit the bandwidth allocated to a network of computers.
9 }% r$ V% ~! v- Z ZTo this aim, you can add a netmask to the IP address. Both the7 D3 a1 B3 e, h& `. C
following forms work:
% @- h. F3 l) l+ B8 D6 M7 k" [* o1 ]( }. U
rshaperctl 192.168.1.16/255.255.255.240 19200' Q2 C( x& t; Y4 `3 b8 r3 }: T
rshaperctl 192.168.1.16/28 19200
/ o( S, Q4 G& P* P5 `
. q9 ]. h! a1 a) d"rshaperctl", when called without arguments, shows the current( d9 ?' i- A$ b; D
configuration. Two options can be passed to rshaperctl:5 W# ]$ A8 X, _% m. m& N1 g0 y* |
/ {, D" u' }, W" e
-n (numeric): don't decode IP numbers to name when reporting
% r: ?7 g( G# J9 I configuration information4 }0 d" U; j* ^7 d7 N o
-t (no-title): don't print the title line in the report. This
5 X8 N- m$ }3 ~9 \/ E5 F/ i is useful if you feed the output to a script
1 J- f; i* v2 k" k9 [* ?( f4 \1 \% P }/ Z2 J, ]5 i
Any other option makes rshaperctl print an help message. More) I! Z; u; e/ ?5 ?% I
information about rshaperctl is available as a man page: rshaperctl.8." ]3 L9 M& g) w
2 Y; e: V! B8 g b) s- u; g
SHAPING OUTGOING TRAFFIC
6 I s* U2 Q1 b: }& V9 N. O ========================
) F1 c% m( ^7 ^9 R+ B n0 P2 P, p, F
. t; |% i- P- VAs suggested above, in kernel 2.4 is possible to manage both incoming
& @* g$ c$ \$ jand outgoing packets. The load-time parameter "mode" specifies
- T; y9 t" b( P3 {. |whether the module handles received packets, transmitted ones or both
! B% B$ Y0 r" D( c' Qdirections. It is an integer parameter that can be set to:
' \4 s! v2 X: w+ x' V4 T! X6 k7 z2 ^1 ]0 e; N! [
0: Outgoing 5 E# L' S1 e$ ?0 ?
1: Incoming (default)
- |! ~7 F4 s7 j/ q" D) U: s8 r 2: 2 directions
. P+ F1 T8 Y6 Q0 E! x7 m! `# }. W y) [- S; s h7 p8 _1 i8 K
other values make the module barf and refuse to load. For example, for
0 z, |5 k- L7 Sbidirectional shaping use:4 f" k9 s' U# d) Y! s! i
$ A2 k: P! d4 S* P! y2 L2 W) f" Z. H
insmod rshaper.o mode=20 h/ `, v' c6 @# i. x& ?" `
! P0 v/ u U' _, s6 r$ n; YWhen rshaper works in mode 2, the same bandwidth limit is enforced
3 r+ S" p# e9 K+ a6 i( bfor both directions.
. z2 _# g% d( E$ [# K+ \ O( G7 [6 E0 a$ a7 B% A) X
Mode 2, bidirectional shaping, can be interesting for leaf computers
2 u6 p" o Z7 w2 Dwhere you want to limit both download and upload speed. However, a6 A* J. D! ^9 G3 ^! F& g7 l" x
router should not use mode 2. When a packet is forwarded through the
: O2 B. |( j* Y) m1 N V( f' t: W. lrouter and matches a shaping rule, it will be shaped twice: both when6 i% m, L6 L; T3 U
entering the computer and when leaving from it. This in practice! Q# Q8 W. a# i5 n+ L1 e4 V }
reduces the available bandwidth to less-than-half and reduses the
7 t1 V9 I1 k" b: M! Leffective length of the queue., J7 \4 n) B. @- d# S" Y
3 L3 r2 g z( s$ c# h( W) t- WWe know how to fix the problem, but are reluctant to add computational
' ~4 w( E" y: ]$ K8 y) R6 hoverhead for every packet, so the simple rule is: "routers should not
( ~, K6 U! Y3 }use mode 2, that would make no sense for them anyways".
5 j- e: }% X1 C! x
! n+ O( u% J! f. |4 b, } PATCHES (for users of Linux-2.0 and 2.2) V `- b! T& b8 t! A2 ^6 i
========================================+ n0 H* ?7 @1 M0 W
3 F0 k, R! h& {2 W( G$ M
Patch files are the output of "diff -c" or "diff -u" (preferred). They% ]( }) ? \' Y* r. B0 l9 r
describe how to change the original file to obtain a new one. A good
: x! F/ }% ^$ v3 q$ B. ^feature of patches is that they are human-readable, so you can always
9 `1 d; P7 i% M2 X+ p: qknow what is going on." O, V7 W4 ^0 O
6 n5 k7 v F7 h# J* _# q
To apply a patch, feed it to the standard input of the patch command., {4 H+ M' d, O, X; @. @# l. @
The command receives a few options on its command-line, the most
9 ?) b8 P; l7 p$ W! b" h; Vneeded being "-p". "-p" tells patch to discard path components: "patch
' R+ w( [4 y) h: l3 Y-p1" for example discards one path-component in the file names it find
6 x; b( E& B! s2 X: ]! ein the patch file before looking for files. You should pass the/ F$ y. `1 o' }4 V' g
correct "-p" option according to what your current directory is when6 f9 s+ p# l8 e) h/ x
you apply the patch file.
( G- @1 W1 R, [1 k8 o$ f) ^! K9 J3 V6 f# n& X0 t3 G
Specifically, to apply the "8390-2.X.c" patch included in this
6 |' L2 Z) ~8 N* C/ F( @distribution:. J% V8 d8 m+ e
+ d2 J D4 M- t' Y. Z) a8 j* P+ j& X4 u cd /your/kernel/src; patch -p0 < /.../8390-2.X.c.patch3 n8 k6 I N. V
or
' n9 r2 ~6 r( O6 r2 z- U cd /your/kernel/src/drivers/net; patch -p2 < /.../8390-2.X.c.patch
1 [! M7 ^- T" O; D% J) \. v
0 A$ [: x# H( ?- [: ]5 e3 ?5 O ^ ]0 t
DISCLAIMER
5 W! y) }8 F5 x: x: P! { ==========8 `- V* l; S3 u0 O4 t4 Y
- r/ a' \2 I6 q% M
This is not very refined, a lot of interesting things can be done and9 u0 Y) _7 V: w6 n, o1 ?
aren't; check shaper.c distributed with Linux-2.2 or netfilter, c% R- {4 O3 i$ ~* ?6 T/ |0 Z
distributed with Linux-2.4 to see some of the fine details that are
8 C) H0 f6 U5 l3 X- amissing from there.0 Y+ s+ @) p& D Z4 F/ J1 |
! n1 c; J# }% g0 M
R- h3 [7 D. H( w+ T LICENSE
8 d4 ]3 `3 G, S* l% B/ D =======
0 {8 N1 [0 l: D" {+ [8 G1 |- e# u1 i2 i! j! I
The code is released according to the GPL, in the hope you find it
2 R- b9 S1 m' q. K, G$ Q" Tuseful.
, M+ i/ _. T! _8 d! p0 ^8 e, B
& {& L, `+ Z# pEnjoy
. u: ]' E* M* `/alessandro and rodolfo |