]> sjero.net Git - iperf/commitdiff
TCP Congestion Control Module via options
authorIan McDonald <ian.mcdonald@jandi.co.nz>
Tue, 24 Feb 2009 19:42:45 +0000 (20:42 +0100)
committerGerrit Renker <gerrit@erg.abdn.ac.uk>
Tue, 24 Feb 2009 19:42:45 +0000 (20:42 +0100)
This adds plug-able TCP congestion control support to iperf.

include/Reporter.h
include/Settings.hpp
include/headers.h
include/version.h
src/Locale.c
src/PerfSocket.cpp
src/ReportDefault.c
src/Reporter.c
src/Settings.cpp

index db3defe5ca605ffc8e996d5469b8dedfb6013ff3..1dbb22c0ea52447a95f8dfeaa5dd84fed5cda081 100644 (file)
@@ -106,6 +106,7 @@ typedef struct Transfer_Info {
     u_char mTTL;                    // -T
     char   mUDP;
     char   free;
     u_char mTTL;                    // -T
     char   mUDP;
     char   free;
+    char  *congAlgo;                // -A
 } Transfer_Info;
 
 typedef struct Connection_Info {
 } Transfer_Info;
 
 typedef struct Connection_Info {
index 3a9fa2a9592302c8eccfd35e412555f73b0c20b3..0fe99212ca23eed93d34de405d9b2d3ed5802f00 100644 (file)
@@ -198,6 +198,7 @@ typedef struct thread_Settings {
     // chars
     char   mFormat;                 // -f
     int    mTTL;                    // -T
     // chars
     char   mFormat;                 // -f
     int    mTTL;                    // -T
+    char  *congAlgo;                // -A
     char pad1[2];
     // structs or miscellaneous
     struct sockaddr_storage peer;   // remote part of socket
     char pad1[2];
     // structs or miscellaneous
     struct sockaddr_storage peer;   // remote part of socket
index 0bc12dbf745550483f9f1d03cb479c9780efce5e..0ef1c2e231e53d1faa1da290fc0f5df528baf65f 100644 (file)
@@ -147,6 +147,11 @@ typedef uintmax_t max_size_t;
     #define SHUT_RDWR 2
 #endif // SHUT_RD
 
     #define SHUT_RDWR 2
 #endif // SHUT_RD
 
+/* Plug-able TCP congestion control algorithm */
+#ifndef TCP_CONGESTION
+#define TCP_CONGESTION  13      /* include/linux/tcp.h */
+#endif
+
 /* DCCP-specific definitions */
 #include <linux/dccp.h>
 #ifndef SOCK_DCCP
 /* DCCP-specific definitions */
 #include <linux/dccp.h>
 #ifndef SOCK_DCCP
index f8f2c7df2fb5ab69d6e6e193b4d91c6d9297c7ca..1e659138bde8d49ef616f5ce8833be4c337bc9f2 100644 (file)
@@ -1,2 +1,2 @@
-#define IPERF_VERSION "2.0.2 with support for DCCP"
+#define IPERF_VERSION "2.0.2 with support for DCCP and TCP CC"
 #define IPERF_VERSION_DATE "20th Jan 2009"
 #define IPERF_VERSION_DATE "20th Jan 2009"
index acad49c7809257dccb2d5f2fb0e22e640783be3e..838783261fc8fcf0d02b0f60b03dffd39b7b821e 100644 (file)
@@ -81,6 +81,7 @@ Client/Server:\n\
   -u, --udp                use UDP as transport protocol\n\
   -d, --dccp               use DCCP as transport protocol\n\
   -w, --window    #[KM]    TCP window size (socket buffer size)\n\
   -u, --udp                use UDP as transport protocol\n\
   -d, --dccp               use DCCP as transport protocol\n\
   -w, --window    #[KM]    TCP window size (socket buffer size)\n\
+  -A, --algorithm          set TCP congestion control algorithm\n\
   -B, --bind      <host>   bind to <host>, an interface or multicast address\n\
   -C, --compatibility      for use with older versions does not sent extra msgs\n\
   -M, --mss       #        set TCP maximum segment size (MTU - 40 bytes)\n\
   -B, --bind      <host>   bind to <host>, an interface or multicast address\n\
   -C, --compatibility      for use with older versions does not sent extra msgs\n\
   -M, --mss       #        set TCP maximum segment size (MTU - 40 bytes)\n\
index 2c169014b080d8bff8fb0bf9416427a6d2d646c1..04a68b9583ced9bb44de5a7f070fdebbcd76c660 100644 (file)
@@ -126,6 +126,13 @@ void SetSocketOptions( thread_Settings *inSettings )
             WARN_errno( rc == SOCKET_ERROR, "setsockopt TCP_NODELAY" );
         }
 #endif
             WARN_errno( rc == SOCKET_ERROR, "setsockopt TCP_NODELAY" );
         }
 #endif
