Bob Jenness | 1 Apr 21:01 2008

Throughput dropouts

All,

I’ve been working for some time to resolve some throughput dropout issues with a WDS wireless LAN connection.

I’ve done extensive wireless debugging without finding a clear wireless mechanism that explains drastic and/or complete throughput dropouts, such as the attached run shows.

In some cases, rebooting the PC driving the wireless unit restores normal operation.  

So my question is, is there any mechanism between iperf, windows, TCP/IP, and/or lan NIC drivers that might cause a stalled condition during an iperf run, and how can I debug or differentiate between a stall condition on the PC side of the wired LAN and a similar stall in the WLAN internal firmware.

The iperf client below is executing on a Dell D800 laptop with a dedicated PCMCIA 100Mb LAN NIC direct connected to a 802.11g WDS client bridge unit, wireless connected to a D-Link DWL-2700AP direct connected to a HP desktop  computer (iperf endpoint server) via it’s motherboard LAN NIC.  Both are running win XP pro and standard LAN/TCP/IP stacks.

When not stalled, this wireless link has the capability to consistently clock at least 15 Mb, but, of course, the client bridge firmware could be causing the stall on either the wired or wireless sides.

Any help would be greatly appreciated.

 

 

Thanks,

Bob Jenness

Bob Jenness | 1 Apr 23:42 2008

RE: Throughput dropouts

Marc,
Yes, I've used wireshark, ethereal, airopeek, netstumbler, Chariot,
spectrum analyzer with waterfall plots, etc.  I'll admit that there's a
possibility that there's some WDS-specific management packet sequence
that I haven't found, but it's not for lack of looking.  I've even
received some "help" from the manufacturer, but it always comes down to
either "environmental" or "host PC test setup", and no solid supporting
evidence to differentiate between the two, so I'm here making one last
attempt to rule out "host PC test setup", or maybe get lucky and find
something that can be fixed.  I've been much less deep as a user of
iperf than a user of the 802.11g and related standards and tools, so
there could be a well-known iperf/PC OS issue that I could have
overlooked too.
As to tcptrace, this looks quite interesting, and new to me.  Any
further expert user hints will be appreciated while I bring it up.
Thanks for your help and interest,
Bob Jenness

-----Original Message-----
From: owner-iperf-users@...
[mailto:owner-iperf-users@...] On Behalf Of Marc Herbert
Sent: Tuesday, April 01, 2008 4:48 PM
To: iperf-users@...
Subject: Re: Throughput dropouts

2008/4/1, Bob Jenness <bjenness@...>:

> I've done extensive wireless debugging without finding a clear
wireless mechanism that explains drastic and/or complete throughput
dropouts, such as the attached run shows.

What do you mean by wireless debugging?

Did you try tools like wireshark and tcptrace.org ?

Cheers,

Marc

Marc Herbert | 1 Apr 22:47 2008
Picon

Re: Throughput dropouts

2008/4/1, Bob Jenness <bjenness@...>:

> I've done extensive wireless debugging without finding a clear wireless mechanism that explains
drastic and/or complete throughput dropouts, such as the attached run shows.

What do you mean by wireless debugging?

Did you try tools like wireshark and tcptrace.org ?

Cheers,

Marc

Miika Komu | 3 Apr 10:56 2008
Picon
Picon

IPerf UDP and Multihoming (fwd)

---------- Forwarded message ----------
Date: Thu, 3 Apr 2008 11:54:39 +0300 (WET)
From: Dmitriy Nikolaevich Kuptsov <kuptsov@...>
To: Majordomo@...
Cc: Miika Komu <miika@...>
Subject: IPerf UDP and Multihoming

Hi,

We found a bug with the iperf running in server mode over UDP on multihoming 
machine. The problem as follows:

1. We have 2 interfaces 1 is marked a default
2. Iperf client connects to Non-default address on server
3. Once server recieves the message it will route the message to default iface 
and in that case the source ip would be the ip of default iface. Which is 
WRONG. The packet will be discarded once it will arrive back to the client.

I have created the first version of patch (see attached file). It should work. 
However I am not sure, but the idea there is correct.

Best regards,
Dmitriy Kuptsov
diff -Naur iperf/src/Listener.cpp iperf-1.7.0/src/Listener.cpp
--- iperf/src/Listener.cpp	2008-04-03 11:16:54.000000000 +0300
+++ iperf-1.7.0/src/Listener.cpp	2003-03-05 00:47:32.000000000 +0200
 <at>  <at>  -150,9 +150,6  <at>  <at> 
                     continue;
                 }
             }
-            
-            sockaddr_storage * localhost = udpMsg->getDest();
-            
 #ifdef HAVE_THREAD
             clients_mutex.Lock(); 
             exist = Iperf_present( &peer, clients); 
 <at>  <at>  -168,15 +165,7  <at>  <at> 
                                   (((struct sockaddr*)&peer)->sa_family == AF_INET ? 
                                    sizeof(sockaddr_in) : sizeof(sockaddr_in6)));
 #endif // IPV6
-                FAIL_errno( rc == SOCKET_ERROR, "connect UDP" ); 
-                fprintf(stderr, "Binding to address that was recieved with the first UDP Packet");
-                rc = bind (mSock, (struct sockaddr*) localhost, 
-#ifndef IPV6
-                                  sizeof(sockaddr_in));
-#else
-                                  (((struct sockaddr*)&peer)->sa_family == AF_INET ? 
-                                   sizeof(sockaddr_in) : sizeof(sockaddr_in6)));
-#endif // IPV6
+                FAIL_errno( rc == SOCKET_ERROR, "connect UDP" );       
 #ifndef WIN32
                 listtemp = new Iperf_ListEntry;
                 memcpy(listtemp, &peer, sizeof(peer));
