--- Copyright (c) 2007-2009, Centre for Advanced Internet Architectures
--- Swinburne University of Technology, Melbourne, Australia
--- (CRICOS number 00111D).
---
--- All rights reserved.
---
--- CAIA Iperf Patch v1.1 (for Iperf v2.0.2)
---
--- This software was developed by James Healy <jhealy@swin.edu.au>
--- and Lawrence Stewart <lastewart@swin.edu.au>
---
--- Redistribution and use in source and binary forms, with or without
--- modification, are permitted provided that the following conditions
--- are met:
--- 1. Redistributions of source code must retain the above copyright
---    notice, this list of conditions and the following disclaimer.
--- 2. Redistributions in binary form must reproduce the above copyright
---    notice, this list of conditions and the following disclaimer in the
---    documentation and/or other materials provided with the distribution.
--- 3. The names of the authors, the "Centre for Advanced Internet Architectures"
---    and "Swinburne University of Technology" may not be used to endorse
---    or promote products derived from this software without specific
---    prior written permission.
---
--- THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
--- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
--- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
--- ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
--- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
--- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
--- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
--- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
--- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
--- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
--- SUCH DAMAGE.
---
--- include/Locale.h.orig	Tue May  3 06:09:26 2005
+++ include/Locale.h	Mon Aug 27 12:28:35 2007
@@ -92,11 +92,15 @@
 
 extern const char server_datagram_size[];
 
-extern const char tcp_window_size[];
+extern const char tcp_sendspace_size[];
 
-extern const char udp_buffer_size[];
+extern const char tcp_recvspace_size[];
 
-extern const char window_default[];
+extern const char udp_sendspace_size[];
+
+extern const char udp_recvspace_size[];
+
+extern const char buf_default[];
 
 extern const char wait_server_threads[];
 
@@ -146,9 +150,9 @@
  * warnings
  * ------------------------------------------------------------------- */
 
-extern const char warn_window_requested[];
+extern const char warn_buf_requested[];
 
-extern const char warn_window_small[];
+extern const char warn_buf_small[];
 
 extern const char warn_delay_large[];
 
@@ -160,7 +164,7 @@
 
 extern const char warn_fileopen_failed[];
 
-extern const char unable_to_change_win[];
+extern const char unable_to_change_buf[];
 
 extern const char opt_estimate[];
 
--- include/Reporter.h.orig	Tue May  3 06:09:26 2005
+++ include/Reporter.h	Mon Aug 27 12:28:35 2007
@@ -129,7 +129,8 @@
     int PacketID;
     int mBufLen;                    // -l
     int mMSS;                       // -M
-    int mTCPWin;                    // -w
+    int mTCPSndBuf;                 // -j
+    int mTCPRcvBuf;                 // -k
     /*   flags is a BitMask of old bools
         bool   mBufLenSet;              // -l
         bool   mCompat;                 // -C
--- include/util.h.orig	Tue May  3 06:09:26 2005
+++ include/util.h	Mon Aug 27 12:28:35 2007
@@ -65,8 +65,8 @@
  * set/getsockopt wrappers for SO_RCVBUF and SO_SNDBUF; TCP_MAXSEG
  * socket.c
  * ------------------------------------------------------------------- */
-int setsock_tcp_windowsize( int inSock, int inTCPWin, int inSend );
-int getsock_tcp_windowsize( int inSock, int inSend );
+int setsock_buffer_size( int inSock, int inBufSize, int inWhichBuf );
+int getsock_buffer_size( int inSock, int inWhichBuf );
 
 void setsock_tcp_mss( int inSock, int inTCPWin );
 int  getsock_tcp_mss( int inSock );
--- include/Settings.hpp.orig	Tue May  3 06:09:26 2005
+++ include/Settings.hpp	Mon Aug 27 12:28:35 2007
@@ -124,7 +124,9 @@
     int Extractor_size;
     int mBufLen;                    // -l
     int mMSS;                       // -M
