I once wrote that, so I thought to share it, feel free to copy.
Short trafgen (traffic generator), ifpps (measurement) howto:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(Patches + further ideas are welcome!)
*** Build + installation:
^^^^^^^^^^^^^^^^^^^^^^^^^
Additional libs required: libnl3-devel
$ git clone git://github.com/borkmann/netsniff-ng.git
$ cd netsniff-ng/src/
$ make trafgen
Building trafgen:
LEX trafgen_lexer.l
YAAC trafgen_parser.y
CC xmalloc.c
CC xio.c
CC xutils.c
CC mac80211.c
CC ring_tx.c
CC trafgen/trafgen_lexer.yy.c
CC trafgen/trafgen_parser.tab.c
CC trafgen.c
LD trafgen
STRIP trafgen
# make trafgen_install
Next to that, also 'ifpps' (needs ncurses-devel) might be useful,
ifpps reads out stats from procfs:
# make ifpps
Building ifpps:
CC xmalloc.c
CC xio.c
CC xutils.c
CC ifpps.c
LD ifpps
STRIP ifpps
# make ifpps_install
Run ifpps on the receiver side with:
# ifpps eth0 (normal working mode)
# ifpps --promisc --dev eth0 (in promisc mode)
# ifpps --promisc --dev eth0 --interval 10000 (for 10s measurement
interval)
# ifpps -lpcd wlan0 > plot.dat (for Gnuplot data output)
*** For general overview:
^^^^^^^^^^^^^^^^^^^^^^^^^
# trafgen -h
*** Stress test (configuration examples follow later):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# trafgen --dev eth0 --conf trafgen.cfg (normal working mode,
using TX_RING)
# trafgen --dev eth0 --conf trafgen.cfg --cpp (config shall go to C
preprocessor first)
# trafgen --dev wlan0 --rfraw --conf beacon-test.cfg (for injection of raw
802.11 packets)
# trafgen --dev eth0 --conf trafgen.cfg -k1000 (increase kernel batch
interval to 1ms)
# trafgen --dev eth0 --conf trafgen.cfg -J (enable Jumbo frame
support)
# trafgen --dev eth0 --conf trafgen.cfg --ring-size 100MB (use different
TX_RING mmap(2) size)
# trafgen --dev eth0 --conf trafgen.cfg --cpus 2 (use 2 CPUs instead of
all)
*** Smoke test:
^^^^^^^^^^^^^^^
E.g. setup: MachineA (trafgen) <--> MachineB (IP:10.0.0.1, test-system/kernel)
# trafgen --dev eth0 --conf fuzz-test.cfg \ (smoke test, means
after each injection to probe
--smoke-test 10.0.0.1 the remote end for
ICMP echo replies, if system
crashed, the current
``compiled'' packet payload
is printed together
with the srand(3) seed)
*** Debugging:
^^^^^^^^^^^^^^
# trafgen --dev eth0 --conf trafgen.cfg --gap 1000 (inter-packet gap: 1ms,
using sendto(2))
# trafgen --dev eth0 --conf trafgen.cfg --gap 0 (no inter-packet gap,
but still using sendto(2))
# trafgen --dev lo --conf trafgen.cfg --num 1 -V (only send 1 packet and
exit, be verbose)
# trafgen --dev eth0 --conf trafgen.cfg --gap 0 --cpus 2 --num 300 (only use 2
out of X cpus and distribute
packets fairly among
them if in cfg 'cpu()' is used)
# trafgen --dev eth0 --conf - (read packet config
from stdin)
*** Simple packet config examples (what goes into trafgen.cfg):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note that one trafgen.cfg file can have multiple packet configs (delimiters of
packets: '{','}')
{ 0xff, 0xff, [...] 0xff } (send one packet full
of 0xff's, note: replace [...] with hexstuff)
{ fill(0xff, 64) } (send one packet full
of 0xff's, 64 bytes are filled by this macro)
{ drnd(64) } (send one packet full
of 64byte random data, regenerated during run-time)
{ rnd(64) } (send one packet full
of 64byte random data, generated once during compile-time)
cpu(1): { rnd(64), 0b11001100, 0xaa } (send some garbage, but
only on CPU1, not from the others, CPU count starts with CPU0)
cpu(1:2): { drnd(64),'a',csum16(1, 8),'b',42 } (send some more
garbage, but only from CPU1 till CPU2)
{ fill(0xff, 64) } (send this packet from
all CPUs)
*** Here's a more complicated packet and built-in config example
(run it with e.g. # trafgen -e | trafgen -i - -o lo --cpp -n 1):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note that my comments here are inline and start with '>>', so do not include
them in the config file.
Example can be seen via from 'trafgen -e' as well (as already mentioned), this
example needs '--cpp':
/* Note: dynamic elements make trafgen slower! */
>> This above is how an comment looks like
#define ETH_P_IP 0x0800
#define SYN (1 << 1)
#define ECN (1 << 6)
>> This is for the C preprocessor to eat up, will replace the strings below,
but here could also
>> be sth. more complicated, since we use the full power of cpp!
{
/* MAC Destination */
fill(0xff, 6),
/* MAC Source */
0x00, 0x02, 0xb3, drnd(3),
/* IPv4 Protocol */
c16(ETH_P_IP),
>> This is a 'c16', 16 Bit constant, stored in big endian. There are:
c8(),c16(),c32(),c64() (long forms: const8(),..)
>> Content from there is evaluated/calculated during compile-time and the
result is stored in the payload
>> e.g. c16(((1 << 9) + 10 - (0b1100 % 3)) ^ 0b1010101001010101)
/* IPv4 Version, IHL, TOS */
0b01000101, 0,
>> Numbers can be represented as decimal (10), hex (0xff), octal (0812), binary
(0b1100), char ('a')
/* IPv4 Total Len */
c16(59),
/* IPv4 Ident */
drnd(2),
/* IPv4 Flags, Frag Off */
0b01000000, 0,
/* IPv4 TTL */
64,
/* Proto TCP */
0x06,
/* IPv4 Checksum (IP header from, to) */
csumip(14, 33),
>> IPv4 checksum calculation during runtime
/* Source IP */
drnd(4),
/* Dest IP */
drnd(4),
/* TCP Source Port */
drnd(2),
/* TCP Dest Port */
c16(80),
/* TCP Sequence Number */
drnd(4),
/* TCP Ackn. Number */
c32(0),
/* TCP Header length + TCP SYN/ECN Flag */
c16((0x8 << 12) | SYN | ECN)
/* Window Size */
c16(16),
/* TCP Checksum (offset IP, offset TCP) */
csumtcp(14, 34),
>> TCP checksum calculation during runtime
/* TCP Options */
0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x06,
0x91, 0x68, 0x7d, 0x06, 0x91, 0x68, 0x6f,
/* Data blob */
"gotcha!",
>> String, that will be dissected into a char array into the payload
}
*** Other/misc packet config functions:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Compile-time:
seqinc(1,2) - fill out byte sequence/array of length 2, incremented
by 1, starting with value 1
seqinc(1,2,3) - fill out byte sequence/array of length 2, incremented by
3, starting with value 1
seqdec(1,2) - fill out byte array of length 2, decremented by 1,
starting with value 1
seqdec(1,2,3) - fill out byte array of length 2, decremented by 3,
starting with value 1
Run-time:
dinc(1,9) - 1 byte counter in the interval of [1,9], increment by 1,
start with 1
dinc(1,9,2) - 1 byte counter in the interval of [1,9], increment by 2,
start with 1
ddec(9,1) - 1 byte counter in the interval of [1,9], decrement by 1,
start with 9
ddec(9,1,2) - 1 byte counter in the interval of [1,9], decrement by 2,
start with 9
--