diff -Naur iperf/src/PerfSocket.cpp iperf-1.7.0/src/PerfSocket.cpp
--- iperf/src/PerfSocket.cpp	2008-04-03 11:11:32.000000000 +0300
+++ iperf-1.7.0/src/PerfSocket.cpp	2003-03-12 20:54:52.000000000 +0200
 <at>  <at>  -97,8 +97,8  <at>  <at> 
 PerfSocket::PerfSocket( ext_Settings *inSettings,
                         Notify* toNotify )
 : Socket( inSettings->mPort, (inSettings->mUDPRate > 0) ) {
+
     mSettings = inSettings;
-    udpMsg = new UDPMessage(mSettings->mDomain);
     ptr_parent = toNotify;
     mBuf = NULL;
     extractor = NULL;
 <at>  <at>  -106,12 +106,6  <at>  <at> 
     // initialize buffer
     mBuf = new char[ mSettings->mBufLen ];
     pattern( mBuf, mSettings->mBufLen );
-    
-    iovec iov;
-    iov.iov_base 	= mBuf;
-    iov.iov_len 	= mSettings->mBufLen;
-    udpMsg->setIOVector(iov);
-    
     sReportCount = 0;
     if ( mSettings->mServerMode == kMode_Client ) {
         if ( mSettings->mFileInput ) {
 <at>  <at>  -559,17 +553,6  <at>  <at> 
             FAIL_errno( rc == SOCKET_ERROR, "setsockopt TCP_NODELAY" );
         }
 #endif
-    } else {
-    	printf("Setting UDP option \n");
-    	int err = 0, on = 1;
-    	if (mSettings->mDomain) {
-    		err = setsockopt(mSock, IPPROTO_IPV6,
-    				DSTADDRV6_SOCKOPT, &on, sizeof(on));
-    	} else {
-    		err = setsockopt(mSock, IPPROTO_IP,
-    				DSTADDRV4_SOCKOPT, &on, sizeof(on));
-    	}
-    	FAIL_errno( err != 0, "setsockopt IP_PKTINFIO" );
     }
 }
 // end SetSocketOptions
diff -Naur iperf/src/PerfSocket.hpp iperf-1.7.0/src/PerfSocket.hpp
--- iperf/src/PerfSocket.hpp	2008-04-03 01:14:21.000000000 +0300
+++ iperf-1.7.0/src/PerfSocket.hpp	2003-02-27 23:59:05.000000000 +0200
 <at>  <at>  -62,7 +62,6  <at>  <at> 
 #include "Extractor.hpp"
 #include "Notify.hpp"
 #include "Settings.hpp"
-#include "UDPMessage.h"
 
 
 class Notify;
 <at>  <at>  -91,7 +90,7  <at>  <at> 
     void write_UDP_AckFIN( max_size_t mTotalLen, Timestamp mEndTime,
                            Timestamp mStartTime, int errorCnt,
                            int outofOrder, int32_t datagramID );
-    
+
     // TCP, in PerfSocket_TCP.cpp
     void Send_TCP( void );
     void Recv_TCP( void );
 <at>  <at>  -140,8 +139,6  <at>  <at> 
 
     // buffer to do reads/writes
     char *mBuf;
-    
-    UDPMessage * udpMsg;
 
     // individual and cummulative bytes written
     max_size_t mTotalLen;