-    int mTCPWin;                    // -w
+    int mTCPSndBuf;                 // -j
+    int mTCPRcvBuf;                 // -k
+    int mTCPWizBuf;                 // -w
     /*   flags is a BitMask of old bools
         bool   mBufLenSet;              // -l
         bool   mCompat;                 // -C
@@ -325,14 +327,16 @@
     int32_t numThreads;
     int32_t mPort;
     int32_t bufferlen;
-    int32_t mWinBand;
+    int32_t mRcvBand;
+    int32_t mSndBand;
     int32_t mAmount;
 #else
     signed int flags      : 32;
     signed int numThreads : 32;
     signed int mPort      : 32;
     signed int bufferlen  : 32;
-    signed int mWinBand   : 32;
+    signed int mSndBand   : 32;
+    signed int mRcvBand   : 32;
     signed int mAmount    : 32;
 #endif
 } client_hdr;
--- src/Locale.c.orig	Tue May  3 06:09:27 2005
+++ src/Locale.c	Mon Aug 27 12:28:35 2007
@@ -79,12 +79,14 @@
 Client/Server:\n\
   -f, --format    [kmKM]   format to report: Kbits, Mbits, KBytes, MBytes\n\
   -i, --interval  #        seconds between periodic bandwidth reports\n\
+  -j, --sendbuf   #[KM]    socket send buffer size\n\
+  -k, --recvbuf   #[KM]    socket receive buffer size\n\
   -l, --len       #[KM]    length of buffer to read or write (default 8 KB)\n\
   -m, --print_mss          print TCP maximum segment size (MTU - TCP/IP header)\n\
   -o, --output    <filename> output the report or error message to this specified file\n\
   -p, --port      #        server port to listen on/connect to\n\
   -u, --udp                use UDP rather than TCP\n\
-  -w, --window    #[KM]    TCP window size (socket buffer size)\n\
+  -w, --wizard    #[KM]    socket buffer tuning wizard (useful for unidirectional client to server tests)\n\
   -B, --bind      <host>   bind to <host>, an interface or multicast address\n\
   -C, --compatibility      for use with older versions does not sent extra msgs\n\
   -M, --mss       #        set TCP maximum segment size (MTU - 40 bytes)\n\
@@ -119,8 +121,7 @@
 \n\
 [KM] Indicates options that support a K or M suffix for kilo- or mega-\n\
 \n\
-The TCP window size option can be set by the environment variable\n\
-TCP_WINDOW_SIZE. Most other options can be set by an environment variable\n\
+Most options can be set by an environment variable\n\
 IPERF_<long option name>, such as IPERF_BANDWIDTH.\n\
 \n\
 Report bugs to <dast@nlanr.net>\n";
@@ -133,11 +134,13 @@
 Client/Server:\n\
   -f, --format    [kmKM]   format to report: Kbits, Mbits, KBytes, MBytes\n\
   -i, --interval  #        seconds between periodic bandwidth reports\n\
+  -j, --sendbuf   #[KM]    socket send buffer size\n\
+  -k, --recvbuf   #[KM]    socket receive buffer size\n\
   -l, --len       #[KM]    length of buffer to read or write (default 8 KB)\n\
   -m, --print_mss          print TCP maximum segment size (MTU - TCP/IP header)\n\
   -p, --port      #        server port to listen on/connect to\n\
   -u, --udp                use UDP rather than TCP\n\
-  -w, --window    #[KM]    TCP window size (socket buffer size)\n\
+  -w, --wizard    #[KM]    socket buffer tuning wizard (useful for unidirectional client to server tests)\n\
   -B, --bind      <host>   bind to <host>, an interface or multicast address\n\
   -C, --compatibility      for use with older versions does not sent extra msgs\n\
   -M, --mss       #        set TCP maximum segment size (MTU - 40 bytes)\n\
@@ -169,8 +172,7 @@
 \n\
 [KM] Indicates options that support a K or M suffix for kilo- or mega-\n\
 \n\
-The TCP window size option can be set by the environment variable\n\
-TCP_WINDOW_SIZE. Most other options can be set by an environment variable\n\
+Most options can be set by an environment variable\n\
 IPERF_<long option name>, such as IPERF_BANDWIDTH.\n\
 \n\
 Report bugs to <dast@nlanr.net>\n";
@@ -216,13 +218,19 @@
 const char server_datagram_size[] =
 "Receiving %d byte datagrams\n";
 
-const char tcp_window_size[] =
-"TCP window size";
+const char tcp_sendspace_size[] =
+"TCP snd buf size";
 
-const char udp_buffer_size[] =
-"UDP buffer size";
+const char tcp_recvspace_size[] =
+"TCP rcv buf size (max advertised window)";
 
-const char window_default[] =
+const char udp_sendspace_size[] =
+"UDP snd buffer size";
+
+const char udp_recvspace_size[] =
+"UDP rcv buffer size";
+
+const char buf_default[] =
 "(default)";
 
 const char wait_server_threads[] =
@@ -317,11 +325,11 @@
  * warnings
  * ------------------------------------------------------------------- */
 
