]> sjero.net Git - iperf/blobdiff - src/Settings.cpp
Native IPv6 support for iperf
[iperf] / src / Settings.cpp
index 244b2a5fecd0000136b5c28c8ee52687997e7ebe..549a9cca9d7523afb8c88e31e72901e3b16f8124 100644 (file)
@@ -84,12 +84,14 @@ void Settings_Interpret( char option, const char *optarg, thread_Settings *mExtS
 const struct option long_options[] =
 {
 {"singleclient",     no_argument, NULL, '1'},
+{"dualtest",         no_argument, NULL, '2'},
 {"bandwidth",  required_argument, NULL, 'b'},
 {"client",     required_argument, NULL, 'c'},
-{"dualtest",         no_argument, NULL, 'd'},
+{"dccp",            no_argument, NULL, 'd'},
 {"format",     required_argument, NULL, 'f'},
 {"help",             no_argument, NULL, 'h'},
 {"interval",   required_argument, NULL, 'i'},
+{"mcast_iface",required_argument, NULL, 'j'},
 {"len",        required_argument, NULL, 'l'},
 {"print_mss",        no_argument, NULL, 'm'},
 {"num",        required_argument, NULL, 'n'},
@@ -128,12 +130,14 @@ const struct option long_options[] =
 const struct option env_options[] =
 {
 {"IPERF_SINGLECLIENT",     no_argument, NULL, '1'},
+{"IPERF_DUALTEST",         no_argument, NULL, '2'},
 {"IPERF_BANDWIDTH",  required_argument, NULL, 'b'},
 {"IPERF_CLIENT",     required_argument, NULL, 'c'},
-{"IPERF_DUALTEST",         no_argument, NULL, 'd'},
+{"IPERF_DCCP",             no_argument, NULL, 'd'},
 {"IPERF_FORMAT",     required_argument, NULL, 'f'},
 // skip help
 {"IPERF_INTERVAL",   required_argument, NULL, 'i'},
+{"IPERF_MCASTIFACE", required_argument, NULL, 'j'},
 {"IPERF_LEN",        required_argument, NULL, 'l'},
 {"IPERF_PRINT_MSS",        no_argument, NULL, 'm'},
 {"IPERF_NUM",        required_argument, NULL, 'n'},
@@ -167,19 +171,22 @@ const struct option env_options[] =
 
 #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[] =
+      "12b::c:df:hi:j:l:mn:o:p:rst:uvw:x:y:B:CDF:IJ:L:M:NP:RS:T:UV:W";
 
 /* -------------------------------------------------------------------
  * defaults
  * ------------------------------------------------------------------- */
 #define DEFAULTS()
 
-const long kDefault_UDPRate = 1024 * 1024; // -u  if set, 1 Mbit/sec
-const int  kDefault_UDPBufLen = 1470;      // -u  if set, read/write 1470 bytes
+const long kDefault_DgramRate = 1024 * 1024; // -u  if set, 1 Mbit/sec
+const int  kDefault_UDPBufLen = 1470;        // -u  if set, read/write 1470 bytes
 // 1470 bytes is small enough to be sending one packet per datagram on ethernet
 
 // 1450 bytes is small enough to be sending one packet per datagram on ethernet
 //  **** with IPv6 ****
+const int  kDefault_DCCPBufLen = 1420;       // -d
+// old DCCPv4: MPS=1424; new DCCPv4: MPS=1440; new DCCPv6: MPS=1420 (above)
 
 /* -------------------------------------------------------------------
  * Initialize all settings to defaults.
@@ -190,42 +197,45 @@ void Settings_Initialize( thread_Settings *main ) {
     // this memset. Only need to set non-zero values
     // below.
     memset( main, 0, sizeof(thread_Settings) );
-    main->mSock = INVALID_SOCKET;
-    main->mReportMode = kReport_Default;
+    main->mSock         = INVALID_SOCKET;
+    //main->mSockAF     = AF_UNSPEC
+    main->mReportMode   = kReport_Default;
     // option, defaults
     main->flags         = FLAG_MODETIME | FLAG_STDOUT; // Default time and stdout
-    //main->mUDPRate      = 0;           // -b,  ie. TCP mode
-    //main->mHost         = NULL;        // -c,  none, required for client
-    main->mMode         = kTest_Normal;  // -d,  mMode == kTest_DualTest
+    //main->mDgramRate  = 0;             // -b,  ie. TCP mode
+    main->mProtocol     = kProto_TCP;   // -u / -d
+    //main->mHost       = NULL;          // -c,  none, required for client
+    main->mMode         = kTest_Normal;  // -2,  mMode == kTest_DualTest
     main->mFormat       = 'a';           // -f,  adaptive bits
     // skip help                         // -h,
     //main->mBufLenSet  = false;         // -l,        
     main->mBufLen       = 8 * 1024;      // -l,  8 Kbyte
-    //main->mInterval     = 0;           // -i,  ie. no periodic bw reports
+    //main->mInterval   = 0;             // -i,  ie. no periodic bw reports
     //main->mPrintMSS   = false;         // -m,  don't print MSS
     // mAmount is time also              // -n,  N/A
     //main->mOutputFileName = NULL;      // -o,  filename
     main->mPort         = 5001;          // -p,  ttcp port
-    // mMode    = kTest_Normal;          // -r,  mMode == kTest_TradeOff
+    // mMode            = kTest_Normal;  // -r,  mMode == kTest_TradeOff
     main->mThreadMode   = kMode_Unknown; // -s,  or -c, none
     main->mAmount       = 1000;          // -t,  10 seconds
-    // mUDPRate > 0 means UDP            // -u,  N/A, see kDefault_UDPRate
+    // mDgramRate                        // -u,  N/A, see kDefault_DgramRate
     // skip version                      // -v,
-    //main->mTCPWin       = 0;           // -w,  ie. don't set window
+    //main->mWinSize       = 0;          // -w,  ie. don't set window
 
     // more esoteric options
-    //main->mLocalhost    = NULL;        // -B,  none
+    //main->mLocalhost  = NULL;          // -B,  bind address - none
     //main->mCompat     = false;         // -C,  run in Compatibility mode
     //main->mDaemon     = false;         // -D,  run as a daemon
     //main->mFileInput  = false;         // -F,
-    //main->mFileName     = NULL;        // -F,  filename 
+    //main->mFileName   = NULL;          // -F,  filename
     //main->mStdin      = false;         // -I,  default not stdin
-    //main->mListenPort   = 0;           // -L,  listen port
-    //main->mMSS          = 0;           // -M,  ie. don't set MSS
+    //main->mMcastIface = 0;             // -J,  default: host chooses interface
+    //main->mListenPort = 0;             // -L,  listen port
+    //main->mMSS        = 0;             // -M,  ie. don't set MSS
     //main->mNodelay    = false;         // -N,  don't set nodelay
-    //main->mThreads      = 0;           // -P,
+    //main->mThreads    = 0;             // -P,
     //main->mRemoveService = false;      // -R,
-    //main->mTOS          = 0;           // -S,  ie. don't set type of service
+    //main->mTOS        = 0;             // -S,  ie. don't set type of service
     main->mTTL          = 1;             // -T,  link-local TTL
     //main->mDomain     = kMode_IPv4;    // -V,
     //main->mSuggestWin = false;         // -W,  Suggest the window size.
@@ -314,25 +324,34 @@ void Settings_Interpret( char option, const char *optarg, thread_Settings *mExtS
         case '1': // Single Client
             setSingleClient( mExtSettings );
             break;
-        case 'b': // UDP bandwidth
-            if ( !isUDP( mExtSettings ) ) {
-                fprintf( stderr, warn_implied_udp, option );
-            }
 
+        case '2': // Dual-test Mode
             if ( mExtSettings->mThreadMode != kMode_Client ) {
                 fprintf( stderr, warn_invalid_server_option, option );
                 break;
             }
+            if ( isCompat( mExtSettings ) ) {
+                fprintf( stderr, warn_invalid_compatibility_option, option );
+            }
+#ifdef HAVE_THREAD
+            mExtSettings->mMode = kTest_DualTest;
+#else
+            fprintf( stderr, warn_invalid_single_threaded, option );
+            mExtSettings->mMode = kTest_TradeOff;
+#endif
+            break;
 
-            Settings_GetLowerCaseArg(optarg,outarg);
-            mExtSettings->mUDPRate = byte_atoi(outarg);
-            setUDP( mExtSettings );
+        case 'b':
+            // This sets packet-oriented mode. The optional
+            // argument sets datagram bandwidth (as before).
+            // If not given, a default bandwith is used.
+            setPacketOriented(mExtSettings);
 
-            // if -l has already been processed, mBufLenSet is true
-            // so don't overwrite that value.
-            if ( !isBuflenSet( mExtSettings ) ) {
-                mExtSettings->mBufLen = kDefault_UDPBufLen;
-            }
+            if (optarg) {
+                Settings_GetLowerCaseArg(optarg, outarg);
+                mExtSettings->mDgramRate = byte_atoi(outarg);
+             } else
+                mExtSettings->mDgramRate = kDefault_DgramRate;
             break;
 
         case 'c': // client mode w/ server host to connect to
@@ -340,32 +359,19 @@ void Settings_Interpret( char option, const char *optarg, thread_Settings *mExtS
             strcpy( mExtSettings->mHost, optarg );
 
             if ( mExtSettings->mThreadMode == kMode_Unknown ) {
-                // Test for Multicast
-                iperf_sockaddr temp;
-                SockAddr_setHostname( mExtSettings->mHost, &temp,
-                                      (isIPV6( mExtSettings ) ? 1 : 0 ));
-                if ( SockAddr_isMulticast( &temp ) ) {
-                    setMulticast( mExtSettings );
-                }
                 mExtSettings->mThreadMode = kMode_Client;
                 mExtSettings->mThreads = 1;
             }
             break;
 
-        case 'd': // Dual-test Mode
-            if ( mExtSettings->mThreadMode != kMode_Client ) {
-                fprintf( stderr, warn_invalid_server_option, option );
-                break;
-            }
-            if ( isCompat( mExtSettings ) ) {
-                fprintf( stderr, warn_invalid_compatibility_option, option );
-            }
-#ifdef HAVE_THREAD
-            mExtSettings->mMode = kTest_DualTest;
-#else
-            fprintf( stderr, warn_invalid_single_threaded, option );
-            mExtSettings->mMode = kTest_TradeOff;
-#endif
+        case 'd': // DCCP as transport
+            mExtSettings->mProtocol  = kProto_DCCP;
+
+            // if -l has already been processed, mBufLenSet is true
+            // so don't overwrite that value.
+            if ( !isBuflenSet( mExtSettings ) )
+                mExtSettings->mBufLen = kDefault_DCCPBufLen;
+
             break;
 
         case 'f': // format to print in
@@ -373,14 +379,7 @@ void Settings_Interpret( char option, const char *optarg, thread_Settings *mExtS
             break;
 
         case 'h': // print help and exit
-#ifndef WIN32
-            fprintf( stderr, usage_long );
-#else
-            fprintf(stderr, usage_long1);
-            fprintf(stderr, usage_long2);
-#endif
-            exit(1);
-            break;
+           die(usage_long);
 
         case 'i': // specify interval between periodic bw reports
             mExtSettings->mInterval = atof( optarg );
@@ -390,23 +389,31 @@ void Settings_Interpret( char option, const char *optarg, thread_Settings *mExtS
             }
             break;
 
+        case 'j':
+        case 'J': // multicast interface to join multicast address on
+            mExtSettings->mMcastIface = if_nametoindex(optarg);
+            if (!mExtSettings->mMcastIface)
+                   die("Interface \"%s\" does not work for -j/-J.", optarg);
+            break;
+
         case 'l': // length of each buffer
             Settings_GetUpperCaseArg(optarg,outarg);
             mExtSettings->mBufLen = byte_atoi( outarg );
             setBuflenSet( mExtSettings );
-            if ( !isUDP( mExtSettings ) ) {
+
+            if ( !isPacketOriented( mExtSettings ) ) {
                  if ( mExtSettings->mBufLen < (int) sizeof( client_hdr ) &&
                       !isCompat( mExtSettings ) ) {
                     setCompat( mExtSettings );
                     fprintf( stderr, warn_implied_compatibility, option );
                  }
             } else {
-                if ( mExtSettings->mBufLen < (int) sizeof( UDP_datagram ) ) {
-                    mExtSettings->mBufLen = sizeof( UDP_datagram );
+                if ( mExtSettings->mBufLen < (int) sizeof( dgram_record ) ) {
+                    mExtSettings->mBufLen = sizeof( dgram_record );
                     fprintf( stderr, warn_buffer_too_small, mExtSettings->mBufLen );
                 }
                 if ( !isCompat( mExtSettings ) &&
-                            mExtSettings->mBufLen < (int) ( sizeof( UDP_datagram )
+                            mExtSettings->mBufLen < (int) ( sizeof( dgram_record )
                             + sizeof( client_hdr ) ) ) {
                     setCompat( mExtSettings );
                     fprintf( stderr, warn_implied_compatibility, option );
@@ -464,18 +471,19 @@ void Settings_Interpret( char option, const char *optarg, thread_Settings *mExtS
             break;
 
         case 'u': // UDP instead of TCP
+            mExtSettings->mProtocol = kProto_UDP;
+
+            setPacketOriented(mExtSettings);
             // if -b has already been processed, UDP rate will
             // already be non-zero, so don't overwrite that value
-            if ( !isUDP( mExtSettings ) ) {
-                setUDP( mExtSettings );
-                mExtSettings->mUDPRate = kDefault_UDPRate;
-            }
+            if ( mExtSettings->mDgramRate == 0 )
+                mExtSettings->mDgramRate = kDefault_DgramRate;
 
             // if -l has already been processed, mBufLenSet is true
             // so don't overwrite that value.
             if ( !isBuflenSet( mExtSettings ) ) {
                 mExtSettings->mBufLen = kDefault_UDPBufLen;
-            } else if ( mExtSettings->mBufLen < (int) ( sizeof( UDP_datagram ) 
+            } else if ( mExtSettings->mBufLen < (int) ( sizeof( dgram_record )
                         + sizeof( client_hdr ) ) &&
                         !isCompat( mExtSettings ) ) {
                 setCompat( mExtSettings );
@@ -484,17 +492,11 @@ void Settings_Interpret( char option, const char *optarg, thread_Settings *mExtS
             break;
 
         case 'v': // print version and exit
-            fprintf( stderr, version );
-            exit(1);
-            break;
+            die(version);
 
-        case 'w': // TCP window size (socket buffer size)
+        case 'w': // TCP window size or socket send-buffer size (UDP/DCCP)
             Settings_GetUpperCaseArg(optarg,outarg);
-            mExtSettings->mTCPWin = byte_atoi(outarg);
-
-            if ( mExtSettings->mTCPWin < 2048 ) {
-                fprintf( stderr, warn_window_small, mExtSettings->mTCPWin );
-            }
+            mExtSettings->mWinSize = byte_atoi(outarg);
             break;
 
         case 'x': // Limit Reports
@@ -543,13 +545,6 @@ void Settings_Interpret( char option, const char *optarg, thread_Settings *mExtS
         case 'B': // specify bind address
             mExtSettings->mLocalhost = new char[ strlen( optarg ) + 1 ];
             strcpy( mExtSettings->mLocalhost, optarg );
-            // Test for Multicast
-            iperf_sockaddr temp;
-            SockAddr_setHostname( mExtSettings->mLocalhost, &temp,
-                                  (isIPV6( mExtSettings ) ? 1 : 0 ));
-            if ( SockAddr_isMulticast( &temp ) ) {
-                setMulticast( mExtSettings );
-            }
             break;
 
         case 'C': // Run in Compatibility Mode
@@ -635,30 +630,15 @@ void Settings_Interpret( char option, const char *optarg, thread_Settings *mExtS
             mExtSettings->mTTL = atoi( optarg );
             break;
 
+        case 'V': // IP Domain: the optional ar
+            mExtSettings->mSockAF = AF_INET6;
+            if ( optarg  && optarg[0] == '4' )
+                mExtSettings->mSockAF = AF_INET;
+            break;
         case 'U': // single threaded UDP server
             setSingleUDP( mExtSettings );
             break;
 
-        case 'V': // IPv6 Domain
-            setIPV6( mExtSettings );
-            if ( mExtSettings->mThreadMode == kMode_Server 
-                 && mExtSettings->mLocalhost != NULL ) {
-                // Test for Multicast
-                iperf_sockaddr temp;
-                SockAddr_setHostname( mExtSettings->mLocalhost, &temp, 1);
-                if ( SockAddr_isMulticast( &temp ) ) {
-                    setMulticast( mExtSettings );
-                }
-            } else if ( mExtSettings->mThreadMode == kMode_Client ) {
-                // Test for Multicast
-                iperf_sockaddr temp;
-                SockAddr_setHostname( mExtSettings->mHost, &temp, 1 );
-                if ( SockAddr_isMulticast( &temp ) ) {
-                    setMulticast( mExtSettings );
-                }
-            }
-            break;
-
         case 'W' :
             setSuggestWin( mExtSettings );
             fprintf( stderr, "The -W option is not available in this release\n");
@@ -745,27 +725,23 @@ void Settings_GenerateClientSettings( thread_Settings *server,
         *client = new thread_Settings;
         memcpy(*client, server, sizeof( thread_Settings ));
         setCompat( (*client) );
-        (*client)->mTID = thread_zeroid();
+        (*client)->mTID        = thread_zeroid();
         (*client)->mPort       = (unsigned short) ntohl(hdr->mPort);
         (*client)->mThreads    = ntohl(hdr->numThreads);
         if ( hdr->bufferlen != 0 ) {
             (*client)->mBufLen = ntohl(hdr->bufferlen);
         }
         if ( hdr->mWinBand != 0 ) {
-            if ( isUDP( server ) ) {
-                (*client)->mUDPRate = ntohl(hdr->mWinBand);
+            if ( isPacketOriented( server ) ) {
+                (*client)->mDgramRate = ntohl(hdr->mWinBand);
             } else {
-                (*client)->mTCPWin = ntohl(hdr->mWinBand);
+                (*client)->mWinSize = ntohl(hdr->mWinBand);
             }
         }
         (*client)->mAmount     = ntohl(hdr->mAmount);
         if ( ((*client)->mAmount & 0x80000000) > 0 ) {
             setModeTime( (*client) );
-#ifndef WIN32
             (*client)->mAmount |= 0xFFFFFFFF00000000LL;
-#else
-            (*client)->mAmount |= 0xFFFFFFFF00000000;
-#endif
             (*client)->mAmount = -(*client)->mAmount;
         }
         (*client)->mFileName   = NULL;
@@ -780,16 +756,7 @@ void Settings_GenerateClientSettings( thread_Settings *server,
             strcpy( (*client)->mLocalhost, server->mLocalhost );
         }
         (*client)->mHost = new char[REPORT_ADDRLEN];
-        if ( ((sockaddr*)&server->peer)->sa_family == AF_INET ) {
-            inet_ntop( AF_INET, &((sockaddr_in*)&server->peer)->sin_addr, 
-                       (*client)->mHost, REPORT_ADDRLEN);
-        }
-#ifdef HAVE_IPV6
-          else {
-            inet_ntop( AF_INET6, &((sockaddr_in6*)&server->peer)->sin6_addr, 
-                       (*client)->mHost, REPORT_ADDRLEN);
-        }
-#endif
+       SockAddr_name(&server->peer, (*client)->mHost, REPORT_ADDRLEN);
     } else {
         *client = NULL;
     }
@@ -812,10 +779,10 @@ void Settings_GenerateClientHdr( thread_Settings *client, client_hdr *hdr ) {
     } else {
         hdr->bufferlen = 0;
     }
-    if ( isUDP( client ) ) {
-        hdr->mWinBand  = htonl(client->mUDPRate);
+    if ( isPacketOriented( client ) ) {
+        hdr->mWinBand  = htonl(client->mDgramRate);
     } else {
-        hdr->mWinBand  = htonl(client->mTCPWin);
+        hdr->mWinBand  = htonl(client->mWinSize);
     }
     if ( client->mListenPort != 0 ) {
         hdr->mPort  = htonl(client->mListenPort);