diff -Naur iperf/src/PerfSocket_UDP.cpp iperf-1.7.0/src/PerfSocket_UDP.cpp
--- iperf/src/PerfSocket_UDP.cpp	2008-04-03 11:09:06.000000000 +0300
+++ iperf-1.7.0/src/PerfSocket_UDP.cpp	2003-03-05 22:30:50.000000000 +0200
 <at>  <at>  -87,7 +87,6  <at>  <at> 
  * ------------------------------------------------------------------- */ 
 
 void PerfSocket::Send_UDP( void ) {
-	SetSocketOptions();
     long currLen; 
     int32_t datagramID = 0; 
     struct UDP_datagram* mBuf_UDP = (struct UDP_datagram*) mBuf; 
 <at>  <at>  -119,7 +118,7  <at>  <at> 
 
     Timestamp lastPacketTime; 
     InitTransfer(); 
-    // Indicates if the stream is readtype filter textable 
+    // Indicates if the stream is readable 
     bool canRead; 
 
     // Due to the UDP timestamps etc, included 
 <at>  <at>  -234,7 +233,6  <at>  <at> 
  * ------------------------------------------------------------------- */ 
 
 void PerfSocket::Recv_UDP( void ) {
-	SetSocketOptions();
     bool going = true; 
     long currLen; 
     int32_t datagramID     = 0; 
 <at>  <at>  -259,22 +257,7  <at>  <at> 
     InitTransfer(); 
     do {
         // perform read 
-        //currLen = read( mSock, mBuf, mSettings->mBufLen );
-        
-        Socklen_t peerlen; 
-        int rc; 
-
-        peerlen = sizeof(peer); 
-        
-        iovec iov;
-        iov.iov_base 	= mBuf;
-        iov.iov_len 	= mSettings->mBufLen;
-        udpMsg->setIOVector(iov);
-        udpMsg->setPeer((struct sockaddr*) &peer, peerlen);
-        
-        currLen = recvmsg(mSock, 
-        			 udpMsg->getMsgHdr(),
-        			 MSG_WAITALL);
+        currLen = read( mSock, mBuf, mSettings->mBufLen ); 
 
         mPacketTime.setnow(); 
 
 <at>  <at>  -285,7 +268,6  <at>  <at> 
 
         // read the datagram ID and sentTime out of the buffer 
         datagramID = ntohl( mBuf_UDP->id ); 
-       
         sentTime.set( ntohl( mBuf_UDP->tv_sec  ), 
                       ntohl( mBuf_UDP->tv_usec )); 
 
 <at>  <at>  -351,29 +333,15  <at>  <at> 
  * ------------------------------------------------------------------- */ 
 
 iperf_sockaddr PerfSocket::Accept_UDP( void ) {
-	
-	SetSocketOptions();
-	
     iperf_sockaddr peer; 
 
     Socklen_t peerlen; 
     int rc; 
 
     peerlen = sizeof(peer); 
-    
-    iovec iov;
-    iov.iov_base 	= mBuf;
-    iov.iov_len 	= mSettings->mBufLen;
-    udpMsg->setIOVector(iov);
-    udpMsg->setPeer((struct sockaddr*) &peer, peerlen);
-    
-    
-    rc = recvmsg(mSock, 
-    			 udpMsg->getMsgHdr(),
-    			 MSG_WAITALL);
-    
-    sockaddr_storage * dsthost = udpMsg->getDest();
-    
+    rc = recvfrom( mSock, mBuf, mSettings->mBufLen, 0, 
+                   (struct sockaddr*) &peer, &peerlen ); 
+
     FAIL_errno( rc == SOCKET_ERROR, "recvfrom" );       
     return peer; 
 } 
 <at>  <at>  -394,14 +362,7  <at>  <at> 
         count++; 
 
         // write data 
-        iovec iov;
-        iov.iov_base 	= mBuf;
-        iov.iov_len 	= mSettings->mBufLen;
-        udpMsg->setIOVector(iov);
-        
-        //write( mSock, mBuf, mSettings->mBufLen );
-        
-        sendmsg(mSock, udpMsg->getMsgHdr(), 0);
+        write( mSock, mBuf, mSettings->mBufLen ); 
 
         // wait until the socket is readable, or our timeout expires 
         FD_ZERO( &readSet ); 
 <at>  <at>  -417,21 +378,7  <at>  <at> 
             continue; 
         } else {
             // socket ready to read 
-            //rc = read( mSock, mBuf, mSettings->mBufLen ); 
-            iperf_sockaddr peer; 
-
-            Socklen_t peerlen; 
-            peerlen = sizeof(peer); 
-            iovec iov;
-            iov.iov_base 	= mBuf;
-            iov.iov_len 	= mSettings->mBufLen;
-            udpMsg->setIOVector(iov);
-            udpMsg->setPeer((struct sockaddr*) &peer, peerlen);
-            
-            rc = recvmsg(mSock, 
-            			 udpMsg->getMsgHdr(),
-            			 MSG_WAITALL);
-            
+            rc = read( mSock, mBuf, mSettings->mBufLen ); 
             FAIL_errno( rc < 0, "read" );
             if ( rc >= (int) (sizeof(UDP_datagram) + sizeof(server_hdr)) ) {
                 UDP_datagram *UDP_Hdr;
 <at>  <at>  -478,6 +425,7  <at>  <at> 
                                    int outofOrder, int32_t datagramID ) {
 
     int rc; 
+
     fd_set readSet; 
     FD_ZERO( &readSet ); 
 
 <at>  <at>  -512,14 +460,7  <at>  <at> 
         }
 
         // write data 
-        iovec iov;
-        iov.iov_base 	= mBuf;
-        iov.iov_len 	= mSettings->mBufLen;
-        udpMsg->setIOVector(iov);
-                
-        //write( mSock, mBuf, mSettings->mBufLen );
-                
-        sendmsg(mSock, udpMsg->getMsgHdr(), 0);
+        write( mSock, mBuf, mSettings->mBufLen ); 
 
         // wait until the socket is readable, or our timeout expires 
         FD_SET( mSock, &readSet ); 
 <at>  <at>  -534,20 +475,7  <at>  <at> 
             return; 
         } else {
             // socket ready to read 
-            //rc = read( mSock, mBuf, mSettings->mBufLen ); 
-        	iperf_sockaddr peer; 
-        	Socklen_t peerlen; 
-        	peerlen = sizeof(peer);
-            iovec iov;
-            iov.iov_base 	= mBuf;
-            iov.iov_len 	= mSettings->mBufLen;
-            udpMsg->setIOVector(iov);
-            udpMsg->setPeer((struct sockaddr*) &peer, peerlen);
-            
-            
-            rc = recvmsg(mSock, 
-            			 udpMsg->getMsgHdr(),
-            			 MSG_WAITALL);
+            rc = read( mSock, mBuf, mSettings->mBufLen ); 
             WARN_errno( rc < 0, "read" ); 
             continue; 
         } 
diff -Naur iperf/src/UDPMessage.h iperf-1.7.0/src/UDPMessage.h
--- iperf/src/UDPMessage.h	2008-04-03 11:02:01.000000000 +0300
+++ iperf-1.7.0/src/UDPMessage.h	1970-01-01 02:00:00.000000000 +0200
 <at>  <at>  -1,127 +0,0  <at>  <at> 
-#ifndef UDPMESSAGE_H_
-#define UDPMESSAGE_H_
-
-#if defined IP_RECVDSTADDR
-#define DSTADDRV4_SOCKOPT IP_RECVDSTADDR
-#define DSTADDRV4_SOCKOPT IP_RECVDSTADDR
-#define DSTADDR_DATASIZE (CMSG_SPACE(sizeof(struct in_addr)))
-#define dstaddr(x) (CMSG_DATA(x))
-#elif defined IP_PKTINFO
-#define DSTADDRV4_SOCKOPT IP_PKTINFO
-#define DSTADDRV6_SOCKOPT IPV6_2292PKTINFO
-#define DSTADDR_DATASIZE (CMSG_SPACE(sizeof(struct in_pktinfo)))
-#define dstaddr(x) (&(((struct in_pktinfo *)(CMSG_DATA(x)))->ipi_addr))
-#define dstaddr6(x) (&(((struct in6_pktinfo *)(CMSG_DATA(x)))->ipi6_addr))
-#else
-#error "can't determine socket option"
-#endif 
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h> 
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-union control_data {
-    struct cmsghdr  cmsg;
-    u_char          data[DSTADDR_DATASIZE];
-
-}; 
-
-class UDPMessage
-{
-private:
-	msghdr udpMessage;
-	bool _isIPV6;
-public:
-	UDPMessage(bool isIPV6) {
-		memset(&udpMessage, 0, sizeof (udpMessage));
-		union control_data  cmsg;	
-		udpMessage.msg_flags 		= 0;
-		udpMessage.msg_control 		= &cmsg;
-		_isIPV6 					= isIPV6;
-	}
-
-	
-	UDPMessage(iovec iov, 
-		   	   sockaddr_storage * addr, 
-		   	   socklen_t addrlen,
-		   	   bool isIPV6) {
-	
-		memset(&udpMessage, 0, sizeof (udpMessage)); 
-	
-		union control_data  cmsg;
-	
-		udpMessage.msg_flags 		= 0;
-		udpMessage.msg_control 		= &cmsg;
-		udpMessage.msg_controllen 	= sizeof(cmsg);
-		udpMessage.msg_iov 			= &iov;
-		udpMessage.msg_iovlen 		= 1;
-		udpMessage.msg_name 		= (sockaddr *) addr;
-		udpMessage.msg_namelen 		= addrlen;
-		_isIPV6 					= isIPV6;
-	}
-
-	virtual 					~UDPMessage() {
-		
-	}
-	
-	bool isIPv6(void) {
-		return _isIPV6;
-	}
-
-	void setIOVector(iovec & iov) {
-		udpMessage.msg_iov      = &iov;
-		udpMessage.msg_iovlen   = 1;
-	}
-
-	iovec * getIOVector() {
-		return udpMessage.msg_iov;
-	}
-
-	void setPeer(struct sockaddr * addr, socklen_t len) {
-		udpMessage.msg_name 		= addr;
-		udpMessage.msg_namelen 		= len;
-	}
-
-	struct sockaddr_storage * getDest() {
-		struct cmsghdr     *cmsgptr = NULL; 
-		struct sockaddr_storage * generic;
-		
-		for (cmsgptr = CMSG_FIRSTHDR(&udpMessage);
-				cmsgptr != NULL;
-		        cmsgptr = CMSG_NXTHDR(&udpMessage, cmsgptr)) {
-			fprintf(stderr, "UDP HEADER FOUND \n");
-			if (!_isIPV6) {
-				if (cmsgptr->cmsg_level == IPPROTO_IP &&
-					cmsgptr->cmsg_type == DSTADDRV4_SOCKOPT) {
-					in_addr * addr = (struct in_addr *)dstaddr(cmsgptr);
-					generic = (struct sockaddr_storage *)addr;
-		            fprintf(stderr, "to %s", inet_ntoa(*(struct in_addr *)dstaddr(cmsgptr)));
-				}
-			} else {
-				if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
-					cmsgptr->cmsg_type == DSTADDRV6_SOCKOPT) {
-					in6_addr * addr = (struct in6_addr *)dstaddr6(cmsgptr);
-					generic = (struct sockaddr_storage *)addr;
-					fprintf(stderr, "dst host ip found");
-					//printf("to %s", inet6_ntoa(*(struct in6_addr *)dstaddr6(cmsgptr)));
-				}
-			}
-		}
-		return generic;
-	}
-
-	struct msghdr * getMsgHdr() {
-		return &udpMessage;
-	}
-	
-	
-};
-
-#endif /*UDPMESSAGE_H_*/
Picon
Picon

Revisited patch to UDP connection problem in IPERF

Hi all,

Here is cleaned patch for the UDP problem in iperf.

Best regards,
Dmitriy Kuptsov
diff -Nuar iperf/src/Listener.cpp iperf-1.7.0/src/Listener.cpp
--- iperf/src/Listener.cpp	2008-04-03 14:25:17.000000000 +0300
+++ iperf-1.7.0/src/Listener.cpp	2003-03-05 00:47:32.000000000 +0200
 <at>  <at>  -150,9 +150,6  <at>  <at> 
                     continue;
                 }
             }
