i used this quite extensively to work on tcp SYNOPSIS nettest -l [ -s sleepms ][ -n nblocks ] nettest [ -a addr ][ -s sleepms ] nettest -r raddr -n nblocks DESCRIPTION Nettest tests goodput of reliable, in-order transports at full speed, and with receiver throttling. Both sender and [...] Reference: /n/sources/patch/maybe/net-test Date: Mon Dec 24 17:38:40 CET 2012 Signed-off-by: quanstro@quanstro.net --- /sys/src/cmd/nettest.c Thu Jan 1 00:00:00 1970 +++ /sys/src/cmd/nettest.c Mon Dec 24 17:37:33 2012 @@ -0,0 +1,179 @@ +#include +#include + +char *service = "17766"; +char *laddr = "*"; +char *raddr; + +uchar flag[127]; +ulong n; +long sleepms; +vlong sleepns; + +#define dprint(...) {if(flag['d']) print(__VA_ARGS__);} + +enum { + Blen = 8*1024, +}; + +void +usage(void) +{ + fprint(2, "usage: %s [-l] [-s sleepms] [-n nblocks]\n" + " %s [-a addr] [-s sleepms]\n" + " %s -r addr -n nblocks\n", argv0, argv0, argv0); + exits("usage"); +} + +void +die(void) +{ + sysfatal("%s: %r", argv0); +} + +int +notef(void*, char *note) +{ + if(strstr(note, "alarm") != nil) + return 1; + return 0; +} + +char* +·netmkaddr(char *linear, char *net, char *service) +{ + char *r; + static QLock stupid; + + qlock(&stupid); /* protect stupid static memory */ + r = netmkaddr(linear, net, service); + if(r != nil) + r = strdup(r); + qunlock(&stupid); + + return r; +} + +void +client(void) +{ + char *dst, b[Blen]; + int fd, i; + + atnotify(notef, 1); + sleep(1); + dprint("client\n"); + dst = ·netmkaddr(raddr, "tcp", service); + alarm(3*1000); + if((fd = dial(dst, 0, 0, 0)) < 0) + die(); + alarm(0); + free(dst); + dprint("dialed\n"); + for(i = 0; i < n; ++i){ + if(write(fd, b, sizeof b) < 0) + die(); + } + close(fd); + dprint("wrote\n"); +} + +void +server(void) +{ + int acfd, lcfd, dfd; + char adir[40], ldir[40], b[Blen], *a; + long c; + uvlong i, t; + double ratemb, maxr, delta; + NetConnInfo *nc; + + dprint("server\n"); + a = ·netmkaddr(laddr, "tcp", service); + acfd = announce(a, adir); + if(acfd == -1) + die(); + free(a); + + dprint("listen\n"); + if((lcfd = listen(adir, ldir)) < 0) + die(); + dprint("listened\n"); + if((dfd = accept(lcfd, ldir)) < 0) + die(); + nc = getnetconninfo(ldir, dfd); + dprint("accepted\n"); + t = -nsec(); + for(i = 0;; i++){ + c = readn(dfd, b, sizeof b); + if(c != sizeof b) + break; + if(sleepms) + sleep(sleepms); + } + t += nsec(); + close(dfd); + close(lcfd); + + print("%s count %llud; ", nc? nc->raddr: "(unknown)", i); + free(nc); + i *= Blen; + delta = t/1e9; + ratemb = i/delta/1024/1024; + if(sleepms > 0){ + maxr = Blen*1000. / sleepms / 1e6; + print("%llud bytes in %g s @ %.2g MB/s (%ldms; limit %.2g MB/s)\n", i, delta, ratemb, sleepms, maxr); + } + else + print("%llud bytes in %g s @ %.2g MB/s (0ms)\n", i, delta, ratemb); +} + +void +main(int argc, char **argv) +{ + ARGBEGIN{ + case 'r': + raddr = EARGF(usage()); + break; + case 'a': + laddr = EARGF(usage()); + break; + case 'n': + n = strtoul(EARGF(usage()), nil, 0); + break; + case 's': + sleepms = strtoul(EARGF(usage()), nil, 0); + break; + case 'd': + case 'l': + flag[ARGC()] = 1; + break; + default: + usage(); + }ARGEND + if(argc != 0) + usage(); + + if(flag['l']){ + /* loopback */ + raddr = getenv("sysname"); + if(raddr == nil) + sysfatal("%s: can't find my address", argv0); + switch(fork()){ + case -1: + die(); + break; + case 0: + server(); + break; + default: + client(); + wait(); + break; + } + }else if(raddr != nil) + client(); + else + server(); + exits(nil); +} --- /sys/man/8/nettest Thu Jan 1 00:00:00 1970 +++ /sys/man/8/nettest Mon Dec 24 17:37:34 2012 @@ -0,0 +1,94 @@ +.TH NETTEST 8 +.SH NAME +nettest \- test network performance +.SH SYNOPSIS +.B nettest +.B -l +[ +.B -s +.I sleepms +][ +.B -n +.I nblocks +] +.br +.B nettest +[ +.B -a +.I addr +][ +.B -s +.I sleepms +] +.br +.B nettest +.B -r +.I raddr +.B -n +.I nblocks +.SH DESCRIPTION +.I Nettest +tests goodput of reliable, in-order transports +at full speed, and with receiver throttling. Both sender +and receiver do i/o in 8 KB chunks. +Goodput in MB/s and if throttled, the theoretical +maximum goodput in MB/s are reported. +.PP +As a client the options are +.TF "-s sleepms" +.PD 0 +.TP +.B "-r \fIraddr\fP" +remote address +.I addr +.TP +.B "-n \fInblocks\fP" +send +.I nblocks +8-KiB blocks +.PP +Server options are +.TF "-s sleepms" +.PD 0 +.TP +.B "-a \fIaddr\fP" +listen on network address +.I addr +.TP +.B "-s \fIsleepms\fP" +sleep +.I sleepms +between 8KiB reads +.PP +In loopback mode the options are +.TF "-s sleepms" +.PD 0 +.TP +.B -l +specify loopback mode +.TP +.B "-s \fIsleepms\fP" +sleep +.I sleepms +between 8KiB reads +.TP +.B "-n \fInblocks\fP" +send +.I nblocks +8-KiB blocks +.SH EXAMPLE +To test a reader limited to 8MB/s +.IP +.EX +nettest -l -n 5000 -s 1 +.EE +.PP +To do the same test using two independent IP stacks +.IP +.EX +nettest -s 1 -a /net.a/tcp!* & +nettest -n 5000 -r /net.b/tcp!mymachine-neta +.EE +nettest +.SH "SEE ALSO" +.IR ping (8)