From f1b0eab7804a32863e9881d17d704d1dbaca17cb Mon Sep 17 00:00:00 2001 From: "Christiano F. Haesbaert" Date: Tue, 23 Aug 2011 04:13:39 +0000 Subject: Allow TOS/TCLASS to be set with -T, accept the same keywords as in pf.conf. ok mcbride@ djm@ 'fine from me' jmc@ --- usr.bin/tcpbench/tcpbench.1 | 21 ++++++++- usr.bin/tcpbench/tcpbench.c | 102 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 117 insertions(+), 6 deletions(-) (limited to 'usr.bin') diff --git a/usr.bin/tcpbench/tcpbench.1 b/usr.bin/tcpbench/tcpbench.1 index df0e8ebb89f..9f9294bca61 100644 --- a/usr.bin/tcpbench/tcpbench.1 +++ b/usr.bin/tcpbench/tcpbench.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tcpbench.1,v 1.12 2011/03/16 08:06:10 jmc Exp $ +.\" $OpenBSD: tcpbench.1,v 1.13 2011/08/23 04:13:37 haesbaert Exp $ .\" .\" Copyright (c) 2008 Damien Miller .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: March 16 2011 $ +.Dd $Mdocdate: August 23 2011 $ .Dt TCPBENCH 1 .Os .Sh NAME @@ -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. diff --git a/usr.bin/tcpbench/tcpbench.c b/usr.bin/tcpbench/tcpbench.c index a25314882d1..07b628b6063 100644 --- a/usr.bin/tcpbench/tcpbench.c +++ b/usr.bin/tcpbench/tcpbench.c @@ -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 *, int, struct statctx *); 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 IPV6_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, struct statctx *udp_sc) 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 @@ client_init(struct addrinfo *aitop, int nconn, struct statctx *udp_sc) 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 @@ client_init(struct addrinfo *aitop, int nconn, struct statctx *udp_sc) 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(); @@ -957,6 +1038,19 @@ main(int argc, char **argv) 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: usage(); -- cgit v1.2.3