-            
-            sockaddr_storage * localhost = udpMsg->getDest();
-            
 #ifdef HAVE_THREAD
             clients_mutex.Lock(); 
             exist = Iperf_present( &peer, clients); 
 <at>  <at>  -168,15 +165,7  <at>  <at> 
                                   (((struct sockaddr*)&peer)->sa_family == AF_INET ? 
                                    sizeof(sockaddr_in) : sizeof(sockaddr_in6)));
 #endif // IPV6
-                FAIL_errno( rc == SOCKET_ERROR, "connect UDP" ); 
-                //fprintf(stderr, "Binding to address that was recieved with the first UDP Packet");
-                rc = bind (mSock, (struct sockaddr*) localhost, 
-#ifndef IPV6
-                                  sizeof(sockaddr_in));
-#else
-                                  (((struct sockaddr*)&peer)->sa_family == AF_INET ? 
-                                   sizeof(sockaddr_in) : sizeof(sockaddr_in6)));
-#endif // IPV6
+                FAIL_errno( rc == SOCKET_ERROR, "connect UDP" );       
 #ifndef WIN32
                 listtemp = new Iperf_ListEntry;
                 memcpy(listtemp, &peer, sizeof(peer));
 <at>  <at>  -261,14 +250,6  <at>  <at> 
                                    sizeof(sockaddr_in) : sizeof(sockaddr_in6)));
 #endif // IPV6
                 FAIL_errno( rc == SOCKET_ERROR, "connect UDP" );       
