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

--


Reply via email to