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:

Reply via email to