-                //fprintf(stderr, "Binding to address that was recieved with the first UDP Packet");
-                rc = bind (mSock, (struct sockaddr*) localhost, 
-#ifndef IPV6
-                                  sizeof(sockaddr_in));
-#else
-                                  (((struct sockaddr*)&peer)->sa_family == AF_INET ? 
-                                   sizeof(sockaddr_in) : sizeof(sockaddr_in6)));
-#endif // IPV6
                 if ( !mSettings->mCompat ) {
                     Settings::GenerateSpeakerSettings( mSettings, &tempSettings, 
                                                         hdr, (sockaddr*) &peer );
diff -Nuar iperf/src/PerfSocket.cpp iperf-1.7.0/src/PerfSocket.cpp
--- iperf/src/PerfSocket.cpp	2008-04-03 13:28:45.000000000 +0300
+++ iperf-1.7.0/src/PerfSocket.cpp	2003-03-12 20:54:52.000000000 +0200
 <at>  <at>  -97,8 +97,8  <at>  <at> 
 PerfSocket::PerfSocket( ext_Settings *inSettings,
                         Notify* toNotify )
 : Socket( inSettings->mPort, (inSettings->mUDPRate > 0) ) {
+
     mSettings = inSettings;
-    udpMsg = new UDPMessage(mSettings->mDomain);
     ptr_parent = toNotify;
     mBuf = NULL;
     extractor = NULL;
 <at>  <at>  -106,12 +106,6  <at>  <at> 
     // initialize buffer
     mBuf = new char[ mSettings->mBufLen ];
     pattern( mBuf, mSettings->mBufLen );
-    
-    iovec iov;
-    iov.iov_base 	= mBuf;
-    iov.iov_len 	= mSettings->mBufLen;
-    udpMsg->setIOVector(iov);
-    
     sReportCount = 0;
     if ( mSettings->mServerMode == kMode_Client ) {
         if ( mSettings->mFileInput ) {
 <at>  <at>  -559,17 +553,6  <at>  <at> 
             FAIL_errno( rc == SOCKET_ERROR, "setsockopt TCP_NODELAY" );
         }
 #endif
-    } else {
-    	printf("Setting UDP option \n");
-    	int err = 0, on = 1;
-    	if (mSettings->mDomain) {
-    		err = setsockopt(mSock, IPPROTO_IPV6,
-    				DSTADDRV6_SOCKOPT, &on, sizeof(on));
-    	} else {
-    		err = setsockopt(mSock, IPPROTO_IP,
-    				DSTADDRV4_SOCKOPT, &on, sizeof(on));
-    	}
-    	FAIL_errno( err != 0, "setsockopt IP_PKTINFIO" );
     }
 }
 // end SetSocketOptions
diff -Nuar iperf/src/PerfSocket.hpp iperf-1.7.0/src/PerfSocket.hpp
--- iperf/src/PerfSocket.hpp	2008-04-03 13:28:45.000000000 +0300
+++ iperf-1.7.0/src/PerfSocket.hpp	2003-02-27 23:59:05.000000000 +0200
 <at>  <at>  -62,7 +62,6  <at>  <at> 
 #include "Extractor.hpp"
 #include "Notify.hpp"
 #include "Settings.hpp"
-#include "UDPMessage.h"
 
 
 class Notify;
 <at>  <at>  -91,7 +90,7  <at>  <at> 
     void write_UDP_AckFIN( max_size_t mTotalLen, Timestamp mEndTime,
                            Timestamp mStartTime, int errorCnt,
                            int outofOrder, int32_t datagramID );
-    
+
     // TCP, in PerfSocket_TCP.cpp
     void Send_TCP( void );
     void Recv_TCP( void );
 <at>  <at>  -140,8 +139,6  <at>  <at> 
 
     // buffer to do reads/writes
     char *mBuf;
-    
-    UDPMessage * udpMsg;
 
     // individual and cummulative bytes written
     max_size_t mTotalLen;
diff -Nuar iperf/src/PerfSocket_UDP.cpp iperf-1.7.0/src/PerfSocket_UDP.cpp
--- iperf/src/PerfSocket_UDP.cpp	2008-04-03 13:28:45.000000000 +0300
+++ iperf-1.7.0/src/PerfSocket_UDP.cpp	2003-03-05 22:30:50.000000000 +0200
 <at>  <at>  -87,7 +87,6  <at>  <at> 
  * ------------------------------------------------------------------- */ 
 
 void PerfSocket::Send_UDP( void ) {
-	SetSocketOptions();
     long currLen; 
     int32_t datagramID = 0; 
     struct UDP_datagram* mBuf_UDP = (struct UDP_datagram*) mBuf; 
 <at>  <at>  -119,7 +118,7  <at>  <at> 
 
     Timestamp lastPacketTime; 
     InitTransfer(); 
-    // Indicates if the stream is readtype filter textable 
+    // Indicates if the stream is readable 
     bool canRead; 
 
     // Due to the UDP timestamps etc, included 
 <at>  <at>  -234,7 +233,6  <at>  <at> 
  * ------------------------------------------------------------------- */ 
 
 void PerfSocket::Recv_UDP( void ) {
-	SetSocketOptions();
     bool going = true; 
     long currLen; 
     int32_t datagramID     = 0; 
 <at>  <at>  -259,22 +257,7  <at>  <at> 
     InitTransfer(); 
     do {
         // perform read 
-        //currLen = read( mSock, mBuf, mSettings->mBufLen );
-        
-        Socklen_t peerlen; 
-        int rc; 
-
-        peerlen = sizeof(peer); 
-        
-        iovec iov;
-        iov.iov_base 	= mBuf;
-        iov.iov_len 	= mSettings->mBufLen;
-        udpMsg->setIOVector(iov);
-        udpMsg->setPeer((struct sockaddr*) &peer, peerlen);
-        
-        currLen = recvmsg(mSock, 
-        			 udpMsg->getMsgHdr(),
-        			 MSG_WAITALL);
+        currLen = read( mSock, mBuf, mSettings->mBufLen ); 
 
         mPacketTime.setnow(); 
 
 <at>  <at>  -285,7 +268,6  <at>  <at> 
 
         // read the datagram ID and sentTime out of the buffer 
         datagramID = ntohl( mBuf_UDP->id ); 
-       
         sentTime.set( ntohl( mBuf_UDP->tv_sec  ), 
                       ntohl( mBuf_UDP->tv_usec )); 
 
 <at>  <at>  -351,29 +333,15  <at>  <at> 
  * ------------------------------------------------------------------- */ 
 
 iperf_sockaddr PerfSocket::Accept_UDP( void ) {
-	
-	SetSocketOptions();
-	
     iperf_sockaddr peer; 
 
     Socklen_t peerlen; 
     int rc; 
 
     peerlen = sizeof(peer); 
-    
-    iovec iov;
-    iov.iov_base 	= mBuf;
-    iov.iov_len 	= mSettings->mBufLen;
-    udpMsg->setIOVector(iov);
-    udpMsg->setPeer((struct sockaddr*) &peer, peerlen);
-    
-    
-    rc = recvmsg(mSock, 
-    			 udpMsg->getMsgHdr(),
-    			 MSG_WAITALL);
-    
-    sockaddr_storage * dsthost = udpMsg->getDest();
-    
+    rc = recvfrom( mSock, mBuf, mSettings->mBufLen, 0, 
+                   (struct sockaddr*) &peer, &peerlen ); 
+
     FAIL_errno( rc == SOCKET_ERROR, "recvfrom" );       
     return peer; 
 } 
 <at>  <at>  -394,14 +362,7  <at>  <at> 
         count++; 
 
         // write data 
-        iovec iov;
-        iov.iov_base 	= mBuf;
-        iov.iov_len 	= mSettings->mBufLen;
-        udpMsg->setIOVector(iov);
-        
-        //write( mSock, mBuf, mSettings->mBufLen );
-        
-        sendmsg(mSock, udpMsg->getMsgHdr(), 0);
+        write( mSock, mBuf, mSettings->mBufLen ); 
 
         // wait until the socket is readable, or our timeout expires 
         FD_ZERO( &readSet ); 
 <at>  <at>  -417,21 +378,7  <at>  <at> 
             continue; 
         } else {
             // socket ready to read 
-            //rc = read( mSock, mBuf, mSettings->mBufLen ); 
-            iperf_sockaddr peer; 
-
-            Socklen_t peerlen; 
-            peerlen = sizeof(peer); 
-            iovec iov;
-            iov.iov_base 	= mBuf;
-            iov.iov_len 	= mSettings->mBufLen;
-            udpMsg->setIOVector(iov);
-            udpMsg->setPeer((struct sockaddr*) &peer, peerlen);
-            
-            rc = recvmsg(mSock, 
-            			 udpMsg->getMsgHdr(),
-            			 MSG_WAITALL);
-            
+            rc = read( mSock, mBuf, mSettings->mBufLen ); 
             FAIL_errno( rc < 0, "read" );
             if ( rc >= (int) (sizeof(UDP_datagram) + sizeof(server_hdr)) ) {
                 UDP_datagram *UDP_Hdr;
 <at>  <at>  -478,6 +425,7  <at>  <at> 
                                    int outofOrder, int32_t datagramID ) {
 
     int rc; 
+
     fd_set readSet; 
     FD_ZERO( &readSet ); 
 
 <at>  <at>  -512,14 +460,7  <at>  <at> 
         }
 
         // write data 
-        iovec iov;
-        iov.iov_base 	= mBuf;
-        iov.iov_len 	= mSettings->mBufLen;
-        udpMsg->setIOVector(iov);
-                
-        //write( mSock, mBuf, mSettings->mBufLen );
-                
-        sendmsg(mSock, udpMsg->getMsgHdr(), 0);
+        write( mSock, mBuf, mSettings->mBufLen ); 
 
         // wait until the socket is readable, or our timeout expires 
         FD_SET( mSock, &readSet ); 
 <at>  <at>  -534,20 +475,7  <at>  <at> 
             return; 
         } else {
             // socket ready to read 
-            //rc = read( mSock, mBuf, mSettings->mBufLen ); 
-        	iperf_sockaddr peer; 
-        	Socklen_t peerlen; 
-        	peerlen = sizeof(peer);
-            iovec iov;
-            iov.iov_base 	= mBuf;
-            iov.iov_len 	= mSettings->mBufLen;
-            udpMsg->setIOVector(iov);
-            udpMsg->setPeer((struct sockaddr*) &peer, peerlen);
-            
-            
-            rc = recvmsg(mSock, 
-            			 udpMsg->getMsgHdr(),
-            			 MSG_WAITALL);
+            rc = read( mSock, mBuf, mSettings->mBufLen ); 
             WARN_errno( rc < 0, "read" ); 
             continue; 
         } 
diff -Nuar iperf/src/UDPMessage.h iperf-1.7.0/src/UDPMessage.h
--- iperf/src/UDPMessage.h	2008-04-03 14:27:46.000000000 +0300
+++ iperf-1.7.0/src/UDPMessage.h	1970-01-01 02:00:00.000000000 +0200
 <at>  <at>  -1,127 +0,0  <at>  <at> 
-#ifndef UDPMESSAGE_H_
-#define UDPMESSAGE_H_
-
-#if defined IP_RECVDSTADDR
-#define DSTADDRV4_SOCKOPT IP_RECVDSTADDR
-#define DSTADDRV4_SOCKOPT IP_RECVDSTADDR
-#define DSTADDR_DATASIZE (CMSG_SPACE(sizeof(struct in_addr)))
-#define dstaddr(x) (CMSG_DATA(x))
-#elif defined IP_PKTINFO
-#define DSTADDRV4_SOCKOPT IP_PKTINFO
-#define DSTADDRV6_SOCKOPT IPV6_2292PKTINFO
-#define DSTADDR_DATASIZE (CMSG_SPACE(sizeof(struct in_pktinfo)))
-#define dstaddr(x) (&(((struct in_pktinfo *)(CMSG_DATA(x)))->ipi_addr))
-#define dstaddr6(x) (&(((struct in6_pktinfo *)(CMSG_DATA(x)))->ipi6_addr))
-#else
-#error "can't determine socket option"
-#endif 
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h> 
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-union control_data {
-    struct cmsghdr  cmsg;
-    u_char          data[DSTADDR_DATASIZE];
-
-}; 
-
-class UDPMessage
-{
-private:
-	msghdr udpMessage;
-	bool _isIPV6;
-public:
-	UDPMessage(bool isIPV6) {
-		memset(&udpMessage, 0, sizeof (udpMessage));
-		union control_data  cmsg;	
-		udpMessage.msg_flags 		= 0;
-		udpMessage.msg_control 		= &cmsg;
-		_isIPV6 					= isIPV6;
-	}
-
-	
-	UDPMessage(iovec iov, 
-		   	   sockaddr_storage * addr, 
-		   	   socklen_t addrlen,
-		   	   bool isIPV6) {
-	
-		memset(&udpMessage, 0, sizeof (udpMessage)); 
-	
-		union control_data  cmsg;
-	
-		udpMessage.msg_flags 		= 0;
-		udpMessage.msg_control 		= &cmsg;
-		udpMessage.msg_controllen 	= sizeof(cmsg);
-		udpMessage.msg_iov 			= &iov;
-		udpMessage.msg_iovlen 		= 1;
-		udpMessage.msg_name 		= (sockaddr *) addr;
-		udpMessage.msg_namelen 		= addrlen;
-		_isIPV6 					= isIPV6;
-	}
-
-	virtual 					~UDPMessage() {
-		
-	}
-	
-	bool isIPv6(void) {
-		return _isIPV6;
-	}
-
-	void setIOVector(iovec & iov) {
-		udpMessage.msg_iov      = &iov;
-		udpMessage.msg_iovlen   = 1;
-	}
-
-	iovec * getIOVector() {
-		return udpMessage.msg_iov;
-	}
-
-	void setPeer(struct sockaddr * addr, socklen_t len) {
-		udpMessage.msg_name 		= addr;
-		udpMessage.msg_namelen 		= len;
-	}
-
-	struct sockaddr_storage * getDest() {
-		struct cmsghdr     *cmsgptr = NULL; 
-		struct sockaddr_storage * generic;
-		
-		for (cmsgptr = CMSG_FIRSTHDR(&udpMessage);
-				cmsgptr != NULL;
-		        cmsgptr = CMSG_NXTHDR(&udpMessage, cmsgptr)) {
-			fprintf(stderr, "UDP HEADER FOUND \n");
-			if (!_isIPV6) {
-				if (cmsgptr->cmsg_level == IPPROTO_IP &&
-					cmsgptr->cmsg_type == DSTADDRV4_SOCKOPT) {
-					in_addr * addr = (struct in_addr *)dstaddr(cmsgptr);
-					generic = (struct sockaddr_storage *)addr;
-		            		//fprintf(stderr, "to %s", inet_ntoa(*(struct in_addr *)dstaddr(cmsgptr)));
-				}
-			} else {
-				if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
-					cmsgptr->cmsg_type == DSTADDRV6_SOCKOPT) {
-					in6_addr * addr = (struct in6_addr *)dstaddr6(cmsgptr);
-					generic = (struct sockaddr_storage *)addr;
-					fprintf(stderr, "dst host ip found");
-					//printf("to %s", inet6_ntoa(*(struct in6_addr *)dstaddr6(cmsgptr)));
-				}
-			}
-		}
-		return generic;
-	}
-
-	struct msghdr * getMsgHdr() {
-		return &udpMessage;
-	}
-	
-	
-};
-
-#endif /*UDPMESSAGE_H_*/
Jon Dugan | 8 Apr 00:40 2008
Picon

Re: List migration to sourceforge

The iperf-users list has been moved to sourceforge.  The correct address for 
the list is now iperf-users@..., however 
iperf-users@... will forward to the new list for the time being.

The archives have not yet been imported into Sourceforge but I have an open 
support request to have that done.

Please let me know if you have problems with the new setup.

Jon

PS: I am sending this email to the old address to confirm that it forwards to 
the new address properly.

Jon Dugan wrote:
> Hello everyone,
> 
> I am in the process of migrating the iperf-users@... to 
> SourceForge.  The list has been created and I have submitted a request 
> to import the membership list and the archives into the new list.  I 
> expect this will happen sometime in the next few days.   I'll be sending 
> out an email when it is complete.  Once this is done the 
> iperf-users@... address will point to the new list.
> 
> Just to be clear: there is no need for you to go an subscribe to the 
> SourceForge list as I have requested that they import everyone from the 
> current list.
> 
> I will send out another note when the migration is complete.
> 
> Cheers,
> 
> Jon
> 

-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Register now and save $200. Hurry, offer ends at 11:59 p.m., 
Monday, April 7! Use priority code J8TLD2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
Iperf-users mailing list
Iperf-users@...
https://lists.sourceforge.net/lists/listinfo/iperf-users

Jon M. Dugan | 8 Apr 06:03 2008
Picon

Iperf 2.0.4 Released

Iperf 2.0.4 addresses one major and several minor issues with Iperf.

The bugs fixed were:

  * Iperf should no longer consume gratuitous CPU under Linux The help messages
  * have been expanded to include previously undocumented options The header
  * the stats report was missing a header which has been replaced.

New in Iperf 2.0.4:

 * Under Linux you can select the TCP congestion algorithm by using the -Z (--linux-congestion) flag
 * Iperf has a minimal man page!

Thanks to Stephen Hemminger and Claus Klein for their patches.

This is intended to be the last release in the 2.0 train.  Development efforts
going forward will concentrate on the 2.1 series of releases.  If significant
bugs are found there will be a 2.0.5 release, but hopefully we won't need to
do that.

You can download it at:

https://sourceforge.net/project/showfiles.php?group_id=128336

Jon
--

-- 
Jon M. Dugan <jdugan@...>
ESnet Network Engineering Group
Lawrence Berkeley National Laboratory

-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Register now and save $200. Hurry, offer ends at 11:59 p.m., 
Monday, April 7! Use priority code J8TLD2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
Iperf-users mailing list
Iperf-users@...
https://lists.sourceforge.net/lists/listinfo/iperf-users

Gerrit Renker | 8 Apr 14:36 2008
Picon
Picon

[Patch 1/1]: (a) timer utilities, (b) use nanosleep(2) for delay_loop()

Dear Jon,

further to earlier email discussion, I am now in the process
of updating the DCCP patches from

  http://www.erg.abdn.ac.uk/users/gerrit/dccp/apps/#iperf

to match the current SVN revision (#37). I have copied this
to the iperf-users list -- can you please advise re submission
format and to whom to copy?

I will be sending the other patches shortly. The first patch
in the series has been omitted (replacing sched_yield() with
condition variables), since per announcement this is in the
works anyway.

Gerrit

The attached patch: 
------------------
 * replaces delay_loop() with nanosleep
   - this has advantages over the gettimeofday() spin-loop
     since among other things it blocks signals and was found
     to be more accurate over the long term than the current
     implementation
   - if people feel they would like a different delay_loop,
     the old implementation has been kept via #ifdefs

 * implements several timer utilities
   - a "timer-stop" delta_usec() time measurement method
   - an overloaded form of "before()"
   - a corresponding "after()"

The University of Aberdeen is a charity registered in Scotland, No SC013683.

-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Register now and save $200. Hurry, offer ends at 11:59 p.m., 
Monday, April 7! Use priority code J8TLD2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
Iperf-users mailing list
Iperf-users@...
https://lists.sourceforge.net/lists/listinfo/iperf-users
Jon Dugan | 8 Apr 22:58 2008
Picon

Re: [Patch 1/1]: (a) timer utilities, (b) use nanosleep(2) for delay_loop()

Gerrit,

Excellent!

My preference for handling patches would be to submit them to the Patch 
tracker on Sourceforge:

https://sourceforge.net/tracker/?group_id=128336&atid=711373

And then send a note to the list mentioning that the patch has been uploaded 
and what it does.  I'll get an email when the patches are submitted, but 
others on the list may be interested.

I don't have time to look at this patch in depth right now, but I will get to 
it early next week.  This along with several other patches should hit trunk 
next week.

Cheers,

Jon

Gerrit Renker wrote:
> Dear Jon,
> 
> further to earlier email discussion, I am now in the process
> of updating the DCCP patches from
>  
>   http://www.erg.abdn.ac.uk/users/gerrit/dccp/apps/#iperf
> 
> to match the current SVN revision (#37). I have copied this
> to the iperf-users list -- can you please advise re submission
> format and to whom to copy?
> 
> I will be sending the other patches shortly. The first patch
> in the series has been omitted (replacing sched_yield() with
> condition variables), since per announcement this is in the
> works anyway.
> 
> Gerrit
> 
> The attached patch: 
> ------------------
>  * replaces delay_loop() with nanosleep
>    - this has advantages over the gettimeofday() spin-loop
>      since among other things it blocks signals and was found
>      to be more accurate over the long term than the current
>      implementation
>    - if people feel they would like a different delay_loop,
>      the old implementation has been kept via #ifdefs
> 
>  * implements several timer utilities
>    - a "timer-stop" delta_usec() time measurement method
>    - an overloaded form of "before()"
>    - a corresponding "after()"
> 
> 
> The University of Aberdeen is a charity registered in Scotland, No SC013683.
> 
> 
> 
> ------------------------------------------------------------------------
> 
> Timer Utilities
> ===============
> 
> Apart from extending the Timestamp class (support for measuring elapsed
> time and an `after' test), the main point of this patch is to update
> the delay_loop() function. 
> 
> The present implementation used a tight loop of continually calling
> gettimeofday(2) until the specified amount of time has passed. This 
> is resource-intensive. In addition, while the loop worked reasonably
> in many cases, it sometimes caused unwanted delays of 50 milliseconds
> or more (process preempted?).
> 
> This has been replaced with nanosleep(2) as default now. The advantage
> of nanosleep over the old solution is that signals are blocked and it
> seems a much more robust solution.
> 
> Also, nanosleep uses the hrtimers interface internally 
> (/usr/src/davem-2.6/Documentation/hrtimers/hrtimers.txt).
> 
> For people who would like to keep the old behaviour, #ifdefs with
> alternatives have been added.
> 
> Signed-off-by: Gerrit Renker <gerrit@...>
> ---
>  compat/delay.cpp      |   38 ++++++++++++++++++++++++++++++--------
>  include/Timestamp.hpp |   29 ++++++++++++++++-------------
>  2 files changed, 46 insertions(+), 21 deletions(-)
> 
> --- a/compat/delay.cpp
> +++ b/compat/delay.cpp
>  <at>  <at>  -51,19 +51,31  <at>  <at> 
>   * ------------------------------------------------------------------- */
>  
>  #include "Timestamp.hpp"
> -
> +#include "util.h"
>  #include "delay.hpp"
>  
>  /* -------------------------------------------------------------------
> - * A micro-second delay function. This uses gettimeofday (underneith
> - * the Timestamp) which has a resolution of upto microseconds. I've
> - * found it's good to within about 10 usecs.
> - * I used to do calibration, but iperf automatically adjusts itself
> - * so that isn't necesary, and it causes some problems if the
> - * calibration adjustment is larger than your sleep time.
> + * A micro-second delay function.
>   * ------------------------------------------------------------------- */
> +void delay_loop(unsigned long usec)
> +{
> +#ifdef SLEEP_VIA_SELECT
> +     // This is a hack but works apparently quite well
> +     // I found that it sometimes under-estimates the timeout
> +     struct timeval tv;
> +
> +     tv.tv_sec = 0;
> +     tv.tv_usec = usec;
>  
> -void delay_loop( unsigned long usec ) {
> +     select(1, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &tv);
> +#elif defined(SLEEP_OLD_METHOD)
> +    /* Tis uses gettimeofday (underneath the Timestamp), which has a
> +     * resolution of upto microseconds. I've found it's good to within
> +     * about 10 usecs. I used to do calibration, but iperf automatically
> +     * adjusts itself so that isn't necesary, and it causes some problems
> +     * if the calibration adjustment is larger than your sleep time.
> +     * Note: I found this has problems - if the loop gets interrupted,
> +     * long sleeps can result. I found up to 50..60msec. -- Gerrit */
>      Timestamp end;
>      end.add( usec * 1e-6 );
>  
>  <at>  <at>  -71,4 +83,14  <at>  <at>  void delay_loop( unsigned long usec ) {
>      while ( now.before( end ) ) {
>          now.setnow();
>      }
> +#else
> +    // This is preferred; it is even better than usleep (see manpage).
> +    struct timespec ts;
> +
> +    ts.tv_sec = 0;
> +    ts.tv_nsec = usec * 1000L;
> +
> +    if (nanosleep(&ts, NULL) < 0)
> +        WARN_errno(1, "nanosleep");
> +#endif
>  }
> --- a/include/Timestamp.hpp
> +++ b/include/Timestamp.hpp
>  <at>  <at>  -152,6 +152,16  <at>  <at>  public:
>      }
>  
>      /* -------------------------------------------------------------------
> +     * Return the number of microseconds from now to last time of setting.
> +     * ------------------------------------------------------------------- */
> +    long delta_usec(void) {
> +        struct timeval previous = mTime;
> +
> +        setnow();
> +        return subUsec(previous);
> +    }
> +
> +    /* -------------------------------------------------------------------
>       * subtract the right timestamp from my timestamp.
>       * return the difference in seconds as a floating point.
>       * ------------------------------------------------------------------- */
>  <at>  <at>  -202,29 +212,22  <at>  <at>  public:
>      /* -------------------------------------------------------------------
>       * return true if my timestamp is before the right timestamp.
>       * ------------------------------------------------------------------- */
> -    bool before( Timestamp right ) {
> -        return mTime.tv_sec < right.mTime.tv_sec  ||
> -        (mTime.tv_sec == right.mTime.tv_sec &&
> -         mTime.tv_usec < right.mTime.tv_usec);
> -    }
> -    
> -    /* -------------------------------------------------------------------
> -     * return true if my timestamp is before the right timestamp.
> -     * ------------------------------------------------------------------- */
>      bool before( timeval right ) {
>          return mTime.tv_sec < right.tv_sec  ||
>          (mTime.tv_sec == right.tv_sec &&
>           mTime.tv_usec < right.tv_usec);
>      }
> +    bool before( Timestamp right ) { return before(right.mTime); }
>  
>      /* -------------------------------------------------------------------
>       * return true if my timestamp is after the right timestamp.
>       * ------------------------------------------------------------------- */
> -    bool after( Timestamp right ) {
> -        return mTime.tv_sec > right.mTime.tv_sec  ||
> -        (mTime.tv_sec == right.mTime.tv_sec &&
> -         mTime.tv_usec > right.mTime.tv_usec);
> +    bool after( timeval right ) {
> +        return mTime.tv_sec > right.tv_sec  ||
> +        (mTime.tv_sec == right.tv_sec &&
> +         mTime.tv_usec > right.tv_usec);
>      }
> +    bool after( Timestamp right ) { return after(right.mTime); }
>  
>      /**
>       * This function returns the fraction of time elapsed after the beginning 

-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Register now and save $200. Hurry, offer ends at 11:59 p.m., 
Monday, April 7! Use priority code J8TLD2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
Iperf-users mailing list
Iperf-users@...
https://lists.sourceforge.net/lists/listinfo/iperf-users

Jon Dugan | 9 Apr 03:55 2008
Picon

Bug in 2.0.4

Well, that didn't take long.

An annoying (but harmless) bug has been found in Iperf 2.0.4: if you use the 
-i flag to get a status report periodically the header for those reports will 
be printed for each report.   This has been fixed in SVN for both the 2.0 and 
2.1 trains.

I'm not planning to cut a new release for this unless there is a demand for 
it.   Instead I think I will wait a few weeks and see what else trickles in 
and cut a new release if there is sufficient reason.  Otherwise I'd rather 
focus on the more significant changes that are slated for 2.1.

Cheers,

Jon

-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Don't miss this year's exciting event. There's still time to save $100. 
Use priority code J8TL2D2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
Iperf-users mailing list
Iperf-users@...
https://lists.sourceforge.net/lists/listinfo/iperf-users


Gmane