From 4a61594d8e95e2d9662816ae595f8257b69012eb Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 24 Feb 2009 20:50:23 +0100 Subject: [PATCH] Bring DiffServ codepoint support up-to-date The -S/--tos argument currently only supports IPv4 TOS, for IPv6 a different socket option is used. Both uses are unified through the definition of the DiffServ codepoint in RFC 2474 (the two unused bits are used for ECN marking and can not normally be influenced via socket options). This patch * adds (conditional) support for IPv4/v6 socket options to set the DSCP; * adds an extra type argument mSockAF to remember the address family of mSock (to allow address-family-dependent TOS); * fixes a ToDo to support base-2 numbers for the DSCP string; * validates the numeric argument; * replaces the older IPv4-based `--tos' option with `--dscp' and the environment variable `IPERF_TOS' with `IPERF_DSCP'. The argument types that are now supported are # iperf -c server -S 0x1f # hex string # iperf -c server -S 017 # octal string (=0xf) # iperf -c server -S 42 # decimal string # iperf -c server -S 011011 # binary string (must be 6 digits) --- src/Locale.c | 1 + src/PerfSocket.cpp | 18 +++++++++++++----- src/Settings.cpp | 23 ++++++++++++++++------- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/Locale.c b/src/Locale.c index ade47f0..cc02522 100644 --- a/src/Locale.c +++ b/src/Locale.c @@ -106,6 +106,7 @@ Client specific:\n\ -I, --stdin input the data to be transmitted from stdin\n\ -L, --listenport # port to receive bidirectional tests back on\n\ -P, --parallel # number of parallel client threads to run\n\ + -S --dscp # set the 6-bit IPv4/v6 DiffServ codepoint\n\ -T, --ttl # time-to-live, for multicast (default 1)\n\ \n\ Miscellaneous:\n\ diff --git a/src/PerfSocket.cpp b/src/PerfSocket.cpp index 04a68b9..63e97ff 100644 --- a/src/PerfSocket.cpp +++ b/src/PerfSocket.cpp @@ -99,14 +99,22 @@ void SetSocketOptions( thread_Settings *inSettings ) } - // set IP TOS (type-of-service) field -#ifdef IP_TOS + // Set the DiffServ codepoint for IPv4 TOS or IPv6 traffic class if ( inSettings->mTOS > 0 ) { val = inSettings->mTOS; - rc = setsockopt( inSettings->mSock, IPPROTO_IP, IP_TOS, &val, len ); - WARN_errno( rc == SOCKET_ERROR, "setsockopt IP_TOS" ); - } +#if defined(IP_TOS) + if ( inSettings->mSockAF == AF_INET ) { + rc = setsockopt( inSettings->mSock, IPPROTO_IP, IP_TOS, &val, len ); + WARN_errno( rc == SOCKET_ERROR, "setsockopt IP_TOS" ); + } #endif +#if defined(IPV6_TCLASS) + if ( inSettings->mSockAF == AF_INET6 ) { + rc = setsockopt( inSettings->mSock, IPPROTO_IPV6, IPV6_TCLASS, &val, len ); + WARN_errno( rc == SOCKET_ERROR, "setsockopt IPV6_TCLASS" ); + } +#endif + } // TCP-specific options diff --git a/src/Settings.cpp b/src/Settings.cpp index 4034158..15b5ccd 100644 --- a/src/Settings.cpp +++ b/src/Settings.cpp @@ -118,7 +118,7 @@ const struct option long_options[] = {"listenport", required_argument, NULL, 'L'}, {"parallel", required_argument, NULL, 'P'}, {"remove", no_argument, NULL, 'R'}, -{"tos", required_argument, NULL, 'S'}, +{"dscp", required_argument, NULL, 'S'}, {"ttl", required_argument, NULL, 'T'}, {"single_udp", no_argument, NULL, 'U'}, {"ipv6_domian", no_argument, NULL, 'V'}, @@ -163,7 +163,7 @@ const struct option env_options[] = {"IPERF_NODELAY", no_argument, NULL, 'N'}, {"IPERF_LISTENPORT", required_argument, NULL, 'L'}, {"IPERF_PARALLEL", required_argument, NULL, 'P'}, -{"IPERF_TOS", required_argument, NULL, 'S'}, +{"IPERF_DSCP", required_argument, NULL, 'S'}, {"IPERF_TTL", required_argument, NULL, 'T'}, {"IPERF_SINGLE_UDP", no_argument, NULL, 'U'}, {"IPERF_IPV6_DOMAIN", no_argument, NULL, 'V'}, @@ -626,11 +626,20 @@ void Settings_Interpret( char option, const char *optarg, thread_Settings *mExtS setRemoveService( mExtSettings ); break; - case 'S': // IP type-of-service - // TODO use a function that understands base-2 - // the zero base here allows the user to specify - // "0x#" hex, "0#" octal, and "#" decimal numbers - mExtSettings->mTOS = strtol( optarg, NULL, 0 ); + case 'S': + // Convert into IPv4/v6 6-bit DiffServ codepoint. If string + // - consists of six 0/1 digits, it is seen as binary number; + // - is preceded by `0x', it is interpreted as hex number; + // - is preceded by `0', it is interpreted as octal number; + // - otherwise it is interpreted as decimal number. + // The maximum possible 6-bit value is 252 (0xfc). + if ( strspn(optarg, "01") == 6 ) + mExtSettings->mTOS = strtol(optarg, NULL, 2); + else + mExtSettings->mTOS = strtol(optarg, NULL, 0); + if ( mExtSettings->mTOS < 0 || mExtSettings->mTOS > 0xfc ) + die("Invalid DiffServ codepoint %s", optarg); + mExtSettings->mTOS <<= 2; break; case 'T': // time-to-live for multicast -- 2.39.2