		TCPBLAST - NETWORK BANDWIDTH MEASURING TOOL

Tcpblast can be used for:
- crude network throuput measurements
- testing bandwidth limits (also in incoming direction or bidirectional)

Tcpblast typically will need one of the discard, echo or chargen services which
are usually turned off because of security reasons.

WARNING: tcpblast is really crude and measures the throuput by sending as much
data as possible. USE CAREFULLY. For much more subtle bandwidth measurements
use
http://www.employees.org/~bmah/Software/pchar/	by Bruce A. Mah
http://www.cs.colby.edu/~downey/clink/		by Allen B. Downey
ftp://ftp.ee.lbl.gov/pathchar/			by Van Jacobson


		PATHCHAR-STYLE TOOLS AND TCPBLAST COMPARISON

Pro:
- gives immediate results
- clogs the link - good for testing actual bandwidth limits (like CBQ+TBF)
- bidirectional
- can generate traffic with specific limit for specified time

Contra:
- needs discard or echo service
- wastes bandwidth
- bottleneck measurement only
- cannot measure raw capacity on loaded link


		COUSINS

New version of tcpblast is based on (or ideas contained in) tcpblast, tcpping,
tcpspray and ttcp, various versions floating around, mostly on FreeBSD version
of tcpblast (signed: Daniel Karrenberg <dfk@nic.eu.net>, but I do not think we
should bother him with bugs of this version).


		INSTALLATION

Tcpblast can be made as follows:

./configure
make
make install

The standalone discard program is not installed by default.


		RECENT VERSION

The newest version is available in
ftp://ftp.6bone.pl/pub/blast/


Discussion list, subscribing:

echo subscribe tcpblast | mail majordomo@sunsite.icm.edu.pl

messages to:

tcpblast@sunsite.icm.edu.pl


		OPTIONS

WARNING: most of the options changed since version 19991109!

NEW!: RATE, using units

Usage: tcpblast [options] destination[:port]

tcpblast/udpblast is a simple tool for probing network and estimating its
throughput. By default it sends 300 blocks (1024 bytes each) of data to
specified destination host.

