From 840e9078558547dbd9e2ed33670c3e116e718897 Mon Sep 17 00:00:00 2001 From: Ian McDonald Date: Tue, 24 Feb 2009 20:42:45 +0100 Subject: [PATCH] TCP Congestion Control Module via options This adds plug-able TCP congestion control support to iperf. --- include/Reporter.h | 1 + include/Settings.hpp | 1 + include/headers.h | 5 +++++ include/version.h | 2 +- src/Locale.c | 1 + src/PerfSocket.cpp | 7 +++++++ src/ReportDefault.c | 18 ++++++++++++++++++ src/Reporter.c | 3 +++ src/Settings.cpp | 9 ++++++++- 9 files changed, 45 insertions(+), 2 deletions(-) diff --git a/include/Reporter.h b/include/Reporter.h index db3defe..1dbb22c 100644 --- a/include/Reporter.h +++ b/include/Reporter.h @@ -106,6 +106,7 @@ typedef struct Transfer_Info { u_char mTTL; // -T char mUDP; char free; + char *congAlgo; // -A } Transfer_Info; typedef struct Connection_Info { diff --git a/include/Settings.hpp b/include/Settings.hpp index 3a9fa2a..0fe9921 100644 --- a/include/Settings.hpp +++ b/include/Settings.hpp @@ -198,6 +198,7 @@ typedef struct thread_Settings { // chars char mFormat; // -f int mTTL; // -T + char *congAlgo; // -A char pad1[2]; // structs or miscellaneous struct sockaddr_storage peer; // remote part of socket diff --git a/include/headers.h b/include/headers.h index 0bc12db..0ef1c2e 100644 --- a/include/headers.h +++ b/include/headers.h @@ -147,6 +147,11 @@ typedef uintmax_t max_size_t; #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 #ifndef SOCK_DCCP diff --git a/include/version.h b/include/version.h index f8f2c7d..1e65913 100644 --- a/include/version.h +++ b/include/version.h @@ -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" diff --git a/src/Locale.c b/src/Locale.c index acad49c..8387832 100644 --- a/src/Locale.c +++ b/src/Locale.c @@ -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\ + -A, --algorithm set TCP congestion control algorithm\n\ -B, --bind bind to , 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\ diff --git a/src/PerfSocket.cpp b/src/PerfSocket.cpp index 2c16901..04a68b9 100644 --- a/src/PerfSocket.cpp +++ b/src/PerfSocket.cpp @@ -126,6 +126,13 @@ void SetSocketOptions( thread_Settings *inSettings ) 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); diff --git a/src/ReportDefault.c b/src/ReportDefault.c index dcb3852..150df10 100644 --- a/src/ReportDefault.c +++ b/src/ReportDefault.c @@ -204,6 +204,24 @@ void reporter_reportsettings( ReporterData *data ) { 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 ); } diff --git a/src/Reporter.c b/src/Reporter.c index c5eff5c..f3bd219 100644 --- a/src/Reporter.c +++ b/src/Reporter.c @@ -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.congAlgo = agent->congAlgo; 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->info.congAlgo = agent->congAlgo; } 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->info.congAlgo = agent->congAlgo; data->connection.peer = agent->peer; data->connection.local = agent->local; diff --git a/src/Settings.cpp b/src/Settings.cpp index 549a9cc..4034158 100644 --- a/src/Settings.cpp +++ b/src/Settings.cpp @@ -107,6 +107,7 @@ const struct option long_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'}, @@ -152,6 +153,7 @@ const struct option env_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'}, @@ -172,7 +174,7 @@ const struct option env_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 @@ -542,6 +544,11 @@ void Settings_Interpret( char option, const char *optarg, thread_Settings *mExtS // 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 ); -- 2.39.2