Hi, So here is the final version using -T with IPv6 with some points addressed by jmc@ in the manual.
ok to commit ? Index: tcpbench.1 =================================================================== RCS file: /cvs/src/usr.bin/tcpbench/tcpbench.1,v retrieving revision 1.12 diff -d -u -p -w -r1.12 tcpbench.1 --- tcpbench.1 16 Mar 2011 08:06:10 -0000 1.12 +++ tcpbench.1 21 Aug 2011 22:04:58 -0000 @@ -31,6 +31,7 @@ .Op Fl p Ar port .Op Fl r Ar interval .Op Fl S Ar space +.Op Fl T Ar toskeyword .Op Fl V Ar rtable .Ar hostname .Nm @@ -41,6 +42,7 @@ .Op Fl k Ar kvars .Op Fl p Ar port .Op Fl r Ar interval +.Op Fl T Ar toskeyword .Op Fl S Ar space .Op Fl V Ar rtable .Ek @@ -105,6 +107,21 @@ connections. It defaults to using TCP if .Fl u is not specified. +.It Fl T Ar toskeyword +Change the IPv4 TOS or IPv6 TCLASS value. +.Ar toskeyword +may be one of +.Ar critical , +.Ar inetcontrol , +.Ar lowdelay , +.Ar netcontrol , +.Ar throughput , +.Ar reliability , +or one of the DiffServ Code Points: +.Ar ef , +.Ar af11 ... af43 , +.Ar cs0 ... cs7 ; +or a number in either hex or decimal. .It Fl u Use UDP instead of TCP; this must be specified on both the client and the server. Index: tcpbench.c =================================================================== RCS file: /cvs/src/usr.bin/tcpbench/tcpbench.c,v retrieving revision 1.23 diff -d -u -p -w -r1.23 tcpbench.c --- tcpbench.c 20 Aug 2011 11:11:30 -0000 1.23 +++ tcpbench.c 21 Aug 2011 05:42:21 -0000 @@ -65,6 +65,7 @@ struct { int Sflag; /* Socket buffer size (tcp mode) */ u_int rflag; /* Report rate (ms) */ int sflag; /* True if server */ + int Tflag; /* ToS if != -1 */ int vflag; /* Verbose */ int uflag; /* UDP mode */ kvm_t *kvmh; /* Kvm handler */ @@ -113,7 +114,7 @@ static void client_init(struct addrinfo static int clock_gettime_tv(clockid_t, struct timeval *); static void udp_server_handle_sc(int, short, void *); static void udp_process_slice(int, short, void *); - +static int map_tos(char *, int *); /* * We account the mainstats here, that is the stats * for all connections, all variables starting with slice @@ -173,9 +174,10 @@ usage(void) fprintf(stderr, "usage: tcpbench -l\n" " tcpbench [-uv] [-B buf] [-k kvars] [-n connections] [-p port]\n" - " [-r interval] [-S space] [-V rtable] hostname\n" + " [-r interval] [-S space] [-T toskeyword] [-V rtable]\n" + " hostname\n" " tcpbench -s [-uv] [-B buf] [-k kvars] [-p port]\n" - " [-r interval] [-S space] [-V rtable]\n"); + " [-r interval] [-S space] [-T toskeyword] [-V rtable]\n"); exit(1); } @@ -680,6 +682,16 @@ again: r |= O_NONBLOCK; if (fcntl(sock, F_SETFL, r) == -1) err(1, "fcntl(F_SETFL, O_NONBLOCK)"); + if (ptb->Tflag != -1 && ss.ss_family == AF_INET) { + if (setsockopt(sock, IPPROTO_IP, IP_TOS, + &ptb->Tflag, sizeof(ptb->Tflag))) + err(1, "setsockopt IP_TOS"); + } + if (ptb->Tflag != -1 && ss.ss_family == AF_INET6) { + if (setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS, + &ptb->Tflag, sizeof(ptb->Tflag))) + err(1, "setsockopt IPV_TCLASS"); + } /* Alloc client structure and register reading callback */ if ((sc = calloc(1, sizeof(*sc))) == NULL) err(1, "calloc"); @@ -729,6 +741,16 @@ server_init(struct addrinfo *aitop, stru err(1, "setsockopt SO_RTABLE"); } } + if (ptb->Tflag != -1 && ai->ai_family == AF_INET) { + if (setsockopt(sock, IPPROTO_IP, IP_TOS, + &ptb->Tflag, sizeof(ptb->Tflag))) + err(1, "setsockopt IP_TOS"); + } + if (ptb->Tflag != -1 && ai->ai_family == AF_INET6) { + if (setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS, + &ptb->Tflag, sizeof(ptb->Tflag))) + err(1, "setsockopt IPV_TCLASS"); + } if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) warn("reuse port"); @@ -821,6 +843,16 @@ client_init(struct addrinfo *aitop, int warn("socket"); continue; } + if (ptb->Tflag != -1 && ai->ai_family == AF_INET) { + if (setsockopt(sock, IPPROTO_IP, IP_TOS, + &ptb->Tflag, sizeof(ptb->Tflag))) + err(1, "setsockopt IP_TOS"); + } + if (ptb->Tflag != -1 && ai->ai_family == AF_INET6) { + if (setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS, + &ptb->Tflag, sizeof(ptb->Tflag))) + err(1, "setsockopt IPV_TCLASS"); + } if (ptb->Vflag) { if (setsockopt(sock, SOL_SOCKET, SO_RTABLE, &ptb->Vflag, sizeof(ptb->Vflag)) == -1) { @@ -875,6 +907,54 @@ client_init(struct addrinfo *aitop, int fprintf(stderr, "%u connections established\n", nconn); } +static int +map_tos(char *s, int *val) +{ + /* DiffServ Codepoints and other TOS mappings */ + const struct toskeywords { + const char *keyword; + int val; + } *t, toskeywords[] = { + { "af11", IPTOS_DSCP_AF11 }, + { "af12", IPTOS_DSCP_AF12 }, + { "af13", IPTOS_DSCP_AF13 }, + { "af21", IPTOS_DSCP_AF21 }, + { "af22", IPTOS_DSCP_AF22 }, + { "af23", IPTOS_DSCP_AF23 }, + { "af31", IPTOS_DSCP_AF31 }, + { "af32", IPTOS_DSCP_AF32 }, + { "af33", IPTOS_DSCP_AF33 }, + { "af41", IPTOS_DSCP_AF41 }, + { "af42", IPTOS_DSCP_AF42 }, + { "af43", IPTOS_DSCP_AF43 }, + { "critical", IPTOS_PREC_CRITIC_ECP }, + { "cs0", IPTOS_DSCP_CS0 }, + { "cs1", IPTOS_DSCP_CS1 }, + { "cs2", IPTOS_DSCP_CS2 }, + { "cs3", IPTOS_DSCP_CS3 }, + { "cs4", IPTOS_DSCP_CS4 }, + { "cs5", IPTOS_DSCP_CS5 }, + { "cs6", IPTOS_DSCP_CS6 }, + { "cs7", IPTOS_DSCP_CS7 }, + { "ef", IPTOS_DSCP_EF }, + { "inetcontrol", IPTOS_PREC_INTERNETCONTROL }, + { "lowdelay", IPTOS_LOWDELAY }, + { "netcontrol", IPTOS_PREC_NETCONTROL }, + { "reliability", IPTOS_RELIABILITY }, + { "throughput", IPTOS_THROUGHPUT }, + { NULL, -1 }, + }; + + for (t = toskeywords; t->keyword != NULL; t++) { + if (strcmp(s, t->keyword) == 0) { + *val = t->val; + return (1); + } + } + + return (0); +} + int main(int argc, char **argv) { @@ -898,9 +978,10 @@ main(int argc, char **argv) ptb->kvmh = NULL; ptb->kvars = NULL; ptb->rflag = DEFAULT_STATS_INTERVAL; + ptb->Tflag = -1; nconn = 1; - while ((ch = getopt(argc, argv, "B:hlk:n:p:r:sS:uvV:")) != -1) { + while ((ch = getopt(argc, argv, "B:hlk:n:p:r:sS:T:uvV:")) != -1) { switch (ch) { case 'l': list_kvars(); @@ -956,6 +1037,19 @@ main(int argc, char **argv) break; case 'u': ptb->uflag = 1; + break; + case 'T': + if (map_tos(optarg, &ptb->Tflag)) + break; + errstr = NULL; + if (strlen(optarg) > 1 && optarg[0] == '0' && + optarg[1] == 'x') + ptb->Tflag = (int)strtol(optarg, NULL, 16); + else + ptb->Tflag = (int)strtonum(optarg, 0, 255, + &errstr); + if (ptb->Tflag == -1 || ptb->Tflag > 255 || errstr) + errx(1, "illegal tos value %s", optarg); break; case 'h': default: