]> sjero.net Git - iperf/blob - src/tcp_window_size.c
DCCP support for iperf
[iperf] / src / tcp_window_size.c
1 /*--------------------------------------------------------------- 
2  * Copyright (c) 1999,2000,2001,2002,2003                              
3  * The Board of Trustees of the University of Illinois            
4  * All Rights Reserved.                                           
5  *--------------------------------------------------------------- 
6  * Permission is hereby granted, free of charge, to any person    
7  * obtaining a copy of this software (Iperf) and associated       
8  * documentation files (the "Software"), to deal in the Software  
9  * without restriction, including without limitation the          
10  * rights to use, copy, modify, merge, publish, distribute,        
11  * sublicense, and/or sell copies of the Software, and to permit     
12  * persons to whom the Software is furnished to do
13  * so, subject to the following conditions: 
14  *
15  *     
16  * Redistributions of source code must retain the above 
17  * copyright notice, this list of conditions and 
18  * the following disclaimers. 
19  *
20  *     
21  * Redistributions in binary form must reproduce the above 
22  * copyright notice, this list of conditions and the following 
23  * disclaimers in the documentation and/or other materials 
24  * provided with the distribution. 
25  * 
26  *     
27  * Neither the names of the University of Illinois, NCSA, 
28  * nor the names of its contributors may be used to endorse 
29  * or promote products derived from this Software without
30  * specific prior written permission. 
31  * 
32  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
33  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
34  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
35  * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT 
36  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
37  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
38  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE
39  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
40  * ________________________________________________________________
41  * National Laboratory for Applied Network Research 
42  * National Center for Supercomputing Applications 
43  * University of Illinois at Urbana-Champaign 
44  * http://www.ncsa.uiuc.edu
45  * ________________________________________________________________ 
46  *
47  * tcp_window_size.c
48  * by Mark Gates <mgates@nlanr.net>
49  * -------------------------------------------------------------------
50  * set/getsockopt
51  * ------------------------------------------------------------------- */
52
53 #include "headers.h"
54
55 #include "util.h"
56
57 #ifdef __cplusplus
58 extern "C" {
59 #endif
60
61 /* -------------------------------------------------------------------
62  * Set the socket buffer size in bytes (returns -1 on error, 0 otherwise).
63  * ------------------------------------------------------------------- */
64 int set_buffer_sock_size(int inSock, int inWinSize , bool inSend)
65 {
66    // note: results are verified after connect() or listen(),
67    // since some OS's don't show the corrected value until then.
68 #ifdef SO_SNDBUF
69     if (inWinSize > 0) {
70         return setsockopt(inSock, SOL_SOCKET,
71                           inSend ? SO_SNDBUF: SO_RCVBUF,
72                           &inWinSize, sizeof(inWinSize));
73     }
74 #else
75     fprintf(stderr, "%s: no support for SO_SNDBUF\n", __FUNCTION__);
76 #endif
77     return 0;
78 }
79
80 /* -------------------------------------------------------------------
81  * If inTCPWin > 0, set the TCP window size (via the socket buffer
82  * sizes) for inSock. Otherwise leave it as the system default.
83  *
84  * This must be called prior to calling listen() or connect() on
85  * the socket, for TCP window sizes > 64 KB to be effective.
86  *
87  * This now works on UNICOS also, by setting TCP_WINSHIFT.
88  * This now works on AIX, by enabling RFC1323.
89  * returns -1 on error, 0 on no error.
90  * ------------------------------------------------------------------- */
91 int setsock_tcp_windowsize(int inSock, int inTCPWin, int inSend)
92 {
93     assert( inSock >= 0 );
94
95     if (inTCPWin > 0) {
96        if (inTCPWin < 2048)
97          fprintf(stderr, "WARNING: A TCP window size of %d bytes is "
98                          "considered small and will give poor performance. "
99                          "See the Iperf documentation.\n", inTCPWin);
100 #ifdef TCP_WINSHIFT
101         /* UNICOS requires setting the winshift explicitly */
102         if ( inTCPWin > 65535 ) {
103             int winShift = 0;
104             int scaledWin = inTCPWin >> 16;
105             while ( scaledWin > 0 ) {
106                 scaledWin >>= 1;
107                 winShift++;
108             }
109
110             /* set TCP window shift */
111             rc = setsockopt( inSock, IPPROTO_TCP, TCP_WINSHIFT,
112                              (char*) &winShift, sizeof( winShift ));
113             if ( rc < 0 ) {
114                 return rc;
115             }
116
117             /* Note: you cannot verify TCP window shift, since it returns
118              * a structure and not the same integer we use to set it. (ugh) */
119         }
120 #endif /* TCP_WINSHIFT  */
121
122 #ifdef TCP_RFC1323
123         /* On AIX, RFC 1323 extensions can be set system-wide,
124          * using the 'no' network options command. But we can also set them
125          * per-socket, so let's try just in case. */
126         if ( inTCPWin > 65535 ) {
127             /* enable RFC 1323 */
128             int on = 1;
129             rc = setsockopt( inSock, IPPROTO_TCP, TCP_RFC1323,
130                              (char*) &on, sizeof( on ));
131             if ( rc < 0 ) {
132                 return rc;
133             }
134         }
135 #endif /* TCP_RFC1323 */
136     }
137     return set_buffer_sock_size(inSock, inTCPWin, inSend);
138 }
139
140 /* -------------------------------------------------------------------
141  * returns the send/receive socket buffer size in bytes
142  * or -1 on error.
143  * ------------------------------------------------------------------- */
144 int get_buffer_sock_size( int inSock, int inSend )
145 {
146     int bufSize = 0;
147 #ifdef SO_SNDBUF
148     Socklen_t len = sizeof(bufSize);
149     int rc;
150
151     if ( inSend )
152         rc = getsockopt( inSock, SOL_SOCKET, SO_SNDBUF,
153                          (char*) &bufSize, &len );
154     else
155         rc = getsockopt( inSock, SOL_SOCKET, SO_RCVBUF,
156                          (char*) &bufSize, &len );
157     if (rc < 0)
158         return rc;
159 #endif
160     return bufSize;
161 }
162
163 #ifdef __cplusplus
164 } /* end extern "C" */
165 #endif