]> sjero.net Git - iperf/blob - src/ReportDefault.c
7944e038e07295c37e69869a4b10743c86dc1c7b
[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 Reporting
79         printf( report_bw_format, stats->transferID, 
80                 stats->startTime, stats->endTime, 
81                 buffer, &buffer[sizeof(buffer)/2] );
82     } else {
83         // UDP 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 Reporting
114         printf( report_sum_bw_format, 
115                 stats->startTime, stats->endTime, 
116                 buffer, &buffer[sizeof(buffer)/2] );
117     } else {
118         // UDP 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 /*
144  * Report the client or listener Settings in default style
145  */
146 void reporter_reportsettings( ReporterData *data ) {
147     int win, win_requested;
148
149     win = getsock_tcp_windowsize( data->info.transferID,
150                   (data->mThreadMode == kMode_Listener ? 0 : 1) );
151     win_requested = data->mTCPWin;
152
153     printf( seperator_line );
154     if ( data->mThreadMode == kMode_Listener ) {
155         printf( server_port,
156                 (isUDP( data ) ? "UDP" : "TCP"), 
157                 data->mPort );
158     } else {
159         printf( client_port,
160                 data->mHost,
161                 (isUDP( data ) ? "UDP" : "TCP"),
162                 data->mPort );
163     }
164     if ( data->mLocalhost != NULL ) {
165         printf( bind_address, data->mLocalhost );
166         if ( SockAddr_isMulticast( &data->connection.local ) ) {
167             printf( join_multicast, data->mLocalhost );
168         }
169     }
170
171     if ( isUDP( data ) ) {
172         printf( (data->mThreadMode == kMode_Listener ? 
173                                    server_datagram_size : client_datagram_size),
174                 data->mBufLen );
175         if ( SockAddr_isMulticast( &data->connection.peer ) ) {
176             printf( multicast_ttl, data->info.mTTL);
177         }
178     }
179     byte_snprintf( buffer, sizeof(buffer), win,
180                    toupper( data->info.mFormat));
181     printf( "%s: %s", (isUDP( data ) ? 
182                                 udp_buffer_size : tcp_window_size), buffer );
183
184     if ( win_requested == 0 ) {
185         printf( " %s", window_default );
186     } else if ( win != win_requested ) {
187         byte_snprintf( buffer, sizeof(buffer), win_requested,
188                        toupper( data->info.mFormat));
189         printf( warn_window_requested, buffer );
190     }
191     printf( "\n" );
192     printf( seperator_line );
193 }
194
195 /*
196  * Report a socket's peer IP address in default style
197  */
198 void *reporter_reportpeer( Connection_Info *stats, int ID ) {
199     if ( ID > 0 ) {
200         // copy the inet_ntop into temp buffers, to avoid overwriting
201         char local_addr[ REPORT_ADDRLEN ];
202         char remote_addr[ REPORT_ADDRLEN ];
203         struct sockaddr *local = ((struct sockaddr*)&stats->local);
204         struct sockaddr *peer = ((struct sockaddr*)&stats->peer);
205     
206         if ( local->sa_family == AF_INET ) {
207             inet_ntop( AF_INET, &((struct sockaddr_in*)local)->sin_addr, 
208                        local_addr, REPORT_ADDRLEN);
209         }
210 #ifdef HAVE_IPV6
211           else {
212             inet_ntop( AF_INET6, &((struct sockaddr_in6*)local)->sin6_addr, 
213                        local_addr, REPORT_ADDRLEN);
214         }
215 #endif
216     
217         if ( peer->sa_family == AF_INET ) {
218             inet_ntop( AF_INET, &((struct sockaddr_in*)peer)->sin_addr, 
219                        remote_addr, REPORT_ADDRLEN);
220         }
221 #ifdef HAVE_IPV6
222           else {
223             inet_ntop( AF_INET6, &((struct sockaddr_in6*)peer)->sin6_addr, 
224                        remote_addr, REPORT_ADDRLEN);
225         }
226 #endif
227     
228         printf( report_peer,
229                 ID,
230                 local_addr,  ( local->sa_family == AF_INET ?
231                               ntohs(((struct sockaddr_in*)local)->sin_port) :
232 #ifdef HAVE_IPV6
233                               ntohs(((struct sockaddr_in6*)local)->sin6_port)),
234 #else
235                               0),
236 #endif
237                 remote_addr, ( peer->sa_family == AF_INET ?
238                               ntohs(((struct sockaddr_in*)peer)->sin_port) :
239 #ifdef HAVE_IPV6
240                               ntohs(((struct sockaddr_in6*)peer)->sin6_port)));
241 #else
242                               0));
243 #endif
244     }
245     return NULL;
246 }
247 // end ReportPeer
248
249 /* -------------------------------------------------------------------
250  * Report the MSS and MTU, given the MSS (or a guess thereof)
251  * ------------------------------------------------------------------- */
252
253 // compare the MSS against the (MTU - 40) to (MTU - 80) bytes.
254 // 40 byte IP header and somewhat arbitrarily, 40 more bytes of IP options.
255
256 #define checkMSS_MTU( inMSS, inMTU ) (inMTU-40) >= inMSS  &&  inMSS >= (inMTU-80)
257
258 void reporter_reportMSS( int inMSS, thread_Settings *inSettings ) {
259     if ( inMSS <= 0 ) {
260         printf( report_mss_unsupported, inSettings->mSock );
261     } else {
262         char* net;
263         int mtu = 0;
264
265         if ( checkMSS_MTU( inMSS, 1500 ) ) {
266             net = "ethernet";
267             mtu = 1500;
268         } else if ( checkMSS_MTU( inMSS, 4352 ) ) {
269             net = "FDDI";
270             mtu = 4352;
271         } else if ( checkMSS_MTU( inMSS, 9180 ) ) {
272             net = "ATM";
273             mtu = 9180;
274         } else if ( checkMSS_MTU( inMSS, 65280 ) ) {
275             net = "HIPPI";
276             mtu = 65280;
277         } else if ( checkMSS_MTU( inMSS, 576 ) ) {
278             net = "minimum";
279             mtu = 576;
280             printf( warn_no_pathmtu );
281         } else {
282             mtu = inMSS + 40;
283             net = "unknown interface";
284         }
285
286         printf( report_mss,
287                 inSettings->mSock, inMSS, mtu, net );
288     }
289 }
290 // end ReportMSS
291
292 #ifdef __cplusplus
293 } /* end extern "C" */
294 #endif