Re: Usermode per-flow selection of congestion control algorithm


here is the patch

2006/3/15, Angelo P. Castellani <angelo.castellani+iperf --at-- gmail.com>:
Starting with linux kernel 2.6.15, users can choose which congestion control algorithm should be used for a TCP connection.

Here is a patch that adds an iperf parameter to use that feature.

Regards,
Angelo P. Castellani

diff -rdu ../iperf-2.0.2/include/headers.h ./include/headers.h
--- ../iperf-2.0.2/include/headers.h	2005-05-03 17:55:52.000000000 +0200
+++ ./include/headers.h	2006-03-14 15:30:11.000000000 +0100
@@ -193,6 +193,11 @@
     #define SHUT_RDWR 2
 #endif // SHUT_RD
 
+#ifndef TCP_CONGESTION
+    #define TCP_CONGESTION             13      /* Congestion control algorithm */
+#endif // TCP_CONGESTION
+
+
 #endif /* HEADERS_H */
 
 
diff -rdu ../iperf-2.0.2/include/Locale.h ./include/Locale.h
--- ../iperf-2.0.2/include/Locale.h	2005-05-02 22:09:26.000000000 +0200
+++ ./include/Locale.h	2006-03-14 16:30:27.000000000 +0100
@@ -98,6 +98,10 @@
 
 extern const char window_default[];
 
+extern const char tcp_cong_algo[];
+
+extern const char unknown_tcp_cong_algo[];
+
 extern const char wait_server_threads[];
 
 /* -------------------------------------------------------------------
@@ -184,6 +188,8 @@
 
 extern const char warn_invalid_report[];
 
+extern const char warn_cong_requested[];
+
 #ifdef __cplusplus
 } /* end extern "C" */
 #endif
diff -rdu ../iperf-2.0.2/include/Reporter.h ./include/Reporter.h
--- ../iperf-2.0.2/include/Reporter.h	2005-05-02 22:09:26.000000000 +0200
+++ ./include/Reporter.h	2006-03-14 16:28:17.000000000 +0100
@@ -106,6 +106,7 @@
     u_char mTTL;                    // -T
     char   mUDP;
     char   free;
