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


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