Options:
-a               send random data
-b BUF_SIZE      socket buf size (default: -1 == don't change), with `-' to be
                   substracted from results
-c BLOCKS        change default (300) number of blocks, range: 1..10000000
-d DOTFREQ       print dot every DOTFREQ blocks, disables cont. speed disp.
-h, --help       this help
-i, --delay DELAY  write delay in microseconds (EXPERIMENTAL)
-l, --last BLKS  show also speed for last BLKS blocks
    --nwrite     do not write, use e.g. with chargen port
-m               results for every block in separate line
-o               turn off default continuous speed displaying
-p PORT          bind this local PORT
-q --quiet       show only final statistics
-r, --read       read data returned to us, switches default port to echo
-R, --rate RATESPEC  limit the speed according to the RATESPEC
-s BLOCK_SIZE    block size (default 1024 bytes)
-t MAXTIME       limit time to MAXTIME s (up to 42950 h)
    --tcp        use TCP (default)
    --udp        use UDP (default if named udpblast)
-v, --verbosity  verbosity, default 0, maximum 3. -v adds time display, -vv also speed
                   in B/s, -v - speed in b/s.
-V, --version    version
destination      host name or address
port             use port #/name xyz instead of default port 9

RATESPEC         RATE[,TIME][:RATE[,TIME]]...
RATE             generating data at RATE speed in B/s
TIME             for TIME seconds (can be floating point number), last can
                   be omitted and that time will be infinite

Options -b, -c and -R can use case insensitive unit multipliers and
specifiers:
  -b without units is in bytes, can use [{k,m,g}]b (lower or upper case)
     for KB, MB or GB. {k,m,g} are powers of 1024.
  -c argument is just a number, can have k, m or g added (powers of 1024),
     no unit needed
  -R RATE is in B/s or Bps, the postfixes can be [{k,m,g}]{b/s,bps}
  -R TIME is in seconds, can be posfixed with [{k,m,g}]{s,min,h,w,m,y}
Example:
  tcpblast -b 4KB -c 10k -R 10kbps,2:20kbps,3s target

tcpblast version: FreeBSD + rzm 20001017


		EXAMPLES

tcpblast -c 200 step

read SO_SNDBUF = 65535
Sending non-random TCP data to step:9 using 1024 B blocks.
Written   200 KB   35.10 KB/s

tcpblast -r -c 200 --nwrite step:chargen

read SO_SNDBUF = 65535
Sending non-random TCP data to step:chargen using 1024 B blocks.
/Read /200 KB   /9.65 KB/s

tcpblast -r -c 200 step:echo

read SO_SNDBUF = 65535
Sending non-random TCP data to step:echo using 1024 B blocks.
Written/Read   200/200 KB   16.98/16.94 KB/s

But:

tcpblast step:chargen

blocks after some time because chargen is not reading anything, we can fill the
buffers and that is all. Such command can be stopped by ^C or using a time
limit:

tcpblast -t 10 step:chargen


With UDP one can get very high apparent throuput because of discarded packets.
UDP does NOT have the acknowledging mechanism as TCP has. You can check how
many packets got to the destination with tcpdump - usually much less than sent.
Some estimation is possible with usage of echo service:

udpblast -r pingwin:echo

read SO_SNDBUF = 8192
Sending non-random UDP data to pingwin:echo using 1024 B blocks.
Written/Read   300/201 KB   5837.71/461.34 KB/s     ^C

tcpblast -p 40023 step

Send/receive from/to port 40023. I needed it for one of the traffic limits
tests.


Simple rate limit (to 10000 B/s):

tcpblast -R 10000 rzm-ac

Advanced rate limits:

tcpblast -c 9999 -R 10000,5:20000,5 -l 10 -vvv rzm-ac

Sends 9999 blocks. The RATESPEC 10000,5:20000,5 says to send 10000 B/s for 5 s,
then 20000 B/s for another 5 s. '-l 10' additionally shows the speed for last
10 blocks. -vvv displays the time, speed in B/s and b/s.

The result

Written   147 KB  in 10002.8 ms   120389.2 b/s   15048.6 B/s   14.70 KB/s  (last 10 KB: 19692.3 B/s)

shows the final speed in B/s as more less 15000 B/s - it is an average of 10000
and 20000 B/s, 5 s each.

For high speeds the TCP buffer size and time used for displaying speed
continuously matter.

In the last (or only) RATE,TIME in RATESPEC the TIME can be omitted. This means
a more less infinite time.


Recent version can use units:

tcpblast -b 4KB -c 10k -R 10kbps,2:20kbps,3s target

In this somewhat artificial example we are:
- trying to set 4 KB buffer
- sending 10 K == 10240 blocks; lower case 'k' is always the same as 'K' equal
  to 1024
- sending 10 KB/s (again lower case 'k' is 1024, 'b' in 'bps' is 'B', i.e.
  byte) for 2 seconds (no unit specified, default for time is 's')
- and then sending 20 KB/s for 3 s
to the target.


		CHANGES

- setting TCP/UDP
- setting block size
- setting buffer size
- sending random data
19960224 version released
19960926 setting port # 
         uploaded to sunsite.unc.edu
19961001 option for setting # of dots per block sent 
         some cleanup
19961002 better description of -b in usage()
         corrected bug in setsockopt (buffer wasn't set)
         for -r buffer still wasn't filled with random data (Pratip K. Banerji <pbanerji@bbn.com>)
         version 961002a
19961003 usage_small() used in same cases instead of usage()
         some help/error messages rearangement
19961028 getopt from GNU libc 961017 included
         #include <errno.h>
         compiles+links on Solaris 0.5
         more files, Makefiles and such
19970119 -c option for continuous speed display
         either port # or name can be used with -p
         SunOS (4.1.3) compile target works
19981108 included DEC OSF/1 changes from Arun Moorthy <moorthy@cs.iitm.ernet.in> (sent Feb 97,  sorry..)
         getsockopt() should know how much space can it use for returned parameter, so size must be 4
         output shows data/time and (data-bufsize)/time. far from perfect, take a look
         y2k problem in version number (:
         install target
19981109 printresult() in a loop arguments corrected
         -e(xperimental) option
         default port now properly printed
19981112 dist Makefile target
         changed . into - in the package name
19990326 install udpblast too (as a symlink)
         version.h depending on tcpblast.c
19990504 2 spaces after 'KB/s'
	 I don't understand why
write(3, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"..., 65536) = -1 EFAULT (Bad address)
write(2, "tcp/udpblast send:: Bad address\n"..., 32tcp/udpblast send:: Bad address
) = 32
	 with -s 65536. It works OK up to 46648 B (?!)
19991102 configure.in and such borrowed from nmap
	 Karsten Hecker <karsten@merlin.nrw-online.de> had problems compiling it on Solaris, should work with configure
	 Michal 'Orr' Daszkowski <midas@ufik.idn.org.pl> spotted a long standing bug in port arg copying
	 included a manual from Artur R. Czechowski <arturcz@bofh.org.pl>, I'm sure it is going to be outdated soon
	 moved binary do ..../sbin
19991103  -c  (continuous) is default now, instead of dots
	 millisecond = ms (not msec)
	 time scaling when adding s and us (USCALE)
	 circular buffer for measuring last nnn blocks speed, the option: -l nnn  (off by default)
19991103a one more correction to port arg copying
19991104 massive rewrite, mostly for bidirectionality
	 summary on ^C
	 both read and write are O_NONBLOCK
	 can run RO, RW, WO
19991108 htons(port) (Peter Barton <pbarton@i3s.net> was complaining on it, backported to 19991103a)
19991109 changed options letters
19991116 small fatal error, this version can be considered beta
	 RPM made
20000525 small changes in source and README, UDP example
	 -r changes default port to "7" (echo)
	 -i DELAY  option implemented, seems to not to scale below 30000 us
20000711 -p PORT  for specifying local port
         spell check
20000725 char -> int	optchar - spotted while compiling on AIX; no other
	 corrections needed!
	 the same on mips-sgi-irix6.3
	 checked compiling on sparc-sun-solaris2.7
20000727 new config.{sub,guess}
20000810 checked compiling on i386-unknown-openbsd2.7
20000904 -R RATESPEC, see --help and examples, tested on Linux only
	 maximal # of blocks in -c is 100000 now
	 -q --quiet option (the same as -d 0)
	 excluded completely outdated man page from an RPM
20001016 separate standalone discard/echo/chargen
20001017 Solaris compatibility, added compat.h (timersub(), timeradd() from
	 Linux includes), daemon.c and strsep.c from glibc-2.1.91
	 parsing units in -R, -c, -b
	 MODE_TEMPLATE in discard to make adding new services easier
	 getopt* compatibility files update, new taken form glibc-2.1.91
	 oops! forgotten that -s and -t options could use units too; there are some others too
20001019 preliminary IPv6 support
	 timersub() detection corrected
	 UDP in discard
	 some configure.in cleanups
	 don't backspace in dots mode when not writing (problem seen by Edgar Glowacki)
	 man page update
20001026 portability fixes
20001101 optimization attempts
20001101 release
20010104 TCP_MAXSEG option to specify packet size
	 beta release
20010620 SOL_TCP (Linx specific?) -> IPPROTO_TCP
20010925 ... tried to compile on Digital Unix V4.0 and could not. I have added casts to int in few places.
20011110 badly formulated ifs in printresult() were leaking memory with every block sent
	 --source address  option; with getaddriinfo() and inet_pton() works for IPv6 too
	 actually binding a local port in getaddrinfo() version
	 in setmaxseg(): message about TCP_MAXSEG, not SO_SNDBUF
	 defining INADDR_NONE as INADDR_BROADCAST or just -1 (for Solaris 2.6)
	 <compat.h> instead of "compat.h" in tcpblast.c and discard.c was
		catching some other compat.h than ours
	 as usual, NEVER EVER USE SINGLE VARIABLE FOR TWO PURPOSES: with
		#undef HAVE_GETADDRINFO  and  #define HAVE_INET_PTON , int err
		declaration was hidden
20011111 new version


		PORTS

Done and tested (20000711):
- Linux Rawhide 19991031, Sparc, 19991102
- Linux RedHat 6.0, i486, 19991109; 6.2, i686 - 20000711
- Solaris 2.6, Sparc, 19991102
- Solaris 2.7, Sparc, 20000725 (sparc-sun-solaris2.7)
- FreeBSD 4.0, i686, 20000711 (hm.. no getopt.h?)
- AIX 4.1, powerpc, 20000725 (powerpc-ibm-aix4.1.4.0)
- IRIX 6.3, mips, 20000725 (mips-sgi-irix6.3)
- OpenBSD 2.7, ix86, 2000810 (i386-unknown-openbsd2.7)

20001017:
- Linux RedHat 6.2
- Solaris 2.6, 2.7

20001026
- Linux RedHat 6.2
- Solaris 2.6, 2.7
- FreeBSD 4.0

20010620
- Linux RedHat 6.2 i386, Sparc32
- Solaris 2.6
- does not compile on Solaris 2.5.1
- FreeBSD 4.3
- OpenBSD 2.8
- AIX 4.1.4 powerpc

20011110
- Linux RedHat 7.2 i386
- Linux RedHat 6.2 sparc
- Solaris 2.5.1, 2.6, 2.8 sparc
- FreeBSD 4.3 i386
- OpenBSD 2.8 i386
- AIX 4.1.4 powerpc
- IRIX 6.5 mips


		TODO

- make a real man page instead of .pod
- multi-port discard?
- source address option in discard
- statistics and logging of them in discard
- rate self limiting: to save CPU limit sending speed to 110% of average rate
  off when  -R  on (will it help really? negative experimental results)
- 'goto 3' - G3 in -R would allow looping
- add even more options - progressing, 17 on Oct 17th, 2000
  - sending file contents - -f
  - comparing when write-read, like tcpblast-dfk or tcpspray
- what features netperf can offer? (i.e. which I could steal?)
- learn/invent more theory and think how to improve accuracy of bandwidth
  measurement (maybe it could be corrected for the buffer size.. - doesn't help
  much 19981108) (-b 1024 gives more reasonable results)
- Menno Pieters <menno.pieters@stelvio.nl> made a timeout option, maybe better
  than mine
- adding more services to discard/echo/chargen (time, daytime?)
- gettext i18n


		BUGS

- I'm a perfectly bad and careless maintainer
- we have memory leaks: in getaddrinfo() (?!) as ccmalloc shows: 4595 bytes in
  79 chunks - is it real?
- autoconf system is somewhat shaky here

Patches for this and other problems send to the address below.

rzm@icm.edu.pl