+    char*  congAlgo;
 } Transfer_Info;
 
 typedef struct Connection_Info {
diff -rdu ../iperf-2.0.2/include/Settings.hpp ./include/Settings.hpp
--- ../iperf-2.0.2/include/Settings.hpp	2005-05-02 22:09:26.000000000 +0200
+++ ./include/Settings.hpp	2006-03-14 15:22:01.000000000 +0100
@@ -173,6 +173,7 @@
 #if defined( HAVE_WIN32_THREAD )
     HANDLE mHandle;
 #endif
+    char *congAlgo;
 } thread_Settings;
 
 /*
diff -rdu ../iperf-2.0.2/src/Locale.c ./src/Locale.c
--- ../iperf-2.0.2/src/Locale.c	2005-05-02 22:09:27.000000000 +0200
+++ ./src/Locale.c	2006-03-14 16:16:10.000000000 +0100
@@ -225,6 +225,15 @@
 const char window_default[] =
 "(default)";
 
+const char tcp_cong_algo[] =
+"TCP congestion control algorithm";
+
+const char unknown_tcp_cong_algo[] =
+"*unknown*";
+
+const char warn_cong_requested[] =
+"REQUESTED:";
+
 const char wait_server_threads[] =
 "Waiting for server threads to complete. Interrupt again to force quit.\n";
 
diff -rdu ../iperf-2.0.2/src/PerfSocket.cpp ./src/PerfSocket.cpp
--- ../iperf-2.0.2/src/PerfSocket.cpp	2005-05-02 22:09:27.000000000 +0200
+++ ./src/PerfSocket.cpp	2006-03-14 16:47:15.000000000 +0100
@@ -138,6 +138,16 @@
             WARN_errno( rc == SOCKET_ERROR, "setsockopt TCP_NODELAY" );
         }
 #endif
+
+#ifdef TCP_CONGESTION
+        // set TCP congestion algorithm
+        if ( inSettings->congAlgo ) {
+            Socklen_t len = strlen( inSettings->congAlgo );
+            int rc = setsockopt( inSettings->mSock, IPPROTO_TCP, TCP_CONGESTION,
+                                 inSettings->congAlgo , len );
+            WARN_errno( rc == SOCKET_ERROR, "setsockopt TCP_CONGESTION" );
+        }
+#endif
     }
 }
 // end SetSocketOptions
diff -rdu ../iperf-2.0.2/src/ReportDefault.c ./src/ReportDefault.c
--- ../iperf-2.0.2/src/ReportDefault.c	2005-05-02 22:09:27.000000000 +0200
+++ ./src/ReportDefault.c	2006-03-14 16:47:07.000000000 +0100
@@ -180,7 +180,7 @@
                    toupper( data->info.mFormat));
     printf( "%s: %s", (isUDP( data ) ? 
                                 udp_buffer_size : tcp_window_size), buffer );
-
+                                
     if ( win_requested == 0 ) {
         printf( " %s", window_default );
     } else if ( win != win_requested ) {
@@ -189,6 +189,32 @@
         printf( warn_window_requested, buffer );
     }
     printf( "\n" );
+    
+#ifdef TCP_CONGESTION
+    if ( !isUDP( data ) ) {
+      char cong[64];
+      char *cong_requested = data->info.congAlgo;
+      Socklen_t len = sizeof(cong);
+      
+      int rc = getsockopt( data->info.transferID, IPPROTO_TCP, TCP_CONGESTION,
+                              cong, &len );
+                              
+      if ( rc == SOCKET_ERROR ) {
+        snprintf ( cong, sizeof(cong), "%s (err: %d %s)", unknown_tcp_cong_algo,
+                    errno, strerror(errno), data->info.transferID);
+      }
+      
+      printf( "%s: %s", tcp_cong_algo, cong );
+      
+      if ( cong_requested && strcmp(cong, cong_requested) ) {
+        printf(" %s %s", warn_cong_requested, cong_requested);
+      }
+      
+      printf("\n");
+      
+    }
+#endif
+
     printf( seperator_line );
 }
 
diff -rdu ../iperf-2.0.2/src/Reporter.c ./src/Reporter.c
--- ../iperf-2.0.2/src/Reporter.c	2005-05-02 22:09:27.000000000 +0200
+++ ./src/Reporter.c	2006-03-14 16:50:34.000000000 +0100
@@ -225,6 +225,7 @@
             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;
@@ -261,6 +262,7 @@
                 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);
             }
@@ -432,6 +434,7 @@
             ReporterData *data = &reporthdr->report;
             data->info.transferID = agent->mSock;
             data->info.groupID = -1;
+            data->info.congAlgo = agent->congAlgo;
             reporthdr->agentindex = -1;
             reporthdr->reporterindex = -1;
         
diff -rdu ../iperf-2.0.2/src/Settings.cpp ./src/Settings.cpp
--- ../iperf-2.0.2/src/Settings.cpp	2005-05-02 22:09:27.000000000 +0200
+++ ./src/Settings.cpp	2006-03-14 15:46:52.000000000 +0100
@@ -105,6 +105,7 @@
 {"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'},
@@ -148,6 +149,7 @@
 {"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'},
@@ -167,7 +169,7 @@
 
 #define SHORT_OPTIONS()
 
-const char short_options[] = "1b:c:df:hi:l:mn:o:p:rst:uvw:x:y:B:CDF:IL:M:NP:RS:T:UVW";
+const char short_options[] = "1b:c:df:hi:l:mn:o:p:rst:uvw:x:y:A:B:CDF:IL:M:NP:RS:T:UVW";
 
 /* -------------------------------------------------------------------
  * defaults
@@ -540,6 +542,11 @@
 
 
             // more esoteric options
+        case 'A': // specify congestion 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 );


Other Mailing lists | Author Index | Date Index | Subject Index | Thread Index