[PATCH] Server report for TCP connection
I've made a quick hack to iperf 2.0.2 to get server reports also on TCP connections.
I know it can be refined a lot and if I make further improvements I will make you know.
Regards,
Angelo P. Castellani
diff -rdu ../iperf-2.0.2/include/Client.hpp ./include/Client.hpp
--- ../iperf-2.0.2/include/Client.hpp 2005-05-02 22:09:26.000000000 +0200
+++ ./include/Client.hpp 2006-03-21 12:17:13.000000000 +0100
@@ -75,6 +75,7 @@
void Send( void );
void write_UDP_FIN( );
+ void wait_TCP_Report( );
// client connect
void Connect( );
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-21 12:17:48.000000000 +0100
@@ -195,6 +195,7 @@
void EndReport( ReportHeader *agent );
Transfer_Info* GetReport( ReportHeader *agent );
void ReportServerUDP( struct thread_Settings *agent, struct server_hdr *server );
+void ReportServerTCP( struct thread_Settings *agent, struct server_hdr *server );
void ReportSettings( struct thread_Settings *agent );
void ReportConnections( struct thread_Settings *agent );
diff -rdu ../iperf-2.0.2/include/Server.hpp ./include/Server.hpp
--- ../iperf-2.0.2/include/Server.hpp 2005-05-02 22:09:26.000000000 +0200
+++ ./include/Server.hpp 2006-03-21 12:17:07.000000000 +0100
@@ -72,6 +72,7 @@
void Run( void );
void write_UDP_AckFIN( );
+ void write_TCP_Report( );
static void Sig_Int( int inSigno );
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-21 11:43:16.000000000 +0100
@@ -173,6 +173,7 @@
#if defined( HAVE_WIN32_THREAD )
HANDLE mHandle;
#endif
+ bool mTCPReport; // -Z
} thread_Settings;
/*
diff -rdu ../iperf-2.0.2/src/Client.cpp ./src/Client.cpp
--- ../iperf-2.0.2/src/Client.cpp 2005-05-02 22:09:27.000000000 +0200
+++ ./src/Client.cpp 2006-03-21 12:38:04.000000000 +0100
@@ -255,6 +255,9 @@
} else {
write_UDP_FIN( );
}
+ } else if ( mSettings->mTCPReport ) {
+ // wait for server report
+ wait_TCP_Report();
}
DELETE_PTR( reportstruct );
EndReport( mSettings->reporthdr );
@@ -376,3 +379,41 @@
fprintf( stderr, warn_no_ack, mSettings->mSock, count );
}
// end write_UDP_FIN
+
+void Client::wait_TCP_Report( ) {
+ int rc;
+ fd_set readSet;
+ struct timeval timeout;
+ char SRep[sizeof(server_hdr)];
+ char* tmp_rep = SRep;
+
+ rc = shutdown(mSettings->mSock, SHUT_WR);
+ FAIL_errno( rc == SOCKET_ERROR, "shutdown", mSettings );
+
+wait:
+ // wait until the socket is readable, or our timeout expires
+
+ FD_ZERO( &readSet );
+ FD_SET( mSettings->mSock, &readSet );
+ timeout.tv_sec = 30;
+ timeout.tv_usec = 0;
+
+ rc = select( mSettings->mSock + 1, &readSet, NULL, NULL, &timeout );
+ FAIL_errno( rc == SOCKET_ERROR, "select", mSettings );
+
+ if ( rc != 0 ) {
+ // socket ready to read
+ int missing = sizeof(SRep) - (tmp_rep - SRep);
+ rc = read( mSettings->mSock, tmp_rep, missing );
+ //printf ("read %d out of %d\n", rc, missing );
+
+ WARN_errno( rc < 0, "read" );
+
+ if ( rc == missing ) {
+ ReportServerTCP( mSettings, (server_hdr*) SRep );
+ } else if ( rc >= 0 ) {
+ tmp_rep += rc;
+ goto wait;
+ }
+ }
+}
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-21 12:35:38.000000000 +0100
@@ -536,6 +536,64 @@
}
}
+void ReportServerTCP( thread_Settings *agent, server_hdr *server ) {
+ printf("flags: %d\n", ntohl(server->flags) & HEADER_VERSION1);
+ if ( (ntohl(server->flags) & HEADER_VERSION1) != 0 ) {
+ /*
+ * Create in one big chunk
+ */
+ ReportHeader *reporthdr = malloc( sizeof(ReportHeader) );
+ Transfer_Info *stats = &reporthdr->report.info;
+
+ if ( reporthdr != NULL ) {
+ stats->transferID = agent->mSock;
+ stats->groupID = (agent->multihdr != NULL ? agent->multihdr->groupID
+ : -1);
+ reporthdr->agentindex = -1;
+ reporthdr->reporterindex = -1;
+
+ reporthdr->report.type = SERVER_RELAY_REPORT;
+ reporthdr->report.mode = agent->mReportMode;
+ stats->mFormat = agent->mFormat;
+ stats->jitter = ntohl( server->jitter1 );
+ stats->jitter += ntohl( server->jitter2 ) / (double)rMillion;
+ stats->TotalLen = (((max_size_t) ntohl( server->total_len1 )) << 32) +
+ ntohl( server->total_len2 );
+ stats->startTime = 0;
+ stats->endTime = ntohl( server->stop_sec );
+ stats->endTime += ntohl( server->stop_usec ) / (double)rMillion;
+ stats->cntError = ntohl( server->error_cnt );
+ stats->cntOutofOrder = ntohl( server->outorder_cnt );
+ stats->cntDatagrams = ntohl( server->datagrams );
+ stats->mUDP = (char)kMode_Server;
+ reporthdr->report.connection.peer = agent->local;
+ reporthdr->report.connection.size_peer = agent->size_local;
+ reporthdr->report.connection.local = agent->peer;
+ reporthdr->report.connection.size_local = agent->size_peer;
+
+#ifdef HAVE_THREAD
+ /*
+ * Update the ReportRoot to include this report.
+ */
+ Condition_Lock( ReportCond );
+ reporthdr->next = ReportRoot;
+ ReportRoot = reporthdr;
+ Condition_Signal( &ReportCond );
+ Condition_Unlock( ReportCond );
+#else
+ /*
+ * Process the report in this thread
+ */
+ reporthdr->next = NULL;
+ process_report ( reporthdr );
+#endif
+ } else {
+ FAIL(1, "Out of Memory!!\n", agent);
+ }
+ }
+}
+
+
/*
* This function is called only when the reporter thread
* This function is the loop that the reporter thread processes
diff -rdu ../iperf-2.0.2/src/Server.cpp ./src/Server.cpp
--- ../iperf-2.0.2/src/Server.cpp 2005-05-02 22:09:27.000000000 +0200
+++ ./src/Server.cpp 2006-03-21 12:35:44.000000000 +0100
@@ -137,6 +137,8 @@
if ( isUDP( mSettings ) && !isMulticast( mSettings ) ) {
// send back an acknowledgement of the terminating datagram
write_UDP_AckFIN( );
+ } else {
+ write_TCP_Report( );
}
} else {
FAIL(1, "Out of memory! Closing server thread\n", mSettings);
@@ -226,3 +228,35 @@
}
// end write_UDP_AckFIN
+void Server::write_TCP_Report( ) {
+
+ int rc;
+
+ fd_set readSet;
+ FD_ZERO( &readSet );
+
+ struct timeval timeout;
+
+ char shdr[sizeof(server_hdr)];
+ server_hdr* hdr = (server_hdr*)shdr;
+
+ Transfer_Info *stats = GetReport( mSettings->reporthdr );
+ hdr->flags = htonl( HEADER_VERSION1 );
+ hdr->total_len1 = htonl( (long) (stats->TotalLen >> 32) );
+ hdr->total_len2 = htonl( (long) (stats->TotalLen & 0xFFFFFFFF) );
+ hdr->stop_sec = htonl( (long) stats->endTime );
+ hdr->stop_usec = htonl( (long)((stats->endTime - (long)stats->endTime)
+ * rMillion));
+ hdr->error_cnt = htonl( stats->cntError );
+ hdr->outorder_cnt = htonl( stats->cntOutofOrder );
+ hdr->datagrams = htonl( stats->cntDatagrams );
+ hdr->jitter1 = htonl( (long) stats->jitter );
+ hdr->jitter2 = htonl( (long) ((stats->jitter - (long)stats->jitter)
+ * rMillion) );
+ // write data
+ rc = write( mSettings->mSock, shdr, sizeof(shdr) );
+
+ //printf ("written %d out of %d\n", rc, sizeof(shdr) );
+}
+//
+
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-21 12:20:03.000000000 +0100
@@ -120,6 +120,7 @@
{"single_udp", no_argument, NULL, 'U'},
{"ipv6_domian", no_argument, NULL, 'V'},
{"suggest_win_size", no_argument, NULL, 'W'},
+{"tcp_report", no_argument, NULL, 'Z'},
{0, 0, 0, 0}
};
@@ -162,12 +163,13 @@
{"IPERF_SINGLE_UDP", no_argument, NULL, 'U'},
{"IPERF_IPV6_DOMAIN", no_argument, NULL, 'V'},
{"IPERF_SUGGEST_WIN_SIZE", required_argument, NULL, 'W'},
+{"IPERF_TCP_REPORT", no_argument, NULL, 'Z'},
{0, 0, 0, 0}
};
#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:B:CDF:IL:M:NP:RS:T:UVWZ";
/* -------------------------------------------------------------------
* defaults
@@ -229,6 +231,7 @@
main->mTTL = 1; // -T, link-local TTL
//main->mDomain = kMode_IPv4; // -V,
//main->mSuggestWin = false; // -W, Suggest the window size.
+ //main->mTCPReport = false;
} // end Settings
@@ -663,6 +666,10 @@
setSuggestWin( mExtSettings );
fprintf( stderr, "The -W option is not available in this release\n");
break;
+
+ case 'Z' : // Ask for server report
+ mExtSettings->mTCPReport = true;
+ break;
default: // ignore unknown
break;