]> sjero.net Git - iperf/blob - src/tcp_window_size.c
bdd28c5c32e1c95755259d9ab2845f85ca886eae
[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  * If inTCPWin > 0, set the TCP window size (via the socket buffer
63  * sizes) for inSock. Otherwise leave it as the system default.
64  *
65  * This must be called prior to calling listen() or connect() on
66  * the socket, for TCP window sizes > 64 KB to be effective.
67  *
68  * This now works on UNICOS also, by setting TCP_WINSHIFT.
69  * This now works on AIX, by enabling RFC1323.
70  * returns -1 on error, 0 on no error.
71  * ------------------------------------------------------------------- */
72
73 int setsock_tcp_windowsize( int inSock, int inTCPWin, int inSend ) {
74 #ifdef SO_SNDBUF
75     int rc;
76     int newTCPWin;
77
78     assert( inSock >= 0 );
79
80     if ( inTCPWin > 0 ) {
81
82 #ifdef TCP_WINSHIFT
83
84         /* UNICOS requires setting the winshift explicitly */
85         if ( inTCPWin > 65535 ) {
86             int winShift = 0;
87             int scaledWin = inTCPWin >> 16;
88             while ( scaledWin > 0 ) {
89                 scaledWin >>= 1;
90                 winShift++;
91             }
92
93             /* set TCP window shift */
94             rc = setsockopt( inSock, IPPROTO_TCP, TCP_WINSHIFT,
95                              (char*) &winShift, sizeof( winShift ));
96             if ( rc < 0 ) {
97                 return rc;
98             }
99
100             /* Note: you cannot verify TCP window shift, since it returns
101              * a structure and not the same integer we use to set it. (ugh) */
102         }
103 #endif /* TCP_WINSHIFT  */
104
105 #ifdef TCP_RFC1323
106         /* On AIX, RFC 1323 extensions can be set system-wide,
107          * using the 'no' network options command. But we can also set them
108          * per-socket, so let's try just in case. */
109         if ( inTCPWin > 65535 ) {
110             /* enable RFC 1323 */
111             int on = 1;
112             rc = setsockopt( inSock, IPPROTO_TCP, TCP_RFC1323,
113                              (char*) &on, sizeof( on ));
114             if ( rc < 0 ) {
115                 return rc;
116             }
117         }
118 #endif /* TCP_RFC1323 */
119
120         if ( !inSend ) {
121             /* receive buffer -- set
122              * note: results are verified after connect() or listen(),
123              * since some OS's don't show the corrected value until then. */
124             newTCPWin = inTCPWin;
125             rc = setsockopt( inSock, SOL_SOCKET, SO_RCVBUF,
126                              (char*) &newTCPWin, sizeof( newTCPWin ));
127         } else {
128             /* send buffer -- set
129              * note: results are verified after connect() or listen(),
130              * since some OS's don't show the corrected value until then. */
131             newTCPWin = inTCPWin;
132             rc = setsockopt( inSock, SOL_SOCKET, SO_SNDBUF,
133                              (char*) &newTCPWin, sizeof( newTCPWin ));
134         }
135         if ( rc < 0 ) {
136             return rc;
137         }
138     }
139 #endif /* SO_SNDBUF */
140
141     return 0;
142 } /* end setsock_tcp_windowsize */
143
144 /* -------------------------------------------------------------------
145  * returns the TCP window size (on the sending buffer, SO_SNDBUF),
146  * or -1 on error.
147  * ------------------------------------------------------------------- */
148
149 int getsock_tcp_windowsize( int inSock, int inSend ) {
150     int theTCPWin = 0;
151
152 #ifdef SO_SNDBUF
153     int rc;
154     Socklen_t len;
155
156     /* send buffer -- query for buffer size */
157     len = sizeof( theTCPWin );
158     if ( inSend ) {
159         rc = getsockopt( inSock, SOL_SOCKET, SO_SNDBUF,
160                          (char*) &theTCPWin, &len );
161     } else {
162         rc = getsockopt( inSock, SOL_SOCKET, SO_RCVBUF,
163                          (char*) &theTCPWin, &len );
164     }
165     if ( rc < 0 ) {
166         return rc;
167     }
168
169 #endif
170
171     return theTCPWin;
172 } /* end getsock_tcp_windowsize */
173
174 #ifdef __cplusplus
175 } /* end extern "C" */
176 #endif
177