=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tcpbench/tcpbench.c,v retrieving revision 1.23 retrieving revision 1.24 diff -u -r1.23 -r1.24 --- src/usr.bin/tcpbench/tcpbench.c 2011/08/20 11:11:30 1.23 +++ src/usr.bin/tcpbench/tcpbench.c 2011/08/23 04:13:38 1.24 @@ -65,6 +65,7 @@ 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 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 @@ 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 @@ 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 IPV6_TCLASS"); + } /* Alloc client structure and register reading callback */ if ((sc = calloc(1, sizeof(*sc))) == NULL) err(1, "calloc"); @@ -729,6 +741,16 @@ 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 IPV6_TCLASS"); + } if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) warn("reuse port"); @@ -821,6 +843,16 @@ 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 IPV6_TCLASS"); + } if (ptb->Vflag) { if (setsockopt(sock, SOL_SOCKET, SO_RTABLE, &ptb->Vflag, sizeof(ptb->Vflag)) == -1) { @@ -875,6 +907,54 @@ 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 @@ 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 @@ 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: