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  * Reporter.h
48  * by Kevin Gibbs <kgibbs@nlanr.net>
49  *
50  * Since version 2.0 this handles all reporting.
51  * ________________________________________________________________ */
52 
53 #ifndef REPORTER_H
54 #define REPORTER_H
55 
56 #include "headers.h"
57 #include "Mutex.h"
58 #include "histogram.h"
59 #include "packet_ring.h"
60 
61 // forward declarations found in Settings.hpp
62 struct thread_Settings;
63 struct server_hdr;
64 
65 #include "Settings.hpp"
66 
67 #define NUM_REPORT_STRUCTS 10000
68 #define PEERVERBUFSIZE 256
69 #define NETPOWERCONSTANT 1e-6
70 #define REPORTTXTMAX 80
71 #define MINBARRIERTIMEOUT 3
72 #define PARTIALPERCENT 0.25 // used to decide if a final partial report should be displayed
73 // If the minimum latency exceeds the boundaries below
74 // assume the clocks are not synched and suppress the
75 // latency output. Units are seconds
76 #define UNREALISTIC_LATENCYMINMIN -0.01
77 #define UNREALISTIC_LATENCYMINMAX 60
78 
79 #ifdef __cplusplus
80 extern "C" {
81 #endif
82 
83 extern struct Condition ReportCond;
84 extern struct Condition ReportsPending;
85 extern int groupID;
86 extern Mutex transferid_mutex;
87 
88 /*
89  *
90  * Used for end/end latency measurements
91  *
92  */
93 struct TransitStats {
94     double maxTransit;
95     double minTransit;
96     double sumTransit;
97     double lastTransit;
98     double meanTransit;
99     double m2Transit;
100     double vdTransit;
101     int cntTransit;
102     double totmaxTransit;
103     double totminTransit;
104     double totsumTransit;
105     int totcntTransit;
106     double totmeanTransit;
107     double totm2Transit;
108     double totvdTransit;
109 };
110 
111 struct MeanMinMaxStats {
112     double max;
113     double min;
114     double sum;
115     double last;
116     double mean;
117     double m2;
118     double vd;
119     int cnt;
120     int err;
121 };
122 
123 #define TCPREADBINCOUNT 8
124 struct ReadStats {
125     int cntRead;
126     int totcntRead;
127     int bins[TCPREADBINCOUNT];
128     int totbins[TCPREADBINCOUNT];
129     int binsize;
130 };
131 
132 struct WriteStats {
133     int WriteCnt;
134     int WriteErr;
135     int totWriteCnt;
136     int totWriteErr;
137 #ifdef HAVE_STRUCT_TCP_INFO_TCPI_TOTAL_RETRANS
138     int TCPretry;
139     int totTCPretry;
140     int cwnd;
141     int rtt;
142 #endif
143 };
144 
145 /*
146  * This struct contains all important information from the sending or
147  * recieving thread.
148  */
149 #define L2UNKNOWN  0x01
150 #define L2LENERR   0x02
151 #define L2CSUMERR  0x04
152 
153 enum WriteErrType {
154     WriteNoErr  = 0,
155     WriteErrAccount,
156     WriteErrFatal,
157     WriteErrNoAccount,
158 };
159 
160 struct L2Stats {
161     intmax_t cnt;
162     intmax_t unknown;
163     intmax_t udpcsumerr;
164     intmax_t lengtherr;
165     intmax_t tot_cnt;
166     intmax_t tot_unknown;
167     intmax_t tot_udpcsumerr;
168     intmax_t tot_lengtherr;
169 };
170 
171 /*
172  * The type field of ReporterData is a bitmask
173  * with one or more of the following
174  */
175 enum ReportType {
176     DATA_REPORT = 1,
177     SUM_REPORT,
178     SETTINGS_REPORT,
179     CONNECTION_REPORT,
180     SERVER_RELAY_REPORT
181 };
182 
183 enum ReportSubType {
184     FULLDUPLEXSUM_REPORT = 1,
185     HOSTSUM_REPORT,
186     TOTALSUM_REPORT
187 };
188 
189 union SendReadStats {
190     struct ReadStats read;
191     struct WriteStats write;
192 };
193 
194 // This attributes are shared by all reports
195 // deep copies are made when creating a new report
196 // rather than using references
197 struct ReportCommon {
198     enum ThreadMode ThreadMode;
199     enum ReportMode ReportMode;
200     bool KeyCheck;
201     int flags;
202     int flags_extend;
203     int flags_extend2;
204     int threads;
205     unsigned short Port;
206     unsigned short PortLast;
207     unsigned short BindPort;
208     unsigned short ListenPort;
209     intmax_t AppRate;            // -b or -u
210     uint32_t BurstSize;
211     int AppRateUnits;
212     char Format;
213     int TTL;
214     int BufLen;
215     int MSS;
216     int TCPWin;
217 #if HAVE_DECL_TCP_WINDOW_CLAMP
218     int ClampSize;
219 #endif
220 #if HAVE_DECL_TCP_NOTSENT_LOWAT
221     int WritePrefetch;
222 #endif
223     int winsize_requested;
224     unsigned int FQPacingRate;
225     int HistBins;
226     int HistBinsize;
227     int HistUnits;
228     double pktIPG;
229     iperf_sockaddr peer;
230     Socklen_t size_peer;
231     iperf_sockaddr local;
232     Socklen_t size_local;
233     char* Host;                   // -c
234     char* HideHost;
235     char* Localhost;              // -B
236     char* Ifrname;
237     char* Ifrnametx;
238     char* SSMMulticastStr;
239     char* Congestion;
240     char* transferIDStr;
241     char* PermitKey;
242     int transferID;
243     double rtt_weight;
244     double ListenerTimeout;
245     double FPS;
246 #ifdef HAVE_STRUCT_TCP_INFO_TCPI_TOTAL_RETRANS
247     bool enable_sampleTCPstats;
248     bool intervalonly_sampleTCPstats;
249 #endif
250 #if WIN32
251     SOCKET socket;
252 #else
253     int socket;
254 #if defined(HAVE_LINUX_FILTER_H) && defined(HAVE_AF_PACKET)
255     int socketdrop;
256 #endif
257 #endif
258 };
259 
260 struct ConnectionInfo {
261     struct ReportCommon *common;
262     struct timeval connect_timestamp;
263     double connecttime;
264     struct timeval txholdbacktime;
265     struct timeval epochStartTime;
266     int winsize;
267     char peerversion[PEERVERBUFSIZE];
268     struct MeanMinMaxStats connect_times;
269     int MSS;
270 };
271 
272 struct ShiftIntCounter {
273     intmax_t current;
274     intmax_t prev;
275 };
276 
277 struct ShiftUintCounter {
278     uintmax_t current;
279     uintmax_t prev;
280 };
281 
282 struct ShiftCounters {
283     struct ShiftUintCounter Bytes;
284     struct ShiftIntCounter Lost;
285     struct ShiftIntCounter OutofOrder;
286     struct ShiftIntCounter Datagrams;
287     struct ShiftIntCounter IPG;
288 };
289 
290 struct IsochStats {
291     double mFPS; //frames per second
292     double mMean; //variable bit rate mean
293     double mVariance; //vbr variance
294     int mJitterBufSize; //Server jitter buffer size, units is frames
295     uintmax_t cntFrames;
296     uintmax_t cntFramesMissed;
297     uintmax_t cntSlips;
298     struct ShiftUintCounter slipcnt;
299     struct ShiftUintCounter framecnt;
300     struct ShiftUintCounter framelostcnt;
301     unsigned int mBurstInterval;
302     unsigned int mBurstIPG; //IPG of packets within the burst
303     uint32_t frameID;
304 };
305 
306 struct ReportSettings {
307     struct ReportCommon *common;
308     iperf_sockaddr peer;
309     Socklen_t size_peer;
310     iperf_sockaddr local;
311     Socklen_t size_local;
312     int pid;
313     struct IsochStats isochstats;
314     void (*output_handler) (struct ReportSettings *settings);
315 };
316 
317 // Timestamps
318 enum TimeStampType {
319     INTERVAL  = 0,
320     FINALPARTIAL,
321     TOTAL,
322     FRAME
323 };
324 
325 struct ReportTimeStamps {
326     double iStart;
327     double iEnd;
328     double significant_partial;
329     struct timeval startTime;
330     struct timeval matchTime;
331     struct timeval packetTime;
332     struct timeval prevpacketTime;
333     struct timeval prevsendTime;
334     struct timeval nextTime;
335     struct timeval intervalTime;
336     struct timeval IPGstart;
337 #ifdef HAVE_STRUCT_TCP_INFO_TCPI_TOTAL_RETRANS
338     struct timeval nextTCPStampleTime;
339 #endif
340 };
341 
342 struct TransferInfo {
343     struct ReportCommon *common;
344     struct ReportTimeStamps ts;
345     void (*output_handler) (struct TransferInfo *stats);
346     int groupID;
347     int threadcnt;
348     int filter_this_sample_output;
349     uintmax_t cntBytes;
350     intmax_t cntError;
351     intmax_t cntOutofOrder;
352     intmax_t cntDatagrams;
353     intmax_t cntIPG;
354     intmax_t PacketID;
355     double jitter;
356     double tripTime;
357     double IPGsum;
358     struct ShiftCounters total; // Shift counters used to calculate interval reports and hold totals
359     union SendReadStats sock_callstats;
360     struct IsochStats isochstats;
361     struct histogram *latency_histogram;
362     struct TransitStats transit;
363     struct histogram *framelatency_histogram;
364     struct TransitStats frame;
365     struct L2Stats l2counts;
366     // Packet and frame state info
367     uint32_t matchframeID;
368     uint32_t frameID;
369     char csv_peer[CSVPEERLIMIT];
370     bool final;
371     bool burstid_transition;
372 };
373 
374 struct SumReport {
375     struct ReferenceMutex reference;
376     int threads;
377     struct TransferInfo info;
378     void (*transfer_protocol_sum_handler) (struct TransferInfo *stats, int final);
379     struct BarrierMutex fullduplex_barrier;
380     int sum_fd_set;
381 };
382 
383 struct ReporterData {
384     // function pointer for per packet processing
385     void (*packet_handler_pre_report) (struct ReporterData *data, struct ReportStruct *packet);
386     void (*packet_handler_post_report) (struct ReporterData *data, struct ReportStruct *packet);
387     void (*transfer_protocol_handler) (struct ReporterData *data, int final);
388     int (*transfer_interval_handler) (struct ReporterData *data, struct ReportStruct *packet);
389 
390     struct PacketRing *packetring;
391     int reporter_thread_suspends; // used to detect CPU bound systems
392 
393     // group sum and full duplext reports
394     struct SumReport *GroupSumReport;
395     struct SumReport *FullDuplexReport;
396     struct TransferInfo info;
397 };
398 
399 struct ServerRelay {
400     struct TransferInfo info;
401     iperf_sockaddr peer;
402     Socklen_t size_peer;
403     iperf_sockaddr local;
404     Socklen_t size_local;
405 };
406 
407 struct ReportHeader {
408     enum ReportType type;
409     enum ReportMode ReportMode;
410     void *this_report;
411     struct ReportHeader *next;
412 };
413 
414 typedef void* (* report_connection)( struct ConnectionInfo*, int );
415 typedef void (* report_settings)( struct ReporterData* );
416 typedef void (* report_statistics)( struct TransferInfo* );
417 typedef void (* report_serverstatistics)( struct ConnectionInfo *, struct TransferInfo* );
418 
419 void SetSumHandlers (struct thread_Settings *inSettings, struct SumReport* sumreport);
420 struct SumReport* InitSumReport(struct thread_Settings *inSettings, int inID, int fullduplex);
421 struct ReportHeader* InitIndividualReport(struct thread_Settings *inSettings);
422 struct ReportHeader* InitConnectionReport(struct thread_Settings *inSettings, double ct);
423 struct ConnectionInfo* InitConnectOnlyReport(struct thread_Settings *thread);
424 struct ReportHeader *InitSettingsReport(struct thread_Settings *inSettings);
425 struct ReportHeader* InitServerRelayUDPReport(struct thread_Settings *inSettings, struct server_hdr *server);
426 void PostReport(struct ReportHeader *reporthdr);
427 #ifdef HAVE_STRUCT_TCP_INFO_TCPI_TOTAL_RETRANS
428 bool ReportPacket (struct ReporterData* data, struct ReportStruct *packet, struct tcp_info *tcp_stats);
429 #else
430 void ReportPacket (struct ReporterData* data, struct ReportStruct *packet);
431 #endif
432 int EndJob(struct ReportHeader *reporthdr,  struct ReportStruct *packet);
433 void FreeReport(struct ReportHeader *reporthdr);
434 void FreeSumReport (struct SumReport *sumreport);
435 void FreeConnectionReport(struct ConnectionInfo *reporthdr);
436 void ReportServerUDP(struct thread_Settings *inSettings, struct server_hdr *server);
437 void ReportConnections(struct thread_Settings *inSettings );
438 void reporter_dump_job_queue(void);
439 void IncrSumReportRefCounter(struct SumReport *sumreport);
440 int DecrSumReportRefCounter(struct SumReport *sumreport);
441 
442 extern struct AwaitMutex reporter_state;
443 extern struct AwaitMutex threads_start;
444 
445 extern report_connection connection_reports[];
446 extern report_settings settings_reports[];
447 extern report_statistics statistics_reports[];
448 extern report_serverstatistics serverstatistics_reports[];
449 extern report_statistics multiple_reports[];
450 
451 
452 // Packet accounting routines
453 void reporter_handle_packet_null(struct ReporterData *report, struct ReportStruct *packet);
454 void reporter_handle_packet_server_udp(struct ReporterData *data, struct ReportStruct *packet);
455 void reporter_handle_packet_server_tcp(struct ReporterData *data, struct ReportStruct *packet);
456 void reporter_handle_packet_client(struct ReporterData *data, struct ReportStruct *packet);
457 void reporter_handle_packet_pps(struct ReporterData *data, struct ReportStruct *packet);
458 void reporter_handle_packet_isochronous(struct ReporterData *data, struct ReportStruct *packet);
459 
460 // Reporter's conditional prints, right now have time and frame based sampling, possibly add packet based
461 int reporter_condprint_time_interval_report(struct ReporterData *data, struct ReportStruct *packet);
462 int reporter_condprint_frame_interval_report_client_udp(struct ReporterData *reporthdr, struct ReportStruct *packet);
463 int reporter_condprint_frame_interval_report_server_udp(struct ReporterData *data, struct ReportStruct *packet);
464 int reporter_condprint_frame_interval_report_server_tcp(struct ReporterData *data, struct ReportStruct *packet);
465 int reporter_condprint_frame_interval_report_client_tcp(struct ReporterData *reporthdr, struct ReportStruct *packet);
466 int reporter_condprint_burst_interval_report_client_udp(struct ReporterData *reporthdr, struct ReportStruct *packet);
467 int reporter_condprint_burst_interval_report_server_udp(struct ReporterData *data, struct ReportStruct *packet);
468 int reporter_condprint_burst_interval_report_server_tcp(struct ReporterData *data, struct ReportStruct *packet);
469 int reporter_condprint_burst_interval_report_client_tcp(struct ReporterData *reporthdr, struct ReportStruct *packet);
470 //void reporter_set_timestamps_time(struct ReporterData *stats, enum TimestampType);
471 
472 // Reporter's interval output specialize routines
473 void reporter_transfer_protocol_null(struct ReporterData *stats, int final);
474 //void reporter_transfer_protocol_reports(struct ReporterData *stats, struct ReportStruct *packet);
475 //void reporter_transfer_protocol_multireports(struct ReporterData *stats, struct ReportStruct *packet);
476 void reporter_transfer_protocol_client_tcp(struct ReporterData *data, int final);
477 void reporter_transfer_protocol_client_udp(struct ReporterData *data, int final);
478 void reporter_transfer_protocol_server_tcp(struct ReporterData *data, int final);
479 void reporter_transfer_protocol_server_udp(struct ReporterData *data, int final);
480 
481 // Reporter's sum output routines (per -P > 1)
482 void reporter_transfer_protocol_sum_client_tcp(struct TransferInfo *stats, int final);
483 void reporter_transfer_protocol_sum_server_tcp(struct TransferInfo *stats, int final);
484 void reporter_transfer_protocol_sum_client_udp(struct TransferInfo *stats, int final);
485 void reporter_transfer_protocol_sum_server_udp(struct TransferInfo *stats, int final);
486 void reporter_transfer_protocol_fullduplex_tcp(struct TransferInfo *stats, int final);
487 void reporter_transfer_protocol_fullduplex_udp(struct TransferInfo *stats, int final);
488 
489 
490 // Reporter print routines
491 // TCP server
492 void tcp_output_read(struct TransferInfo *stats);
493 void tcp_output_read_enhanced(struct TransferInfo *stats);
494 void tcp_output_read_enhanced_triptime(struct TransferInfo *stats);
495 void tcp_output_sum_read(struct TransferInfo *stats);
496 void tcp_output_sum_read_enhanced(struct TransferInfo *stats);
497 void tcp_output_sumcnt_read(struct TransferInfo *stats);
498 void tcp_output_sumcnt_read_enhanced (struct TransferInfo *stats);
499 void tcp_output_frame_read(struct TransferInfo *stats);
500 void tcp_output_frame_read_triptime(struct TransferInfo *stats);
501 void tcp_output_burst_read(struct TransferInfo *stats);
502 
503 // TCP client
504 void tcp_output_write(struct TransferInfo *stats);
505 void tcp_output_sum_write(struct TransferInfo *stats);
506 void tcp_output_sumcnt_write(struct TransferInfo *stats);
507 void tcp_output_write_enhanced (struct TransferInfo *stats);
508 void tcp_output_write_enhanced_isoch (struct TransferInfo *stats);
509 void tcp_output_sum_write_enhanced (struct TransferInfo *stats);
510 void tcp_output_sumcnt_write_enhanced (struct TransferInfo *stats);
511 // TCP fullduplex
512 void tcp_output_fullduplex(struct TransferInfo *stats);
513 void tcp_output_fullduplex_enhanced(struct TransferInfo *stats);
514 void tcp_output_fullduplex_sum (struct TransferInfo *stats);
515 
516 // UDP server
517 void udp_output_read(struct TransferInfo *stats);
518 void udp_output_read_enhanced(struct TransferInfo *stats);
519 void udp_output_read_enhanced_triptime(struct TransferInfo *stats);
520 void udp_output_read_enhanced_triptime_isoch(struct TransferInfo *stats);
521 void udp_output_sum_read(struct TransferInfo *stats);
522 void udp_output_sum_read_enhanced (struct TransferInfo *stats);
523 void udp_output_sumcnt(struct TransferInfo *stats);
524 void udp_output_sumcnt_read_enhanced (struct TransferInfo *stats);
525 
526 //UDP client
527 void udp_output_write(struct TransferInfo *stats);
528 void udp_output_sum_write(struct TransferInfo *stats);
529 void udp_output_write_enhanced(struct TransferInfo *stats);
530 void udp_output_write_enhanced_isoch(struct TransferInfo *stats);
531 void udp_output_sum_write_enhanced (struct TransferInfo *stats);
532 void udp_output_sumcnt_write(struct TransferInfo *stats);
533 void udp_output_sumcnt_write_enhanced (struct TransferInfo *stats);
534 void udp_output_sumcnt_enhanced(struct TransferInfo *stats);
535 // UDP full duplex
536 void udp_output_fullduplex(struct TransferInfo *stats);
537 void udp_output_fullduplex_enhanced(struct TransferInfo *stats);
538 void udp_output_fullduplex_sum(struct TransferInfo *stats);
539 
540 
541 // CSV output
542 void udp_output_basic_csv(struct TransferInfo *stats);
543 void tcp_output_basic_csv(struct TransferInfo *stats);
544 
545 // Rest of the reporter output routines
546 void reporter_print_connection_report(struct ConnectionInfo *report);
547 void reporter_print_settings_report(struct ReportSettings *report);
548 void reporter_print_server_relay_report(struct ServerRelay *report);
549 void reporter_peerversion (struct ConnectionInfo *report, uint32_t upper, uint32_t lower);
550 void PrintMSS(struct ReporterData *data);
551 void reporter_default_heading_flags(int);
552 void reporter_connect_printf_tcp_final(struct ConnectionInfo *report);
553 
554 void write_UDP_AckFIN(struct TransferInfo *stats, int len);
555 
556 int reporter_process_transfer_report (struct ReporterData *this_ireport);
557 int reporter_process_report (struct ReportHeader *reporthdr);
558 
559 void setTransferID(struct thread_Settings *inSettings, int role_reversal);
560 
561 #ifdef __cplusplus
562 } /* end extern "C" */
563 #endif
564 
565 #endif // REPORTER_H
566