+        if ( inSettings->congAlgo ) {
+            len = strlen( inSettings->congAlgo );
+            rc = setsockopt( inSettings->mSock, IPPROTO_TCP, TCP_CONGESTION,
+                             inSettings->congAlgo , len );
+            WARN_errno( rc == SOCKET_ERROR, "setsockopt TCP_CONGESTION" );
+        }
+
     } else {
         rc = set_buffer_sock_size(inSettings->mSock, inSettings->mWinSize,
                                   inSettings->mThreadMode == kMode_Client);
     } else {
         rc = set_buffer_sock_size(inSettings->mSock, inSettings->mWinSize,
                                   inSettings->mThreadMode == kMode_Client);
index dcb38527476d9ed3c71d14580409568ff39cf8eb..150df1069d333e5c12557cae9636edf870262580 100644 (file)
@@ -204,6 +204,24 @@ void reporter_reportsettings( ReporterData *data ) {
         printf( warn_window_requested, buffer );
     }
     printf( "\n" );
         printf( warn_window_requested, buffer );
     }
     printf( "\n" );
+
+    if (data->mProtocol == kProto_TCP) {
+        char *cong_requested = data->info.congAlgo,
+              cong[64];
+        Socklen_t len = sizeof(cong);
+
+        if (getsockopt(data->info.transferID, IPPROTO_TCP, TCP_CONGESTION, cong, &len) < 0) {
+            fprintf(stderr, "WARNING: cannot determine TCP congestion control algorithm  (err: %d %s)\n",
+                           errno, strerror(errno));
+        } else {
+            printf("TCP congestion control algorithm: %s", cong[0] == '\0' ? "default" : cong);
+
+          if (data->info.congAlgo && strcmp(cong, data->info.congAlgo))
+            printf(" (NOT \"%s\"!)", data->info.congAlgo);
+          printf("\n");
+        }
+    }
+
     printf( seperator_line );
 }
 
     printf( seperator_line );
 }
 