-const char warn_window_requested[] =
+const char warn_buf_requested[] =
 " (WARNING: requested %s)";
 
-const char warn_window_small[] = "\
-WARNING: TCP window size set to %d bytes. A small window size\n\
+const char warn_buf_small[] = "\
+WARNING: TCP buffer size set to %d bytes. A small buffer size\n\
 will give poor performance. See the Iperf documentation.\n";
 
 const char warn_delay_large[] =
@@ -340,8 +348,8 @@
 "WARNING: Unable to open file stream for transfer\n\
 Using default data stream. \n";
 
-const char unable_to_change_win[]=
-"WARNING: Unable to change the window size\n";
+const char unable_to_change_buf[]=
+"WARNING: Unable to change the buffer size\n";
 
 const char opt_estimate[]=
 "Optimal Estimate\n";
--- src/ReportDefault.c.orig	Tue May  3 06:09:27 2005
+++ src/ReportDefault.c	Mon Aug 27 12:28:35 2007
@@ -144,11 +144,12 @@
  * Report the client or listener Settings in default style
  */
 void reporter_reportsettings( ReporterData *data ) {
-    int win, win_requested;
+    int sendspace, recvspace, rcvbuf_requested, sndbuf_requested;
 
-    win = getsock_tcp_windowsize( data->info.transferID,
-                  (data->mThreadMode == kMode_Listener ? 0 : 1) );
-    win_requested = data->mTCPWin;
+    sendspace = getsock_buffer_size( data->info.transferID, SO_SNDBUF);
+    recvspace = getsock_buffer_size( data->info.transferID, SO_RCVBUF);
+    rcvbuf_requested = data->mTCPRcvBuf;
+    sndbuf_requested = data->mTCPSndBuf;
 
     printf( seperator_line );
     if ( data->mThreadMode == kMode_Listener ) {
@@ -176,17 +177,31 @@
             printf( multicast_ttl, data->info.mTTL);
         }
     }
-    byte_snprintf( buffer, sizeof(buffer), win,
+    byte_snprintf( buffer, sizeof(buffer), sendspace,
                    toupper( data->info.mFormat));
     printf( "%s: %s", (isUDP( data ) ? 
-                                udp_buffer_size : tcp_window_size), buffer );
+                                udp_sendspace_size : tcp_sendspace_size), buffer );
 
