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 );