Hi,

I'm tinkering with ToS->CoS (802.1p) translation in vlan(4) so I
needed something to test, tcpbench seems to deserve a tos option.  

It uses the same map_option() from pfctl with some minor tweeks.
So it accepts decimal, hexadecimal, critical, lowdelay, af11...

Option chosen was -t, couldn't find anything related in other programs.

Index: usr.bin/tcpbench/tcpbench.c
===================================================================
RCS file: /cvs/src/usr.bin/tcpbench/tcpbench.c,v
retrieving revision 1.22
diff -d -u -p -w -r1.22 tcpbench.c
--- usr.bin/tcpbench/tcpbench.c 21 Jun 2011 17:31:07 -0000      1.22
+++ usr.bin/tcpbench/tcpbench.c 18 Aug 2011 13:45:11 -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);
 }
 
@@ -679,6 +681,11 @@ 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");
+       }
        /* Alloc client structure and register reading callback */
        if ((sc = calloc(1, sizeof(*sc))) == NULL)
                err(1, "calloc");
@@ -728,6 +735,11 @@ 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 (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
                    &on, sizeof(on)) == -1)
                        warn("reuse port");
@@ -820,6 +832,11 @@ 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->Vflag) {
                                if (setsockopt(sock, SOL_SOCKET, SO_RTABLE,
                                    &ptb->Vflag, sizeof(ptb->Vflag)) == -1) {
@@ -874,6 +891,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)
 {
@@ -897,9 +962,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();
@@ -955,6 +1021,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:
Index: usr.bin/tcpbench/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
--- usr.bin/tcpbench/tcpbench.1 16 Mar 2011 08:06:10 -0000      1.12
+++ usr.bin/tcpbench/tcpbench.1 18 Aug 2011 06:42:35 -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,22 @@ connections.
 It defaults to using TCP if
 .Fl u
 is not specified.
+.It Fl t Ar toskeyword
+Change IPv4 TOS 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 one number in either hex or decimal.
+This option only applies to AF_INET sockets.
 .It Fl u
 Use UDP instead of TCP; this must be specified on both the client
 and the server.

Reply via email to