]> sjero.net Git - iperf/blob - src/ReportDefault.c
TCP Congestion Control Module via options
[iperf] / src / ReportDefault.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  * ReportDefault.c
48  * by Kevin Gibbs <kgibbs@nlanr.net>
49  *
50  * ________________________________________________________________ */
51
52 #include "headers.h"
53 #include "Settings.hpp"
54 #include "util.h"
55 #include "Reporter.h"
56 #include "report_default.h"
57 #include "Thread.h"
58 #include "Locale.h"
59 #include "PerfSocket.hpp"
60 #include "SocketAddr.h"
61
62 #ifdef __cplusplus
63 extern "C" {
64 #endif
65
66 /*
67  * Prints transfer reports in default style
68  */
69 void reporter_printstats( Transfer_Info *stats ) {
70
71     byte_snprintf( buffer, sizeof(buffer)/2, (double) stats->TotalLen,
72                    toupper( stats->mFormat));
73     byte_snprintf( &buffer[sizeof(buffer)/2], sizeof(buffer)/2,
74                    stats->TotalLen / (stats->endTime - stats->startTime), 
75                    stats->mFormat);
76
77     if ( stats->mUDP != (char)kMode_Server ) {
78         // TCP-like Reporting
79         printf( report_bw_format, stats->transferID, 
80                 stats->startTime, stats->endTime, 
81                 buffer, &buffer[sizeof(buffer)/2] );
82     } else {
83         // UDP-like Reporting
84         printf( report_bw_jitter_loss_format, stats->transferID, 
85                 stats->startTime, stats->endTime, 
86                 buffer, &buffer[sizeof(buffer)/2],
87                 stats->jitter*1000.0, stats->cntError, stats->cntDatagrams,
88                 (100.0 * stats->cntError) / stats->cntDatagrams );
89         if ( stats->cntOutofOrder > 0 ) {
90             printf( report_outoforder,
91                     stats->transferID, stats->startTime, 
92                     stats->endTime, stats->cntOutofOrder );
93         }
94     }
95     if ( stats->free == 1 && stats->mUDP == (char)kMode_Client ) {
96         printf( report_datagrams, stats->transferID, stats->cntDatagrams ); 
97     }
98 }
99
100
101 /*
102  * Prints multiple transfer reports in default style
103  */
104 void reporter_multistats( Transfer_Info *stats ) {
105
106     byte_snprintf( buffer, sizeof(buffer)/2, (double) stats->TotalLen,
107                    toupper( stats->mFormat));
108     byte_snprintf( &buffer[sizeof(buffer)/2], sizeof(buffer)/2,
109                    stats->TotalLen / (stats->endTime - stats->startTime), 
110                    stats->mFormat);
111
112     if ( stats->mUDP != (char)kMode_Server ) {
113         // TCP-like Reporting
114         printf( report_sum_bw_format, 
115                 stats->startTime, stats->endTime, 
116                 buffer, &buffer[sizeof(buffer)/2] );
117     } else {
118         // UDP-like Reporting
119         printf( report_sum_bw_jitter_loss_format, 
120                 stats->startTime, stats->endTime, 
121                 buffer, &buffer[sizeof(buffer)/2],
122                 stats->jitter*1000.0, stats->cntError, stats->cntDatagrams,
123                 (100.0 * stats->cntError) / stats->cntDatagrams );
124         if ( stats->cntOutofOrder > 0 ) {
125             printf( report_sum_outoforder,
126                     stats->startTime, 
127                     stats->endTime, stats->cntOutofOrder );
128         }
129     }
130     if ( stats->free == 1 && stats->mUDP == (char)kMode_Client ) {
131         printf( report_sum_datagrams, stats->cntDatagrams ); 
132     }
133 }
134
135 /*
136  * Prints server transfer reports in default style
137  */
138 void reporter_serverstats( Connection_Info *nused, Transfer_Info *stats ) {
139     printf( server_reporting, stats->transferID );
140     reporter_printstats( stats );
141 }
142
143 static char *McastIface(const unsigned if_index)
144 {
145         static char ifnam[IF_NAMESIZE];
146
147         if (!if_index)
148                 return "default interface";
149         if (if_indextoname(if_index, ifnam))
150                 return ifnam;
151         return "unknown interface";
152 }
153
154 /*
155  * Report the client or listener Settings in default style
156  */
157 void reporter_reportsettings( ReporterData *data ) {
158     int win, win_requested;
159
160     win = get_buffer_sock_size(data->info.transferID,
161                                data->mThreadMode != kMode_Listener);
162     win_requested = data->mWinSize;
163
164     printf( seperator_line );
165     if ( data->mThreadMode == kMode_Listener ) {
166         printf( server_port,
167                 protoName(data->mProtocol),
168                 data->mPort );
169     } else {
170         printf( client_port,
171                 data->mHost,
172                 protoName(data->mProtocol),
173                 data->mPort );
174     }
175     if ( data->mLocalhost != NULL ) {
176         if (SockAddr_isMulticast((struct sockaddr *)&data->connection.local))
177             printf(join_multicast, data->mLocalhost, McastIface(data->mMcastIface));
178         else
179             printf(bind_address, data->mLocalhost);
180     }
181
182     if ( isPacketOriented( data ) ) {
183         printf( (data->mThreadMode == kMode_Listener ? 
184                  server_datagram_size : client_datagram_size),
185                 data->mBufLen );
186         if (SockAddr_isMulticast((struct sockaddr *)&data->connection.peer))
187             printf( multicast_ttl, data->info.mTTL);
188     } else if (data->mProtocol == kProto_DCCP)
189             printf("NOTE: running in bytestream-mode (maximum speed)\n");
190
191     byte_snprintf( buffer, sizeof(buffer), win,
192                    toupper( data->info.mFormat));
193
194     if (data->mProtocol == kProto_TCP)
195         printf( "%s: %s",  tcp_window_size, buffer);
196     else
197         printf( "%s %s: %s", protoName(data->mProtocol), dgram_buffer_size, buffer);
198
199     if ( win_requested == 0 ) {
200         printf( " %s", window_default );
201     } else if ( win != win_requested ) {
202         byte_snprintf( buffer, sizeof(buffer), win_requested,
203                        toupper( data->info.mFormat));
204         printf( warn_window_requested, buffer );
205     }
206     printf( "\n" );
207
208     if (data->mProtocol == kProto_TCP) {
209         char *cong_requested = data->info.congAlgo,
210               cong[64];
211         Socklen_t len = sizeof(cong);
212
213         if (getsockopt(data->info.transferID, IPPROTO_TCP, TCP_CONGESTION, cong, &len) < 0) {
214             fprintf(stderr, "WARNING: cannot determine TCP congestion control algorithm  (err: %d %s)\n",
215                            errno, strerror(errno));
216         } else {
217             printf("TCP congestion control algorithm: %s", cong[0] == '\0' ? "default" : cong);
218
219           if (data->info.congAlgo && strcmp(cong, data->info.congAlgo))
220             printf(" (NOT \"%s\"!)", data->info.congAlgo);
221           printf("\n");
222         }
223     }
224
225     printf( seperator_line );
226 }
227
228 /*
229  * Report a socket's peer IP address in default style
230  */
231 void *reporter_reportpeer(Connection_Info *stats, int ID)
232 {
233     if (ID > 0) {
234         char     laddr[REPORT_ADDRLEN],
235                  daddr[REPORT_ADDRLEN];
236         unsigned lport = SockAddr_port(&stats->local),
237                  dport = SockAddr_port(&stats->peer);
238
239         SockAddr_name(&stats->local, laddr, sizeof(laddr));
240         SockAddr_name(&stats->peer,  daddr, sizeof(daddr));
241         printf(report_peer, ID, laddr, lport, daddr, dport);
242     }
243     return NULL;
244 }
245
246 /* -------------------------------------------------------------------
247  * Report the MSS and MTU, given the MSS (or a guess thereof)
248  * ------------------------------------------------------------------- */
249
250 // compare the MSS against the (MTU - 40) to (MTU - 80) bytes.
251 // 40 byte IP header and somewhat arbitrarily, 40 more bytes of IP options.
252
253 #define checkMSS_MTU( inMSS, inMTU ) (inMTU-40) >= inMSS  &&  inMSS >= (inMTU-80)
254
255 void reporter_reportMSS( int inMSS, thread_Settings *inSettings ) {
256     if ( inMSS <= 0 ) {
257         printf( report_mss_unsupported, inSettings->mSock );
258     } else {
259         char* net;
260         int mtu = 0;
261
262         if ( checkMSS_MTU( inMSS, 1500 ) ) {
263             net = "ethernet";
264             mtu = 1500;
265         } else if ( checkMSS_MTU( inMSS, 4352 ) ) {
266             net = "FDDI";
267             mtu = 4352;
268         } else if ( checkMSS_MTU( inMSS, 9180 ) ) {
269             net = "ATM";
270             mtu = 9180;
271         } else if ( checkMSS_MTU( inMSS, 65280 ) ) {
272             net = "HIPPI";
273             mtu = 65280;
274         } else if ( checkMSS_MTU( inMSS, 576 ) ) {
275             net = "minimum";
276             mtu = 576;
277             printf( warn_no_pathmtu );
278         } else {
279             mtu = inMSS + 40;
280             net = "unknown interface";
281         }
282
283         printf( report_mss,
284                 inSettings->mSock, inMSS, mtu, net );
285     }
286 }
287 // end ReportMSS
288
289 #ifdef __cplusplus
290 } /* end extern "C" */
291 #endif