IPerf UDP and Multihoming (fwd)


---------- Forwarded message ----------
Date: Thu, 3 Apr 2008 11:54:39 +0300 (WET)
From: Dmitriy Nikolaevich Kuptsov <kuptsov --at-- hytti.uku.fi>
To: Majordomo --at-- dast.nlanr.net
Cc: Miika Komu <miika --at-- iki.fi>
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
@@ -150,9 +150,6 @@
                     continue;
                 }
             }
-            
-            sockaddr_storage * localhost = udpMsg->getDest();
-            
 #ifdef HAVE_THREAD
             clients_mutex.Lock(); 
             exist = Iperf_present( &peer, clients); 
@@ -168,15 +165,7 @@
                                   (((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
@@ -97,8 +97,8 @@
 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;
@@ -106,12 +106,6 @@
     // 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 ) {
@@ -559,17 +553,6 @@
             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
@@ -62,7 +62,6 @@
 #include "Extractor.hpp"
 #include "Notify.hpp"
 #include "Settings.hpp"
-#include "UDPMessage.h"
 
 
 class Notify;
@@ -91,7 +90,7 @@
     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 );
@@ -140,8 +139,6 @@
 
     // 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
@@ -87,7 +87,6 @@
  * ------------------------------------------------------------------- */ 
 
 void PerfSocket::Send_UDP( void ) {
-	SetSocketOptions();
     long currLen; 
     int32_t datagramID = 0; 
     struct UDP_datagram* mBuf_UDP = (struct UDP_datagram*) mBuf; 
@@ -119,7 +118,7 @@
 
     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 
@@ -234,7 +233,6 @@
  * ------------------------------------------------------------------- */ 
 
 void PerfSocket::Recv_UDP( void ) {
-	SetSocketOptions();
     bool going = true; 
     long currLen; 
     int32_t datagramID     = 0; 
@@ -259,22 +257,7 @@
     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(); 
 
@@ -285,7 +268,6 @@
 
         // 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 )); 
 
@@ -351,29 +333,15 @@
  * ------------------------------------------------------------------- */ 
 
 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; 
 } 
@@ -394,14 +362,7 @@
         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 ); 
@@ -417,21 +378,7 @@
             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;
@@ -478,6 +425,7 @@
                                    int outofOrder, int32_t datagramID ) {
 
     int rc; 
+
     fd_set readSet; 
     FD_ZERO( &readSet ); 
 
@@ -512,14 +460,7 @@
         }
 
         // 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 ); 
@@ -534,20 +475,7 @@
             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
@@ -1,127 +0,0 @@
-#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_*/


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