-    if ( win_requested == 0 ) {
-        printf( " %s", window_default );
-    } else if ( win != win_requested ) {
-        byte_snprintf( buffer, sizeof(buffer), win_requested,
+    if ( sndbuf_requested == 0 ) {
+        printf( " %s", buf_default );
+    } else if ( sendspace != sndbuf_requested ) {
+        byte_snprintf( buffer, sizeof(buffer), sndbuf_requested,
                        toupper( data->info.mFormat));
-        printf( warn_window_requested, buffer );
+        printf( warn_buf_requested, buffer );
+    }
+    printf( "\n" );
+
+    byte_snprintf( buffer, sizeof(buffer), recvspace,
+                   toupper( data->info.mFormat));
+    printf( "%s: %s", (isUDP( data ) ?
+                                udp_recvspace_size : tcp_recvspace_size), buffer );
+
+    if ( rcvbuf_requested == 0 ) {
+        printf( " %s", buf_default );
+    } else if ( recvspace != rcvbuf_requested ) {
+        byte_snprintf( buffer, sizeof(buffer), rcvbuf_requested,
+                       toupper( data->info.mFormat));
+        printf( warn_buf_requested, buffer );
     }
     printf( "\n" );
     printf( seperator_line );
--- src/Reporter.c.orig	Tue May  3 06:09:27 2005
+++ src/Reporter.c	Mon Aug 27 16:10:05 2007
@@ -155,7 +155,20 @@
                 data->mLocalhost = agent->mLocalhost;
                 data->mBufLen = agent->mBufLen;
                 data->mMSS = agent->mMSS;
-                data->mTCPWin = agent->mTCPWin;
+                if ( agent->mTCPWizBuf > 0 ) {
+                    if ( agent->mThreadMode == kMode_Client ) {
+                        data->mTCPSndBuf = agent->mTCPWizBuf;
+                        data->mTCPRcvBuf = 0;
+                    }
+                    else {
+                        data->mTCPRcvBuf = agent->mTCPWizBuf;
+                        data->mTCPSndBuf;
+                    }
+                }
+                else {
+                    data->mTCPSndBuf = agent->mTCPSndBuf;
+                    data->mTCPRcvBuf = agent->mTCPRcvBuf;
+                }
                 data->flags = agent->flags;
                 data->mThreadMode = agent->mThreadMode;
                 data->mode = agent->mReportMode;
@@ -236,7 +249,20 @@
             data->mLocalhost = agent->mLocalhost;
             data->mBufLen = agent->mBufLen;
             data->mMSS = agent->mMSS;
-            data->mTCPWin = agent->mTCPWin;
+            if ( agent->mTCPWizBuf > 0 ) {
+                if ( agent->mThreadMode == kMode_Client ) {
+                    data->mTCPSndBuf = agent->mTCPWizBuf;
+                    data->mTCPRcvBuf = 0;
+                }
+                else {
+                    data->mTCPRcvBuf = agent->mTCPWizBuf;
+                    data->mTCPSndBuf;
+                }
+            }
+            else {
+                data->mTCPSndBuf = agent->mTCPSndBuf;
+                data->mTCPRcvBuf = agent->mTCPRcvBuf;
+            }
             data->flags = agent->flags;
             data->mThreadMode = agent->mThreadMode;
             data->mode = agent->mReportMode;
@@ -441,7 +467,20 @@
             data->type = SETTINGS_REPORT;
             data->mBufLen = agent->mBufLen;
             data->mMSS = agent->mMSS;
-            data->mTCPWin = agent->mTCPWin;
+            if ( agent->mTCPWizBuf > 0 ) {
+                if ( agent->mThreadMode == kMode_Client ) {
+                    data->mTCPSndBuf = agent->mTCPWizBuf;
+                    data->mTCPRcvBuf = 0;
+                }
+                else {
+                    data->mTCPRcvBuf = agent->mTCPWizBuf;
+                    data->mTCPSndBuf;
+                }
+            }
+            else {
+                data->mTCPSndBuf = agent->mTCPSndBuf;
+                data->mTCPRcvBuf = agent->mTCPRcvBuf;
+            }
             data->flags = agent->flags;
             data->mThreadMode = agent->mThreadMode;
             data->mPort = agent->mPort;
--- src/tcp_window_size.c.orig	Tue May  3 06:09:27 2005
+++ src/tcp_window_size.c	Mon Aug 27 12:28:35 2007
@@ -59,7 +59,7 @@
 #endif
 
 /* -------------------------------------------------------------------
- * If inTCPWin > 0, set the TCP window size (via the socket buffer
+ * If inBufSize > 0, set the TCP window size (via the socket buffer
  * sizes) for inSock. Otherwise leave it as the system default.
  *
  * This must be called prior to calling listen() or connect() on
@@ -70,21 +70,21 @@
  * returns -1 on error, 0 on no error.
  * ------------------------------------------------------------------- */
 
-int setsock_tcp_windowsize( int inSock, int inTCPWin, int inSend ) {
-#ifdef SO_SNDBUF
+int setsock_buffer_size( int inSock, int inBufSize, int inWhichBuf ) {
+#if defined(SO_SNDBUF) && defined(SO_RCVBUF)
     int rc;
-    int newTCPWin;
+    int newBufSize;
 
     assert( inSock >= 0 );
 
-    if ( inTCPWin > 0 ) {
+    if ( inBufSize > 0 ) {
 
 #ifdef TCP_WINSHIFT
 
         /* UNICOS requires setting the winshift explicitly */
-        if ( inTCPWin > 65535 ) {
+        if ( inBufSize > 65535 ) {
             int winShift = 0;
-            int scaledWin = inTCPWin >> 16;
+            int scaledWin = inBufSize >> 16;
             while ( scaledWin > 0 ) {
                 scaledWin >>= 1;
                 winShift++;
@@ -106,7 +106,7 @@
         /* On AIX, RFC 1323 extensions can be set system-wide,
          * using the 'no' network options command. But we can also set them
          * per-socket, so let's try just in case. */
-        if ( inTCPWin > 65535 ) {
+        if ( inBufSize > 65535 ) {
             /* enable RFC 1323 */
             int on = 1;
             rc = setsockopt( inSock, IPPROTO_TCP, TCP_RFC1323,
@@ -117,59 +117,61 @@
         }
 #endif /* TCP_RFC1323 */
 
-        if ( !inSend ) {
+        if ( inWhichBuf == SO_RCVBUF ) {
             /* receive buffer -- set
              * note: results are verified after connect() or listen(),
              * since some OS's don't show the corrected value until then. */
-            newTCPWin = inTCPWin;
+            newBufSize = inBufSize;
             rc = setsockopt( inSock, SOL_SOCKET, SO_RCVBUF,
-                             (char*) &newTCPWin, sizeof( newTCPWin ));
-        } else {
+                             (char*) &newBufSize, sizeof( newBufSize ));
+        } else if ( inWhichBuf == SO_SNDBUF ) {
             /* send buffer -- set
              * note: results are verified after connect() or listen(),
              * since some OS's don't show the corrected value until then. */
-            newTCPWin = inTCPWin;
+            newBufSize = inBufSize;
             rc = setsockopt( inSock, SOL_SOCKET, SO_SNDBUF,
-                             (char*) &newTCPWin, sizeof( newTCPWin ));
+                             (char*) &newBufSize, sizeof( newBufSize ));
         }
         if ( rc < 0 ) {
             return rc;
         }
     }
-#endif /* SO_SNDBUF */
+#endif /* SO_SNDBUF && SO_RCVBUF */
 
     return 0;
-} /* end setsock_tcp_windowsize */
+} /* end setsock_buffer_size */
 
 /* -------------------------------------------------------------------
- * returns the TCP window size (on the sending buffer, SO_SNDBUF),
- * or -1 on error.
+ * returns the socket buffer size or -1 on error.
  * ------------------------------------------------------------------- */
 
-int getsock_tcp_windowsize( int inSock, int inSend ) {
-    int theTCPWin = 0;
+int getsock_buffer_size( int inSock, int inWhichBuf ) {
+    int bufsize = 0;
+
 
-#ifdef SO_SNDBUF
     int rc;
-    Socklen_t len;
+    Socklen_t len = sizeof(bufsize);
 
-    /* send buffer -- query for buffer size */
-    len = sizeof( theTCPWin );
-    if ( inSend ) {
+#ifdef SO_SNDBUF
+    if ( inWhichBuf == SO_SNDBUF ) {
         rc = getsockopt( inSock, SOL_SOCKET, SO_SNDBUF,
-                         (char*) &theTCPWin, &len );
-    } else {
+                         (char*) &bufsize, &len );
+#endif
+#ifdef SO_RCVBUF
+    } else if(inWhichBuf == SO_RCVBUF) {
         rc = getsockopt( inSock, SOL_SOCKET, SO_RCVBUF,
-                         (char*) &theTCPWin, &len );
+                         (char*) &bufsize, &len );
     }
+#endif
     if ( rc < 0 ) {
         return rc;
     }
 
-#endif
 
-    return theTCPWin;
-} /* end getsock_tcp_windowsize */
+
+    return bufsize;
+} /* end getsock_buffer_size */
+
 
 #ifdef __cplusplus
 } /* end extern "C" */
--- src/PerfSocket.cpp.orig	Tue May  3 06:09:27 2005
+++ src/PerfSocket.cpp	Mon Aug 27 12:28:35 2007
@@ -87,8 +87,18 @@
     // set the TCP window size (socket buffer sizes)
     // also the UDP buffer size
     // must occur before call to accept() for large window sizes
-    setsock_tcp_windowsize( inSettings->mSock, inSettings->mTCPWin,
-                            (inSettings->mThreadMode == kMode_Client ? 1 : 0) );
+    if(inSettings->mTCPWizBuf > 0)
+    {
+      if(inSettings->mThreadMode == kMode_Client)
+        setsock_buffer_size( inSettings->mSock, inSettings->mTCPWizBuf, SO_SNDBUF);
+      else
+        setsock_buffer_size( inSettings->mSock, inSettings->mTCPWizBuf, SO_RCVBUF);
+    }
+    else
+    {
+      setsock_buffer_size( inSettings->mSock, inSettings->mTCPRcvBuf, SO_RCVBUF);
+      setsock_buffer_size( inSettings->mSock, inSettings->mTCPSndBuf, SO_SNDBUF);
+    }
 
     // check if we're sending multicast, and set TTL
     if ( isMulticast( inSettings ) && ( inSettings->mTTL > 0 ) ) {
--- src/Settings.cpp.orig	Tue May  3 06:09:27 2005
+++ src/Settings.cpp	Mon Aug 27 12:37:38 2007
@@ -90,6 +90,8 @@
 {"format",     required_argument, NULL, 'f'},
 {"help",             no_argument, NULL, 'h'},
 {"interval",   required_argument, NULL, 'i'},
+{"sendbuf",    required_argument, NULL, 'j'},
+{"recvbuf",    required_argument, NULL, 'k'},
 {"len",        required_argument, NULL, 'l'},
 {"print_mss",        no_argument, NULL, 'm'},
 {"num",        required_argument, NULL, 'n'},
@@ -100,7 +102,7 @@
 {"time",       required_argument, NULL, 't'},
 {"udp",              no_argument, NULL, 'u'},
 {"version",          no_argument, NULL, 'v'},
-{"window",     required_argument, NULL, 'w'},
+{"wizard",     required_argument, NULL, 'w'},
 {"reportexclude", required_argument, NULL, 'x'},
 {"reportstyle",required_argument, NULL, 'y'},
 
@@ -134,6 +136,8 @@
 {"IPERF_FORMAT",     required_argument, NULL, 'f'},
 // skip help
 {"IPERF_INTERVAL",   required_argument, NULL, 'i'},
+{"IPERF_SENDBUF",    required_argument, NULL, 'j'},
+{"IPERF_RECVBUF",    required_argument, NULL, 'k'},
 {"IPERF_LEN",        required_argument, NULL, 'l'},
 {"IPERF_PRINT_MSS",        no_argument, NULL, 'm'},
 {"IPERF_NUM",        required_argument, NULL, 'n'},
@@ -143,7 +147,7 @@
 {"IPERF_TIME",       required_argument, NULL, 't'},
 {"IPERF_UDP",              no_argument, NULL, 'u'},
 // skip version
-{"TCP_WINDOW_SIZE",  required_argument, NULL, 'w'},
+{"IPERF_WIZARD",     required_argument, NULL, 'w'},
 {"IPERF_REPORTEXCLUDE", required_argument, NULL, 'x'},
 {"IPERF_REPORTSTYLE",required_argument, NULL, 'y'},
 
@@ -167,7 +171,7 @@
 
 #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:j:k:l:mn:o:p:rst:uvw:x:y:B:CDF:IL:M:NP:RS:T:UVW";
 
 /* -------------------------------------------------------------------
  * defaults
@@ -300,6 +304,16 @@
     for ( int i = gnu_optind; i < argc; i++ ) {
         fprintf( stderr, "%s: ignoring extra argument -- %s\n", argv[0], argv[i] );
     }
+
+    if ( mSettings->mTCPWizBuf > 0 ) {
+        if ( mSettings->mTCPSndBuf > 0 ) {
+            fprintf( stderr, "-w mutually excludes the use of -j (ignoring -j argument)\n" );
+        }
+        if ( mSettings->mTCPRcvBuf > 0 ) {
+            fprintf( stderr, "-w mutually excludes the use of -k (ignoring -k argument)\n" );
+        }
+    }
+        
 } // end ParseCommandLine
 
 /* -------------------------------------------------------------------
@@ -390,6 +404,24 @@
             }
             break;
 
+        case 'j': // TCP sendbuf size (socket send buffer size)
+            Settings_GetUpperCaseArg(optarg,outarg);
+            mExtSettings->mTCPSndBuf = byte_atoi(outarg);
+
+            if ( mExtSettings->mTCPSndBuf < 2048 ) {
+                fprintf( stderr, warn_buf_small, mExtSettings->mTCPSndBuf );
+            }
+            break;
+
+        case 'k': // TCP recvbuf size (socket receive buffer size)
+            Settings_GetUpperCaseArg(optarg,outarg);
+            mExtSettings->mTCPRcvBuf = byte_atoi(outarg);
+
+            if ( mExtSettings->mTCPRcvBuf < 2048 ) {
+                fprintf( stderr, warn_buf_small, mExtSettings->mTCPRcvBuf );
+            }
+            break;
+
         case 'l': // length of each buffer
             Settings_GetUpperCaseArg(optarg,outarg);
             mExtSettings->mBufLen = byte_atoi( outarg );
@@ -488,12 +520,12 @@
             exit(1);
             break;
 
-        case 'w': // TCP window size (socket buffer size)
+        case 'w': // TCP buffer tuning wizard
             Settings_GetUpperCaseArg(optarg,outarg);
-            mExtSettings->mTCPWin = byte_atoi(outarg);
+            mExtSettings->mTCPWizBuf = byte_atoi(outarg);
 
-            if ( mExtSettings->mTCPWin < 2048 ) {
-                fprintf( stderr, warn_window_small, mExtSettings->mTCPWin );
+            if ( mExtSettings->mTCPWizBuf < 2048 ) {
+                fprintf( stderr, warn_buf_small, mExtSettings->mTCPWizBuf );
             }
             break;
 
@@ -751,11 +783,12 @@
         if ( hdr->bufferlen != 0 ) {
             (*client)->mBufLen = ntohl(hdr->bufferlen);
         }
-        if ( hdr->mWinBand != 0 ) {
+        if ( hdr->mRcvBand != 0 ) {
             if ( isUDP( server ) ) {
-                (*client)->mUDPRate = ntohl(hdr->mWinBand);
+                (*client)->mUDPRate = ntohl(hdr->mRcvBand);
             } else {
-                (*client)->mTCPWin = ntohl(hdr->mWinBand);
+                (*client)->mTCPRcvBuf = ntohl(hdr->mRcvBand);
+                (*client)->mTCPSndBuf = ntohl(hdr->mSndBand);
             }
         }
         (*client)->mAmount     = ntohl(hdr->mAmount);
@@ -813,9 +846,10 @@
         hdr->bufferlen = 0;
     }
     if ( isUDP( client ) ) {
-        hdr->mWinBand  = htonl(client->mUDPRate);
+        hdr->mRcvBand  = htonl(client->mUDPRate);
     } else {
-        hdr->mWinBand  = htonl(client->mTCPWin);
+        hdr->mRcvBand  = htonl(client->mTCPRcvBuf);
+        hdr->mSndBand  = htonl(client->mTCPSndBuf);
     }
     if ( client->mListenPort != 0 ) {
         hdr->mPort  = htonl(client->mListenPort);