index c5eff5c35ba5a48e3610073272ea588db7a9a7dd..f3bd21930e933b5c639af47c475e89a9f5e61559 100644 (file)
@@ -223,6 +223,7 @@ ReportHeader* InitReport( thread_Settings *agent ) {
             data->info.transferID = agent->mSock;
             data->info.groupID = (agent->multihdr != NULL ? agent->multihdr->groupID 
                                                           : -1);
             data->info.transferID = agent->mSock;
             data->info.groupID = (agent->multihdr != NULL ? agent->multihdr->groupID 
                                                           : -1);
+            data->info.congAlgo = agent->congAlgo;
             data->type = TRANSFER_REPORT;
             if ( agent->mInterval != 0.0 ) {
                 struct timeval *interval = &data->intervalTime;
             data->type = TRANSFER_REPORT;
             if ( agent->mInterval != 0.0 ) {
                 struct timeval *interval = &data->intervalTime;
@@ -260,6 +261,7 @@ ReportHeader* InitReport( thread_Settings *agent ) {
                 data = &reporthdr->report;
                 data->info.transferID = agent->mSock;
                 data->info.groupID = -1;
                 data = &reporthdr->report;
                 data->info.transferID = agent->mSock;
                 data->info.groupID = -1;
+                data->info.congAlgo = agent->congAlgo;
             } else {
                 FAIL(1, "Out of Memory!!\n", agent);
             }
             } else {
                 FAIL(1, "Out of Memory!!\n", agent);
             }
@@ -445,6 +447,7 @@ void ReportSettings( thread_Settings *agent ) {
             data->mMcastIface = agent->mMcastIface;
             data->info.mFormat = agent->mFormat;
             data->info.mTTL = agent->mTTL;
             data->mMcastIface = agent->mMcastIface;
             data->info.mFormat = agent->mFormat;
             data->info.mTTL = agent->mTTL;
+            data->info.congAlgo = agent->congAlgo;
             data->connection.peer = agent->peer;
             data->connection.local = agent->local;
     
             data->connection.peer = agent->peer;
             data->connection.local = agent->local;
     
index 549a9cca9d7523afb8c88e31e72901e3b16f8124..4034158cf261d326965afb4d5496de18700871a4 100644 (file)
@@ -107,6 +107,7 @@ const struct option long_options[] =
 {"reportstyle",required_argument, NULL, 'y'},
 
 // more esoteric options
 {"reportstyle",required_argument, NULL, 'y'},
 
 // more esoteric options
+{"algorithm",  required_argument, NULL, 'A'},
 {"bind",       required_argument, NULL, 'B'},
 {"compatibility",    no_argument, NULL, 'C'},
 {"daemon",           no_argument, NULL, 'D'},
 {"bind",       required_argument, NULL, 'B'},
 {"compatibility",    no_argument, NULL, 'C'},
 {"daemon",           no_argument, NULL, 'D'},
@@ -152,6 +153,7 @@ const struct option env_options[] =
 {"IPERF_REPORTSTYLE",required_argument, NULL, 'y'},
 
 // more esoteric options
 {"IPERF_REPORTSTYLE",required_argument, NULL, 'y'},
 
 // more esoteric options
+{"IPERF_CC",         required_argument, NULL, 'A'},
 {"IPERF_BIND",       required_argument, NULL, 'B'},
 {"IPERF_COMPAT",           no_argument, NULL, 'C'},
 {"IPERF_DAEMON",           no_argument, NULL, 'D'},
 {"IPERF_BIND",       required_argument, NULL, 'B'},
 {"IPERF_COMPAT",           no_argument, NULL, 'C'},
 {"IPERF_DAEMON",           no_argument, NULL, 'D'},
@@ -172,7 +174,7 @@ const struct option env_options[] =
 #define SHORT_OPTIONS()
 
 const char short_options[] =
 #define SHORT_OPTIONS()
 
 const char short_options[] =
-      "12b::c:df:hi:j:l:mn:o:p:rst:uvw:x:y:B:CDF:IJ:L:M:NP:RS:T:UV:W";
+      "12b::c:df:hi:j:l:mn:o:p:rst:uvw:x:y:A:B:CDF:IJ:L:M:NP:RS:T:UV:W";
 
 /* -------------------------------------------------------------------
  * defaults
 
 /* -------------------------------------------------------------------
  * defaults
@@ -542,6 +544,11 @@ void Settings_Interpret( char option, const char *optarg, thread_Settings *mExtS
 
 
             // more esoteric options
 
 
             // more esoteric options
+        case 'A': // set TCP congestion control algorithm
+            mExtSettings->congAlgo = new char[ strlen( optarg ) + 1 ];
+            strcpy( mExtSettings->congAlgo, optarg );
+            break;
+
         case 'B': // specify bind address
             mExtSettings->mLocalhost = new char[ strlen( optarg ) + 1 ];
             strcpy( mExtSettings->mLocalhost, optarg );
         case 'B': // specify bind address
             mExtSettings->mLocalhost = new char[ strlen( optarg ) + 1 ];
             strcpy( mExtSettings->mLocalhost, optarg );