1 /*
2 * iperf, Copyright (c) 2014-2018, The Regents of the University of
3 * California, through Lawrence Berkeley National Laboratory (subject
4 * to receipt of any required approvals from the U.S. Dept. of
5 * Energy). All rights reserved.
6 *
7 * If you have questions about your rights to use or distribute this
8 * software, please contact Berkeley Lab's Technology Transfer
9 * Department at TTD@lbl.gov.
10 *
11 * NOTICE. This software is owned by the U.S. Department of Energy.
12 * As such, the U.S. Government has been granted for itself and others
13 * acting on its behalf a paid-up, nonexclusive, irrevocable,
14 * worldwide license in the Software to reproduce, prepare derivative
15 * works, and perform publicly and display publicly. Beginning five
16 * (5) years after the date permission to assert copyright is obtained
17 * from the U.S. Department of Energy, and subject to any subsequent
18 * five (5) year renewals, the U.S. Government is granted for itself
19 * and others acting on its behalf a paid-up, nonexclusive,
20 * irrevocable, worldwide license in the Software to reproduce,
21 * prepare derivative works, distribute copies to the public, perform
22 * publicly and display publicly, and to permit others to do so.
23 *
24 * This code is distributed under a BSD style license, see the LICENSE file
25 * for complete information.
26 */
27 #ifndef _GNU_SOURCE
28 # define _GNU_SOURCE
29 #endif
30 #define __USE_GNU
31
32 #include "iperf_config.h"
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <time.h>
38 #include <getopt.h>
39 #include <errno.h>
40 #include <signal.h>
41 #include <unistd.h>
42 #include <assert.h>
43 #include <fcntl.h>
44 #include <sys/socket.h>
45 #include <sys/types.h>
46 #include <netinet/in.h>
47 #include <arpa/inet.h>
48 #include <netdb.h>
49 #ifdef HAVE_STDINT_H
50 #include <stdint.h>
51 #endif
52 #include <netinet/tcp.h>
53 #include <sys/time.h>
54 #include <sys/resource.h>
55 #include <sys/mman.h>
56 #include <sys/stat.h>
57 #include <sched.h>
58 #include <setjmp.h>
59 #include <stdarg.h>
60
61 #if defined(HAVE_CPUSET_SETAFFINITY)
62 #include <sys/param.h>
63 #include <sys/cpuset.h>
64 #endif /* HAVE_CPUSET_SETAFFINITY */
65
66 #if defined(HAVE_SETPROCESSAFFINITYMASK)
67 #include <Windows.h>
68 #endif /* HAVE_SETPROCESSAFFINITYMASK */
69
70 #include "net.h"
71 #include "iperf.h"
72 #include "iperf_api.h"
73 #include "iperf_udp.h"
74 #include "iperf_tcp.h"
75 #if defined(HAVE_SCTP)
76 #include "iperf_sctp.h"
77 #endif /* HAVE_SCTP */
78 #include "timer.h"
79
80 #include "cjson.h"
81 #include "units.h"
82 #include "iperf_util.h"
83 #include "iperf_locale.h"
84 #include "version.h"
85 #if defined(HAVE_SSL)
86 #include <openssl/bio.h>
87 #include "iperf_auth.h"
88 #endif /* HAVE_SSL */
89
90 /* Forwards. */
91 static int send_parameters(struct iperf_test *test);
92 static int get_parameters(struct iperf_test *test);
93 static int send_results(struct iperf_test *test);
94 static int get_results(struct iperf_test *test);
95 static int diskfile_send(struct iperf_stream *sp);
96 static int diskfile_recv(struct iperf_stream *sp);
97 static int JSON_write(int fd, cJSON *json);
98 static void print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *json_interval_streams);
99 static cJSON *JSON_read(int fd);
100
101
102 /*************************** Print usage functions ****************************/
103
104 void
usage()105 usage()
106 {
107 fputs(usage_shortstr, stderr);
108 }
109
110
111 void
usage_long(FILE * f)112 usage_long(FILE *f)
113 {
114 fprintf(f, usage_longstr, UDP_RATE / (1024*1024), DURATION, DEFAULT_TCP_BLKSIZE / 1024, DEFAULT_UDP_BLKSIZE);
115 }
116
117
warning(char * str)118 void warning(char *str)
119 {
120 fprintf(stderr, "warning: %s\n", str);
121 }
122
123
124 /************** Getter routines for some fields inside iperf_test *************/
125
126 int
iperf_get_verbose(struct iperf_test * ipt)127 iperf_get_verbose(struct iperf_test *ipt)
128 {
129 return ipt->verbose;
130 }
131
132 int
iperf_get_control_socket(struct iperf_test * ipt)133 iperf_get_control_socket(struct iperf_test *ipt)
134 {
135 return ipt->ctrl_sck;
136 }
137
138 int
iperf_get_control_socket_mss(struct iperf_test * ipt)139 iperf_get_control_socket_mss(struct iperf_test *ipt)
140 {
141 return ipt->ctrl_sck_mss;
142 }
143
144 int
iperf_get_test_omit(struct iperf_test * ipt)145 iperf_get_test_omit(struct iperf_test *ipt)
146 {
147 return ipt->omit;
148 }
149
150 int
iperf_get_test_duration(struct iperf_test * ipt)151 iperf_get_test_duration(struct iperf_test *ipt)
152 {
153 return ipt->duration;
154 }
155
156 uint64_t
iperf_get_test_rate(struct iperf_test * ipt)157 iperf_get_test_rate(struct iperf_test *ipt)
158 {
159 return ipt->settings->rate;
160 }
161
162 uint64_t
iperf_get_test_fqrate(struct iperf_test * ipt)163 iperf_get_test_fqrate(struct iperf_test *ipt)
164 {
165 return ipt->settings->fqrate;
166 }
167
168 int
iperf_get_test_pacing_timer(struct iperf_test * ipt)169 iperf_get_test_pacing_timer(struct iperf_test *ipt)
170 {
171 return ipt->settings->pacing_timer;
172 }
173
174 uint64_t
iperf_get_test_bytes(struct iperf_test * ipt)175 iperf_get_test_bytes(struct iperf_test *ipt)
176 {
177 return (uint64_t) ipt->settings->bytes;
178 }
179
180 uint64_t
iperf_get_test_blocks(struct iperf_test * ipt)181 iperf_get_test_blocks(struct iperf_test *ipt)
182 {
183 return (uint64_t) ipt->settings->blocks;
184 }
185
186 int
iperf_get_test_burst(struct iperf_test * ipt)187 iperf_get_test_burst(struct iperf_test *ipt)
188 {
189 return ipt->settings->burst;
190 }
191
192 char
iperf_get_test_role(struct iperf_test * ipt)193 iperf_get_test_role(struct iperf_test *ipt)
194 {
195 return ipt->role;
196 }
197
198 int
iperf_get_test_reverse(struct iperf_test * ipt)199 iperf_get_test_reverse(struct iperf_test *ipt)
200 {
201 return ipt->reverse;
202 }
203
204 int
iperf_get_test_blksize(struct iperf_test * ipt)205 iperf_get_test_blksize(struct iperf_test *ipt)
206 {
207 return ipt->settings->blksize;
208 }
209
210 FILE *
iperf_get_test_outfile(struct iperf_test * ipt)211 iperf_get_test_outfile (struct iperf_test *ipt)
212 {
213 return ipt->outfile;
214 }
215
216 int
iperf_get_test_socket_bufsize(struct iperf_test * ipt)217 iperf_get_test_socket_bufsize(struct iperf_test *ipt)
218 {
219 return ipt->settings->socket_bufsize;
220 }
221
222 double
iperf_get_test_reporter_interval(struct iperf_test * ipt)223 iperf_get_test_reporter_interval(struct iperf_test *ipt)
224 {
225 return ipt->reporter_interval;
226 }
227
228 double
iperf_get_test_stats_interval(struct iperf_test * ipt)229 iperf_get_test_stats_interval(struct iperf_test *ipt)
230 {
231 return ipt->stats_interval;
232 }
233
234 int
iperf_get_test_num_streams(struct iperf_test * ipt)235 iperf_get_test_num_streams(struct iperf_test *ipt)
236 {
237 return ipt->num_streams;
238 }
239
240 int
iperf_get_test_server_port(struct iperf_test * ipt)241 iperf_get_test_server_port(struct iperf_test *ipt)
242 {
243 return ipt->server_port;
244 }
245
246 char*
iperf_get_test_server_hostname(struct iperf_test * ipt)247 iperf_get_test_server_hostname(struct iperf_test *ipt)
248 {
249 return ipt->server_hostname;
250 }
251
252 char*
iperf_get_test_template(struct iperf_test * ipt)253 iperf_get_test_template(struct iperf_test *ipt)
254 {
255 return ipt->tmp_template;
256 }
257
258 int
iperf_get_test_protocol_id(struct iperf_test * ipt)259 iperf_get_test_protocol_id(struct iperf_test *ipt)
260 {
261 return ipt->protocol->id;
262 }
263
264 int
iperf_get_test_json_output(struct iperf_test * ipt)265 iperf_get_test_json_output(struct iperf_test *ipt)
266 {
267 return ipt->json_output;
268 }
269
270 char *
iperf_get_test_json_output_string(struct iperf_test * ipt)271 iperf_get_test_json_output_string(struct iperf_test *ipt)
272 {
273 return ipt->json_output_string;
274 }
275
276 int
iperf_get_test_zerocopy(struct iperf_test * ipt)277 iperf_get_test_zerocopy(struct iperf_test *ipt)
278 {
279 return ipt->zerocopy;
280 }
281
282 int
iperf_get_test_get_server_output(struct iperf_test * ipt)283 iperf_get_test_get_server_output(struct iperf_test *ipt)
284 {
285 return ipt->get_server_output;
286 }
287
288 char
iperf_get_test_unit_format(struct iperf_test * ipt)289 iperf_get_test_unit_format(struct iperf_test *ipt)
290 {
291 return ipt->settings->unit_format;
292 }
293
294 char *
iperf_get_test_bind_address(struct iperf_test * ipt)295 iperf_get_test_bind_address(struct iperf_test *ipt)
296 {
297 return ipt->bind_address;
298 }
299
300 int
iperf_get_test_udp_counters_64bit(struct iperf_test * ipt)301 iperf_get_test_udp_counters_64bit(struct iperf_test *ipt)
302 {
303 return ipt->udp_counters_64bit;
304 }
305
306 int
iperf_get_test_one_off(struct iperf_test * ipt)307 iperf_get_test_one_off(struct iperf_test *ipt)
308 {
309 return ipt->one_off;
310 }
311
312 int
iperf_get_test_tos(struct iperf_test * ipt)313 iperf_get_test_tos(struct iperf_test *ipt)
314 {
315 return ipt->settings->tos;
316 }
317
318 char *
iperf_get_test_extra_data(struct iperf_test * ipt)319 iperf_get_test_extra_data(struct iperf_test *ipt)
320 {
321 return ipt->extra_data;
322 }
323
324 static const char iperf_version[] = IPERF_VERSION;
325 char *
iperf_get_iperf_version(void)326 iperf_get_iperf_version(void)
327 {
328 return (char*)iperf_version;
329 }
330
331 /************** Setter routines for some fields inside iperf_test *************/
332
333 void
iperf_set_verbose(struct iperf_test * ipt,int verbose)334 iperf_set_verbose(struct iperf_test *ipt, int verbose)
335 {
336 ipt->verbose = verbose;
337 }
338
339 void
iperf_set_control_socket(struct iperf_test * ipt,int ctrl_sck)340 iperf_set_control_socket(struct iperf_test *ipt, int ctrl_sck)
341 {
342 ipt->ctrl_sck = ctrl_sck;
343 }
344
345 void
iperf_set_test_omit(struct iperf_test * ipt,int omit)346 iperf_set_test_omit(struct iperf_test *ipt, int omit)
347 {
348 ipt->omit = omit;
349 }
350
351 void
iperf_set_test_duration(struct iperf_test * ipt,int duration)352 iperf_set_test_duration(struct iperf_test *ipt, int duration)
353 {
354 ipt->duration = duration;
355 }
356
357 void
iperf_set_test_reporter_interval(struct iperf_test * ipt,double reporter_interval)358 iperf_set_test_reporter_interval(struct iperf_test *ipt, double reporter_interval)
359 {
360 ipt->reporter_interval = reporter_interval;
361 }
362
363 void
iperf_set_test_stats_interval(struct iperf_test * ipt,double stats_interval)364 iperf_set_test_stats_interval(struct iperf_test *ipt, double stats_interval)
365 {
366 ipt->stats_interval = stats_interval;
367 }
368
369 void
iperf_set_test_state(struct iperf_test * ipt,signed char state)370 iperf_set_test_state(struct iperf_test *ipt, signed char state)
371 {
372 ipt->state = state;
373 }
374
375 void
iperf_set_test_blksize(struct iperf_test * ipt,int blksize)376 iperf_set_test_blksize(struct iperf_test *ipt, int blksize)
377 {
378 ipt->settings->blksize = blksize;
379 }
380
381 void
iperf_set_test_rate(struct iperf_test * ipt,uint64_t rate)382 iperf_set_test_rate(struct iperf_test *ipt, uint64_t rate)
383 {
384 ipt->settings->rate = rate;
385 }
386
387 void
iperf_set_test_fqrate(struct iperf_test * ipt,uint64_t fqrate)388 iperf_set_test_fqrate(struct iperf_test *ipt, uint64_t fqrate)
389 {
390 ipt->settings->fqrate = fqrate;
391 }
392
393 void
iperf_set_test_pacing_timer(struct iperf_test * ipt,int pacing_timer)394 iperf_set_test_pacing_timer(struct iperf_test *ipt, int pacing_timer)
395 {
396 ipt->settings->pacing_timer = pacing_timer;
397 }
398
399 void
iperf_set_test_bytes(struct iperf_test * ipt,uint64_t bytes)400 iperf_set_test_bytes(struct iperf_test *ipt, uint64_t bytes)
401 {
402 ipt->settings->bytes = (iperf_size_t) bytes;
403 }
404
405 void
iperf_set_test_blocks(struct iperf_test * ipt,uint64_t blocks)406 iperf_set_test_blocks(struct iperf_test *ipt, uint64_t blocks)
407 {
408 ipt->settings->blocks = (iperf_size_t) blocks;
409 }
410
411 void
iperf_set_test_burst(struct iperf_test * ipt,int burst)412 iperf_set_test_burst(struct iperf_test *ipt, int burst)
413 {
414 ipt->settings->burst = burst;
415 }
416
417 void
iperf_set_test_server_port(struct iperf_test * ipt,int srv_port)418 iperf_set_test_server_port(struct iperf_test *ipt, int srv_port)
419 {
420 ipt->server_port = srv_port;
421 }
422
423 void
iperf_set_test_socket_bufsize(struct iperf_test * ipt,int socket_bufsize)424 iperf_set_test_socket_bufsize(struct iperf_test *ipt, int socket_bufsize)
425 {
426 ipt->settings->socket_bufsize = socket_bufsize;
427 }
428
429 void
iperf_set_test_num_streams(struct iperf_test * ipt,int num_streams)430 iperf_set_test_num_streams(struct iperf_test *ipt, int num_streams)
431 {
432 ipt->num_streams = num_streams;
433 }
434
435 static void
check_sender_has_retransmits(struct iperf_test * ipt)436 check_sender_has_retransmits(struct iperf_test *ipt)
437 {
438 if (ipt->mode != RECEIVER && ipt->protocol->id == Ptcp && has_tcpinfo_retransmits())
439 ipt->sender_has_retransmits = 1;
440 else
441 ipt->sender_has_retransmits = 0;
442 }
443
444 void
iperf_set_test_role(struct iperf_test * ipt,char role)445 iperf_set_test_role(struct iperf_test *ipt, char role)
446 {
447 ipt->role = role;
448 if (!ipt->reverse) {
449 if (role == 'c')
450 ipt->mode = SENDER;
451 else if (role == 's')
452 ipt->mode = RECEIVER;
453 } else {
454 if (role == 'c')
455 ipt->mode = RECEIVER;
456 else if (role == 's')
457 ipt->mode = SENDER;
458 }
459 check_sender_has_retransmits(ipt);
460 }
461
462 void
iperf_set_test_server_hostname(struct iperf_test * ipt,char * server_hostname)463 iperf_set_test_server_hostname(struct iperf_test *ipt, char *server_hostname)
464 {
465 ipt->server_hostname = strdup(server_hostname);
466 }
467
468 void
iperf_set_test_template(struct iperf_test * ipt,char * tmp_template)469 iperf_set_test_template(struct iperf_test *ipt, char *tmp_template)
470 {
471 ipt->tmp_template = strdup(tmp_template);
472 }
473
474 void
iperf_set_test_reverse(struct iperf_test * ipt,int reverse)475 iperf_set_test_reverse(struct iperf_test *ipt, int reverse)
476 {
477 ipt->reverse = reverse;
478 if (!ipt->reverse) {
479 if (ipt->role == 'c')
480 ipt->mode = SENDER;
481 else if (ipt->role == 's')
482 ipt->mode = RECEIVER;
483 } else {
484 if (ipt->role == 'c')
485 ipt->mode = RECEIVER;
486 else if (ipt->role == 's')
487 ipt->mode = SENDER;
488 }
489 check_sender_has_retransmits(ipt);
490 }
491
492 void
iperf_set_test_json_output(struct iperf_test * ipt,int json_output)493 iperf_set_test_json_output(struct iperf_test *ipt, int json_output)
494 {
495 ipt->json_output = json_output;
496 }
497
498 int
iperf_has_zerocopy(void)499 iperf_has_zerocopy( void )
500 {
501 return has_sendfile();
502 }
503
504 void
iperf_set_test_zerocopy(struct iperf_test * ipt,int zerocopy)505 iperf_set_test_zerocopy(struct iperf_test *ipt, int zerocopy)
506 {
507 ipt->zerocopy = (zerocopy && has_sendfile());
508 }
509
510 void
iperf_set_test_get_server_output(struct iperf_test * ipt,int get_server_output)511 iperf_set_test_get_server_output(struct iperf_test *ipt, int get_server_output)
512 {
513 ipt->get_server_output = get_server_output;
514 }
515
516 void
iperf_set_test_unit_format(struct iperf_test * ipt,char unit_format)517 iperf_set_test_unit_format(struct iperf_test *ipt, char unit_format)
518 {
519 ipt->settings->unit_format = unit_format;
520 }
521
522 #if defined(HAVE_SSL)
523 void
iperf_set_test_client_username(struct iperf_test * ipt,char * client_username)524 iperf_set_test_client_username(struct iperf_test *ipt, char *client_username)
525 {
526 ipt->settings->client_username = client_username;
527 }
528
529 void
iperf_set_test_client_password(struct iperf_test * ipt,char * client_password)530 iperf_set_test_client_password(struct iperf_test *ipt, char *client_password)
531 {
532 ipt->settings->client_password = client_password;
533 }
534
535 void
iperf_set_test_client_rsa_pubkey(struct iperf_test * ipt,char * client_rsa_pubkey_base64)536 iperf_set_test_client_rsa_pubkey(struct iperf_test *ipt, char *client_rsa_pubkey_base64)
537 {
538 ipt->settings->client_rsa_pubkey = load_pubkey_from_base64(client_rsa_pubkey_base64);
539 }
540 #endif // HAVE_SSL
541
542 void
iperf_set_test_bind_address(struct iperf_test * ipt,char * bnd_address)543 iperf_set_test_bind_address(struct iperf_test *ipt, char *bnd_address)
544 {
545 ipt->bind_address = strdup(bnd_address);
546 }
547
548 void
iperf_set_test_udp_counters_64bit(struct iperf_test * ipt,int udp_counters_64bit)549 iperf_set_test_udp_counters_64bit(struct iperf_test *ipt, int udp_counters_64bit)
550 {
551 ipt->udp_counters_64bit = udp_counters_64bit;
552 }
553
554 void
iperf_set_test_one_off(struct iperf_test * ipt,int one_off)555 iperf_set_test_one_off(struct iperf_test *ipt, int one_off)
556 {
557 ipt->one_off = one_off;
558 }
559
560 void
iperf_set_test_tos(struct iperf_test * ipt,int tos)561 iperf_set_test_tos(struct iperf_test *ipt, int tos)
562 {
563 ipt->settings->tos = tos;
564 }
565
566 void
iperf_set_test_extra_data(struct iperf_test * ipt,char * dat)567 iperf_set_test_extra_data(struct iperf_test *ipt, char *dat)
568 {
569 ipt->extra_data = dat;
570 }
571
572 void
iperf_set_test_bidirectional(struct iperf_test * ipt,int bidirectional)573 iperf_set_test_bidirectional(struct iperf_test* ipt, int bidirectional)
574 {
575 ipt->bidirectional = bidirectional;
576 if (bidirectional)
577 ipt->mode = BIDIRECTIONAL;
578 else
579 iperf_set_test_reverse(ipt, ipt->reverse);
580 }
581
582 /********************** Get/set test protocol structure ***********************/
583
584 struct protocol *
get_protocol(struct iperf_test * test,int prot_id)585 get_protocol(struct iperf_test *test, int prot_id)
586 {
587 struct protocol *prot;
588
589 SLIST_FOREACH(prot, &test->protocols, protocols) {
590 if (prot->id == prot_id)
591 break;
592 }
593
594 if (prot == NULL)
595 i_errno = IEPROTOCOL;
596
597 return prot;
598 }
599
600 int
set_protocol(struct iperf_test * test,int prot_id)601 set_protocol(struct iperf_test *test, int prot_id)
602 {
603 struct protocol *prot = NULL;
604
605 SLIST_FOREACH(prot, &test->protocols, protocols) {
606 if (prot->id == prot_id) {
607 test->protocol = prot;
608 check_sender_has_retransmits(test);
609 return 0;
610 }
611 }
612
613 i_errno = IEPROTOCOL;
614 return -1;
615 }
616
617
618 /************************** Iperf callback functions **************************/
619
620 void
iperf_on_new_stream(struct iperf_stream * sp)621 iperf_on_new_stream(struct iperf_stream *sp)
622 {
623 connect_msg(sp);
624 }
625
626 void
iperf_on_test_start(struct iperf_test * test)627 iperf_on_test_start(struct iperf_test *test)
628 {
629 if (test->json_output) {
630 cJSON_AddItemToObject(test->json_start, "test_start", iperf_json_printf("protocol: %s num_streams: %d blksize: %d omit: %d duration: %d bytes: %d blocks: %d reverse: %d tos: %d", test->protocol->name, (int64_t) test->num_streams, (int64_t) test->settings->blksize, (int64_t) test->omit, (int64_t) test->duration, (int64_t) test->settings->bytes, (int64_t) test->settings->blocks, test->reverse?(int64_t)1:(int64_t)0, (int64_t) test->settings->tos));
631 } else {
632 if (test->verbose) {
633 if (test->settings->bytes)
634 iperf_printf(test, test_start_bytes, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->settings->bytes, test->settings->tos);
635 else if (test->settings->blocks)
636 iperf_printf(test, test_start_blocks, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->settings->blocks, test->settings->tos);
637 else
638 iperf_printf(test, test_start_time, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->duration, test->settings->tos);
639 }
640 }
641 }
642
643 /* This converts an IPv6 string address from IPv4-mapped format into regular
644 ** old IPv4 format, which is easier on the eyes of network veterans.
645 **
646 ** If the v6 address is not v4-mapped it is left alone.
647 */
648 static void
mapped_v4_to_regular_v4(char * str)649 mapped_v4_to_regular_v4(char *str)
650 {
651 char *prefix = "::ffff:";
652 int prefix_len;
653
654 prefix_len = strlen(prefix);
655 if (strncmp(str, prefix, prefix_len) == 0) {
656 int str_len = strlen(str);
657 memmove(str, str + prefix_len, str_len - prefix_len + 1);
658 }
659 }
660
661 void
iperf_on_connect(struct iperf_test * test)662 iperf_on_connect(struct iperf_test *test)
663 {
664 time_t now_secs;
665 const char* rfc1123_fmt = "%a, %d %b %Y %H:%M:%S GMT";
666 char now_str[100];
667 char ipr[INET6_ADDRSTRLEN];
668 int port;
669 struct sockaddr_storage sa;
670 struct sockaddr_in *sa_inP;
671 struct sockaddr_in6 *sa_in6P;
672 socklen_t len;
673
674 now_secs = time((time_t*) 0);
675 (void) strftime(now_str, sizeof(now_str), rfc1123_fmt, gmtime(&now_secs));
676 if (test->json_output)
677 cJSON_AddItemToObject(test->json_start, "timestamp", iperf_json_printf("time: %s timesecs: %d", now_str, (int64_t) now_secs));
678 else if (test->verbose)
679 iperf_printf(test, report_time, now_str);
680
681 if (test->role == 'c') {
682 if (test->json_output)
683 cJSON_AddItemToObject(test->json_start, "connecting_to", iperf_json_printf("host: %s port: %d", test->server_hostname, (int64_t) test->server_port));
684 else {
685 iperf_printf(test, report_connecting, test->server_hostname, test->server_port);
686 if (test->reverse)
687 iperf_printf(test, report_reverse, test->server_hostname);
688 }
689 } else {
690 len = sizeof(sa);
691 getpeername(test->ctrl_sck, (struct sockaddr *) &sa, &len);
692 if (getsockdomain(test->ctrl_sck) == AF_INET) {
693 sa_inP = (struct sockaddr_in *) &sa;
694 inet_ntop(AF_INET, &sa_inP->sin_addr, ipr, sizeof(ipr));
695 port = ntohs(sa_inP->sin_port);
696 } else {
697 sa_in6P = (struct sockaddr_in6 *) &sa;
698 inet_ntop(AF_INET6, &sa_in6P->sin6_addr, ipr, sizeof(ipr));
699 port = ntohs(sa_in6P->sin6_port);
700 }
701 mapped_v4_to_regular_v4(ipr);
702 if (test->json_output)
703 cJSON_AddItemToObject(test->json_start, "accepted_connection", iperf_json_printf("host: %s port: %d", ipr, (int64_t) port));
704 else
705 iperf_printf(test, report_accepted, ipr, port);
706 }
707 if (test->json_output) {
708 cJSON_AddStringToObject(test->json_start, "cookie", test->cookie);
709 if (test->protocol->id == SOCK_STREAM) {
710 if (test->settings->mss)
711 cJSON_AddNumberToObject(test->json_start, "tcp_mss", test->settings->mss);
712 else {
713 cJSON_AddNumberToObject(test->json_start, "tcp_mss_default", test->ctrl_sck_mss);
714 }
715 if (test->settings->rate)
716 cJSON_AddNumberToObject(test->json_start, "target_bitrate", test->settings->rate);
717 }
718 } else if (test->verbose) {
719 iperf_printf(test, report_cookie, test->cookie);
720 if (test->protocol->id == SOCK_STREAM) {
721 if (test->settings->mss)
722 iperf_printf(test, " TCP MSS: %d\n", test->settings->mss);
723 else {
724 iperf_printf(test, " TCP MSS: %d (default)\n", test->ctrl_sck_mss);
725 }
726 }
727 if (test->settings->rate)
728 iperf_printf(test, " Target Bitrate: %llu\n", test->settings->rate);
729 }
730 }
731
732 void
iperf_on_test_finish(struct iperf_test * test)733 iperf_on_test_finish(struct iperf_test *test)
734 {
735 }
736
737
738 /******************************************************************************/
739
740 int
iperf_parse_arguments(struct iperf_test * test,int argc,char ** argv)741 iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
742 {
743 static struct option longopts[] =
744 {
745 {"port", required_argument, NULL, 'p'},
746 {"format", required_argument, NULL, 'f'},
747 {"interval", required_argument, NULL, 'i'},
748 {"daemon", no_argument, NULL, 'D'},
749 {"one-off", no_argument, NULL, '1'},
750 {"verbose", no_argument, NULL, 'V'},
751 {"json", no_argument, NULL, 'J'},
752 {"version", no_argument, NULL, 'v'},
753 {"server", no_argument, NULL, 's'},
754 {"client", required_argument, NULL, 'c'},
755 {"udp", no_argument, NULL, 'u'},
756 {"bitrate", required_argument, NULL, 'b'},
757 {"bandwidth", required_argument, NULL, 'b'},
758 {"time", required_argument, NULL, 't'},
759 {"bytes", required_argument, NULL, 'n'},
760 {"blockcount", required_argument, NULL, 'k'},
761 {"length", required_argument, NULL, 'l'},
762 {"parallel", required_argument, NULL, 'P'},
763 {"reverse", no_argument, NULL, 'R'},
764 {"bidir", no_argument, NULL, OPT_BIDIRECTIONAL},
765 {"window", required_argument, NULL, 'w'},
766 {"bind", required_argument, NULL, 'B'},
767 {"cport", required_argument, NULL, OPT_CLIENT_PORT},
768 {"set-mss", required_argument, NULL, 'M'},
769 {"no-delay", no_argument, NULL, 'N'},
770 {"version4", no_argument, NULL, '4'},
771 {"version6", no_argument, NULL, '6'},
772 {"tos", required_argument, NULL, 'S'},
773 {"dscp", required_argument, NULL, OPT_DSCP},
774 {"extra-data", required_argument, NULL, OPT_EXTRA_DATA},
775 #if defined(HAVE_FLOWLABEL)
776 {"flowlabel", required_argument, NULL, 'L'},
777 #endif /* HAVE_FLOWLABEL */
778 {"zerocopy", no_argument, NULL, 'Z'},
779 {"omit", required_argument, NULL, 'O'},
780 {"file", required_argument, NULL, 'F'},
781 {"repeating-payload", no_argument, NULL, OPT_REPEATING_PAYLOAD},
782 #if defined(HAVE_CPU_AFFINITY)
783 {"affinity", required_argument, NULL, 'A'},
784 #endif /* HAVE_CPU_AFFINITY */
785 {"title", required_argument, NULL, 'T'},
786 #if defined(HAVE_TCP_CONGESTION)
787 {"congestion", required_argument, NULL, 'C'},
788 {"linux-congestion", required_argument, NULL, 'C'},
789 #endif /* HAVE_TCP_CONGESTION */
790 #if defined(HAVE_SCTP)
791 {"sctp", no_argument, NULL, OPT_SCTP},
792 {"nstreams", required_argument, NULL, OPT_NUMSTREAMS},
793 {"xbind", required_argument, NULL, 'X'},
794 #endif
795 {"pidfile", required_argument, NULL, 'I'},
796 {"logfile", required_argument, NULL, OPT_LOGFILE},
797 {"forceflush", no_argument, NULL, OPT_FORCEFLUSH},
798 {"get-server-output", no_argument, NULL, OPT_GET_SERVER_OUTPUT},
799 {"udp-counters-64bit", no_argument, NULL, OPT_UDP_COUNTERS_64BIT},
800 {"no-fq-socket-pacing", no_argument, NULL, OPT_NO_FQ_SOCKET_PACING},
801 #if defined(HAVE_SSL)
802 {"username", required_argument, NULL, OPT_CLIENT_USERNAME},
803 {"rsa-public-key-path", required_argument, NULL, OPT_CLIENT_RSA_PUBLIC_KEY},
804 {"rsa-private-key-path", required_argument, NULL, OPT_SERVER_RSA_PRIVATE_KEY},
805 {"authorized-users-path", required_argument, NULL, OPT_SERVER_AUTHORIZED_USERS},
806 #endif /* HAVE_SSL */
807 {"fq-rate", required_argument, NULL, OPT_FQ_RATE},
808 {"pacing-timer", required_argument, NULL, OPT_PACING_TIMER},
809 {"connect-timeout", required_argument, NULL, OPT_CONNECT_TIMEOUT},
810 {"debug", no_argument, NULL, 'd'},
811 {"help", no_argument, NULL, 'h'},
812 {NULL, 0, NULL, 0}
813 };
814 int flag;
815 int blksize;
816 int server_flag, client_flag, rate_flag, duration_flag;
817 char *endptr;
818 #if defined(HAVE_CPU_AFFINITY)
819 char* comma;
820 #endif /* HAVE_CPU_AFFINITY */
821 char* slash;
822 struct xbind_entry *xbe;
823 double farg;
824
825 blksize = 0;
826 server_flag = client_flag = rate_flag = duration_flag = 0;
827 #if defined(HAVE_SSL)
828 char *client_username = NULL, *client_rsa_public_key = NULL, *server_rsa_private_key = NULL;
829 #endif /* HAVE_SSL */
830
831 while ((flag = getopt_long(argc, argv, "p:f:i:D1VJvsc:ub:t:n:k:l:P:Rw:B:M:N46S:L:ZO:F:A:T:C:dI:hX:", longopts, NULL)) != -1) {
832 switch (flag) {
833 case 'p':
834 test->server_port = atoi(optarg);
835 break;
836 case 'f':
837 if (!optarg) {
838 i_errno = IEBADFORMAT;
839 return -1;
840 }
841 test->settings->unit_format = *optarg;
842 if (test->settings->unit_format == 'k' ||
843 test->settings->unit_format == 'K' ||
844 test->settings->unit_format == 'm' ||
845 test->settings->unit_format == 'M' ||
846 test->settings->unit_format == 'g' ||
847 test->settings->unit_format == 'G' ||
848 test->settings->unit_format == 't' ||
849 test->settings->unit_format == 'T') {
850 break;
851 }
852 else {
853 i_errno = IEBADFORMAT;
854 return -1;
855 }
856 break;
857 case 'i':
858 /* XXX: could potentially want separate stat collection and reporting intervals,
859 but just set them to be the same for now */
860 test->stats_interval = test->reporter_interval = atof(optarg);
861 if ((test->stats_interval < MIN_INTERVAL || test->stats_interval > MAX_INTERVAL) && test->stats_interval != 0) {
862 i_errno = IEINTERVAL;
863 return -1;
864 }
865 break;
866 case 'D':
867 test->daemon = 1;
868 server_flag = 1;
869 break;
870 case '1':
871 test->one_off = 1;
872 server_flag = 1;
873 break;
874 case 'V':
875 test->verbose = 1;
876 break;
877 case 'J':
878 test->json_output = 1;
879 break;
880 case 'v':
881 printf("%s (cJSON %s)\n%s\n%s\n", version, cJSON_Version(), get_system_info(),
882 get_optional_features());
883 exit(0);
884 case 's':
885 if (test->role == 'c') {
886 i_errno = IESERVCLIENT;
887 return -1;
888 }
889 iperf_set_test_role(test, 's');
890 break;
891 case 'c':
892 if (test->role == 's') {
893 i_errno = IESERVCLIENT;
894 return -1;
895 }
896 iperf_set_test_role(test, 'c');
897 iperf_set_test_server_hostname(test, optarg);
898 break;
899 case 'u':
900 set_protocol(test, Pudp);
901 client_flag = 1;
902 break;
903 case OPT_SCTP:
904 #if defined(HAVE_SCTP)
905 set_protocol(test, Psctp);
906 client_flag = 1;
907 break;
908 #else /* HAVE_SCTP */
909 i_errno = IEUNIMP;
910 return -1;
911 #endif /* HAVE_SCTP */
912
913 case OPT_NUMSTREAMS:
914 #if defined(linux) || defined(__FreeBSD__)
915 test->settings->num_ostreams = unit_atoi(optarg);
916 client_flag = 1;
917 #else /* linux */
918 i_errno = IEUNIMP;
919 return -1;
920 #endif /* linux */
921 case 'b':
922 slash = strchr(optarg, '/');
923 if (slash) {
924 *slash = '\0';
925 ++slash;
926 test->settings->burst = atoi(slash);
927 if (test->settings->burst <= 0 ||
928 test->settings->burst > MAX_BURST) {
929 i_errno = IEBURST;
930 return -1;
931 }
932 }
933 test->settings->rate = unit_atof_rate(optarg);
934 rate_flag = 1;
935 client_flag = 1;
936 break;
937 case 't':
938 test->duration = atoi(optarg);
939 if (test->duration > MAX_TIME) {
940 i_errno = IEDURATION;
941 return -1;
942 }
943 duration_flag = 1;
944 client_flag = 1;
945 break;
946 case 'n':
947 test->settings->bytes = unit_atoi(optarg);
948 client_flag = 1;
949 break;
950 case 'k':
951 test->settings->blocks = unit_atoi(optarg);
952 client_flag = 1;
953 break;
954 case 'l':
955 blksize = unit_atoi(optarg);
956 client_flag = 1;
957 break;
958 case 'P':
959 test->num_streams = atoi(optarg);
960 if (test->num_streams > MAX_STREAMS) {
961 i_errno = IENUMSTREAMS;
962 return -1;
963 }
964 client_flag = 1;
965 break;
966 case 'R':
967 if (test->bidirectional) {
968 i_errno = IEREVERSEBIDIR;
969 return -1;
970 }
971 iperf_set_test_reverse(test, 1);
972 client_flag = 1;
973 break;
974 case OPT_BIDIRECTIONAL:
975 if (test->reverse) {
976 i_errno = IEREVERSEBIDIR;
977 return -1;
978 }
979 iperf_set_test_bidirectional(test, 1);
980 client_flag = 1;
981 break;
982 case 'w':
983 // XXX: This is a socket buffer, not specific to TCP
984 // Do sanity checks as double-precision floating point
985 // to avoid possible integer overflows.
986 farg = unit_atof(optarg);
987 if (farg > (double) MAX_TCP_BUFFER) {
988 i_errno = IEBUFSIZE;
989 return -1;
990 }
991 test->settings->socket_bufsize = (int) farg;
992 client_flag = 1;
993 break;
994 case 'B':
995 test->bind_address = strdup(optarg);
996 break;
997 case OPT_CLIENT_PORT:
998 test->bind_port = atoi(optarg);
999 break;
1000 case 'M':
1001 test->settings->mss = atoi(optarg);
1002 if (test->settings->mss > MAX_MSS) {
1003 i_errno = IEMSS;
1004 return -1;
1005 }
1006 client_flag = 1;
1007 break;
1008 case 'N':
1009 test->no_delay = 1;
1010 client_flag = 1;
1011 break;
1012 case '4':
1013 test->settings->domain = AF_INET;
1014 break;
1015 case '6':
1016 test->settings->domain = AF_INET6;
1017 break;
1018 case 'S':
1019 test->settings->tos = strtol(optarg, &endptr, 0);
1020 if (endptr == optarg ||
1021 test->settings->tos < 0 ||
1022 test->settings->tos > 255) {
1023 i_errno = IEBADTOS;
1024 return -1;
1025 }
1026 client_flag = 1;
1027 break;
1028 case OPT_DSCP:
1029 test->settings->tos = parse_qos(optarg);
1030 if(test->settings->tos < 0) {
1031 i_errno = IEBADTOS;
1032 return -1;
1033 }
1034 client_flag = 1;
1035 break;
1036 case OPT_EXTRA_DATA:
1037 test->extra_data = strdup(optarg);
1038 client_flag = 1;
1039 break;
1040 case 'L':
1041 #if defined(HAVE_FLOWLABEL)
1042 test->settings->flowlabel = strtol(optarg, &endptr, 0);
1043 if (endptr == optarg ||
1044 test->settings->flowlabel < 1 || test->settings->flowlabel > 0xfffff) {
1045 i_errno = IESETFLOW;
1046 return -1;
1047 }
1048 client_flag = 1;
1049 #else /* HAVE_FLOWLABEL */
1050 i_errno = IEUNIMP;
1051 return -1;
1052 #endif /* HAVE_FLOWLABEL */
1053 break;
1054 case 'X':
1055 xbe = (struct xbind_entry *)malloc(sizeof(struct xbind_entry));
1056 if (!xbe) {
1057 i_errno = IESETSCTPBINDX;
1058 return -1;
1059 }
1060 memset(xbe, 0, sizeof(*xbe));
1061 xbe->name = strdup(optarg);
1062 if (!xbe->name) {
1063 i_errno = IESETSCTPBINDX;
1064 return -1;
1065 }
1066 TAILQ_INSERT_TAIL(&test->xbind_addrs, xbe, link);
1067 break;
1068 case 'Z':
1069 if (!has_sendfile()) {
1070 i_errno = IENOSENDFILE;
1071 return -1;
1072 }
1073 test->zerocopy = 1;
1074 client_flag = 1;
1075 break;
1076 case OPT_REPEATING_PAYLOAD:
1077 test->repeating_payload = 1;
1078 client_flag = 1;
1079 break;
1080 case 'O':
1081 test->omit = atoi(optarg);
1082 if (test->omit < 0 || test->omit > 60) {
1083 i_errno = IEOMIT;
1084 return -1;
1085 }
1086 client_flag = 1;
1087 break;
1088 case 'F':
1089 test->diskfile_name = optarg;
1090 break;
1091 case 'A':
1092 #if defined(HAVE_CPU_AFFINITY)
1093 test->affinity = strtol(optarg, &endptr, 0);
1094 if (endptr == optarg ||
1095 test->affinity < 0 || test->affinity > 1024) {
1096 i_errno = IEAFFINITY;
1097 return -1;
1098 }
1099 comma = strchr(optarg, ',');
1100 if (comma != NULL) {
1101 test->server_affinity = atoi(comma+1);
1102 if (test->server_affinity < 0 || test->server_affinity > 1024) {
1103 i_errno = IEAFFINITY;
1104 return -1;
1105 }
1106 client_flag = 1;
1107 }
1108 #else /* HAVE_CPU_AFFINITY */
1109 i_errno = IEUNIMP;
1110 return -1;
1111 #endif /* HAVE_CPU_AFFINITY */
1112 break;
1113 case 'T':
1114 test->title = strdup(optarg);
1115 client_flag = 1;
1116 break;
1117 case 'C':
1118 #if defined(HAVE_TCP_CONGESTION)
1119 test->congestion = strdup(optarg);
1120 client_flag = 1;
1121 #else /* HAVE_TCP_CONGESTION */
1122 i_errno = IEUNIMP;
1123 return -1;
1124 #endif /* HAVE_TCP_CONGESTION */
1125 break;
1126 case 'd':
1127 test->debug = 1;
1128 break;
1129 case 'I':
1130 test->pidfile = strdup(optarg);
1131 server_flag = 1;
1132 break;
1133 case OPT_LOGFILE:
1134 test->logfile = strdup(optarg);
1135 break;
1136 case OPT_FORCEFLUSH:
1137 test->forceflush = 1;
1138 break;
1139 case OPT_GET_SERVER_OUTPUT:
1140 test->get_server_output = 1;
1141 client_flag = 1;
1142 break;
1143 case OPT_UDP_COUNTERS_64BIT:
1144 test->udp_counters_64bit = 1;
1145 break;
1146 case OPT_NO_FQ_SOCKET_PACING:
1147 #if defined(HAVE_SO_MAX_PACING_RATE)
1148 printf("Warning: --no-fq-socket-pacing is deprecated\n");
1149 test->settings->fqrate = 0;
1150 client_flag = 1;
1151 #else /* HAVE_SO_MAX_PACING_RATE */
1152 i_errno = IEUNIMP;
1153 return -1;
1154 #endif
1155 break;
1156 case OPT_FQ_RATE:
1157 #if defined(HAVE_SO_MAX_PACING_RATE)
1158 test->settings->fqrate = unit_atof_rate(optarg);
1159 client_flag = 1;
1160 #else /* HAVE_SO_MAX_PACING_RATE */
1161 i_errno = IEUNIMP;
1162 return -1;
1163 #endif
1164 break;
1165 #if defined(HAVE_SSL)
1166 case OPT_CLIENT_USERNAME:
1167 client_username = strdup(optarg);
1168 break;
1169 case OPT_CLIENT_RSA_PUBLIC_KEY:
1170 client_rsa_public_key = strdup(optarg);
1171 break;
1172 case OPT_SERVER_RSA_PRIVATE_KEY:
1173 server_rsa_private_key = strdup(optarg);
1174 break;
1175 case OPT_SERVER_AUTHORIZED_USERS:
1176 test->server_authorized_users = strdup(optarg);
1177 break;
1178 #endif /* HAVE_SSL */
1179 case OPT_PACING_TIMER:
1180 test->settings->pacing_timer = unit_atoi(optarg);
1181 client_flag = 1;
1182 break;
1183 case OPT_CONNECT_TIMEOUT:
1184 test->settings->connect_timeout = unit_atoi(optarg);
1185 client_flag = 1;
1186 break;
1187 case 'h':
1188 usage_long(stdout);
1189 exit(0);
1190 default:
1191 usage_long(stderr);
1192 exit(1);
1193 }
1194 }
1195
1196 /* Set logging to a file if specified, otherwise use the default (stdout) */
1197 if (test->logfile) {
1198 test->outfile = fopen(test->logfile, "a+");
1199 if (test->outfile == NULL) {
1200 i_errno = IELOGFILE;
1201 return -1;
1202 }
1203 }
1204
1205 /* Check flag / role compatibility. */
1206 if (test->role == 'c' && server_flag) {
1207 i_errno = IESERVERONLY;
1208 return -1;
1209 }
1210 if (test->role == 's' && client_flag) {
1211 i_errno = IECLIENTONLY;
1212 return -1;
1213 }
1214
1215 #if defined(HAVE_SSL)
1216
1217 if (test->role == 's' && (client_username || client_rsa_public_key)){
1218 i_errno = IECLIENTONLY;
1219 return -1;
1220 } else if (test->role == 'c' && (client_username || client_rsa_public_key) &&
1221 !(client_username && client_rsa_public_key)) {
1222 i_errno = IESETCLIENTAUTH;
1223 return -1;
1224 } else if (test->role == 'c' && (client_username && client_rsa_public_key)){
1225
1226 char *client_password = NULL;
1227 size_t s;
1228 if ((client_password = getenv("IPERF3_PASSWORD")) == NULL &&
1229 iperf_getpass(&client_password, &s, stdin) < 0){
1230 return -1;
1231 }
1232
1233 if (strlen(client_username) > 20 || strlen(client_password) > 20){
1234 i_errno = IESETCLIENTAUTH;
1235 return -1;
1236 }
1237
1238 if (test_load_pubkey_from_file(client_rsa_public_key) < 0){
1239 i_errno = IESETCLIENTAUTH;
1240 return -1;
1241 }
1242
1243 test->settings->client_username = client_username;
1244 test->settings->client_password = client_password;
1245 test->settings->client_rsa_pubkey = load_pubkey_from_file(client_rsa_public_key);
1246 }
1247
1248 if (test->role == 'c' && (server_rsa_private_key || test->server_authorized_users)){
1249 i_errno = IESERVERONLY;
1250 return -1;
1251 } else if (test->role == 's' && (server_rsa_private_key || test->server_authorized_users) &&
1252 !(server_rsa_private_key && test->server_authorized_users)) {
1253 i_errno = IESETSERVERAUTH;
1254 return -1;
1255 } else if (test->role == 's' && server_rsa_private_key && test_load_private_key_from_file(server_rsa_private_key) < 0){
1256 i_errno = IESETSERVERAUTH;
1257 return -1;
1258 } else {
1259 test->server_rsa_private_key = load_privkey_from_file(server_rsa_private_key);
1260 }
1261
1262 #endif //HAVE_SSL
1263 if (blksize == 0) {
1264 if (test->protocol->id == Pudp)
1265 blksize = 0; /* try to dynamically determine from MSS */
1266 else if (test->protocol->id == Psctp)
1267 blksize = DEFAULT_SCTP_BLKSIZE;
1268 else
1269 blksize = DEFAULT_TCP_BLKSIZE;
1270 }
1271 if ((test->protocol->id != Pudp && blksize <= 0)
1272 || blksize > MAX_BLOCKSIZE) {
1273 i_errno = IEBLOCKSIZE;
1274 return -1;
1275 }
1276 if (test->protocol->id == Pudp &&
1277 (blksize > 0 &&
1278 (blksize < MIN_UDP_BLOCKSIZE || blksize > MAX_UDP_BLOCKSIZE))) {
1279 i_errno = IEUDPBLOCKSIZE;
1280 return -1;
1281 }
1282 test->settings->blksize = blksize;
1283
1284 if (!rate_flag)
1285 test->settings->rate = test->protocol->id == Pudp ? UDP_RATE : 0;
1286
1287 if ((test->settings->bytes != 0 || test->settings->blocks != 0) && ! duration_flag)
1288 test->duration = 0;
1289
1290 /* Disallow specifying multiple test end conditions. The code actually
1291 ** works just fine without this prohibition. As soon as any one of the
1292 ** three possible end conditions is met, the test ends. So this check
1293 ** could be removed if desired.
1294 */
1295 if ((duration_flag && test->settings->bytes != 0) ||
1296 (duration_flag && test->settings->blocks != 0) ||
1297 (test->settings->bytes != 0 && test->settings->blocks != 0)) {
1298 i_errno = IEENDCONDITIONS;
1299 return -1;
1300 }
1301
1302 /* For subsequent calls to getopt */
1303 #ifdef __APPLE__
1304 optreset = 1;
1305 #endif
1306 optind = 0;
1307
1308 if ((test->role != 'c') && (test->role != 's')) {
1309 i_errno = IENOROLE;
1310 return -1;
1311 }
1312
1313 /* Show warning if JSON output is used with explicit report format */
1314 if ((test->json_output) && (test->settings->unit_format != 'a')) {
1315 warning("Report format (-f) flag ignored with JSON output (-J)");
1316 }
1317
1318 /* Show warning if JSON output is used with verbose or debug flags */
1319 if (test->json_output && test->verbose) {
1320 warning("Verbose output (-v) may interfere with JSON output (-J)");
1321 }
1322 if (test->json_output && test->debug) {
1323 warning("Debug output (-d) may interfere with JSON output (-J)");
1324 }
1325
1326 return 0;
1327 }
1328
1329 int
iperf_set_send_state(struct iperf_test * test,signed char state)1330 iperf_set_send_state(struct iperf_test *test, signed char state)
1331 {
1332 test->state = state;
1333 if (Nwrite(test->ctrl_sck, (char*) &state, sizeof(state), Ptcp) < 0) {
1334 i_errno = IESENDMESSAGE;
1335 return -1;
1336 }
1337 return 0;
1338 }
1339
1340 void
iperf_check_throttle(struct iperf_stream * sp,struct iperf_time * nowP)1341 iperf_check_throttle(struct iperf_stream *sp, struct iperf_time *nowP)
1342 {
1343 struct iperf_time temp_time;
1344 double seconds;
1345 uint64_t bits_per_second;
1346
1347 if (sp->test->done)
1348 return;
1349 iperf_time_diff(&sp->result->start_time_fixed, nowP, &temp_time);
1350 seconds = iperf_time_in_secs(&temp_time);
1351 bits_per_second = sp->result->bytes_sent * 8 / seconds;
1352 if (bits_per_second < sp->test->settings->rate) {
1353 sp->green_light = 1;
1354 FD_SET(sp->socket, &sp->test->write_set);
1355 } else {
1356 sp->green_light = 0;
1357 FD_CLR(sp->socket, &sp->test->write_set);
1358 }
1359 }
1360
1361 int
iperf_send(struct iperf_test * test,fd_set * write_setP)1362 iperf_send(struct iperf_test *test, fd_set *write_setP)
1363 {
1364 register int multisend, r, streams_active;
1365 register struct iperf_stream *sp;
1366 struct iperf_time now;
1367
1368 /* Can we do multisend mode? */
1369 if (test->settings->burst != 0)
1370 multisend = test->settings->burst;
1371 else if (test->settings->rate == 0)
1372 multisend = test->multisend;
1373 else
1374 multisend = 1; /* nope */
1375
1376 for (; multisend > 0; --multisend) {
1377 if (test->settings->rate != 0 && test->settings->burst == 0)
1378 iperf_time_now(&now);
1379 streams_active = 0;
1380 SLIST_FOREACH(sp, &test->streams, streams) {
1381 if ((sp->green_light && sp->sender &&
1382 (write_setP == NULL || FD_ISSET(sp->socket, write_setP)))) {
1383 if ((r = sp->snd(sp)) < 0) {
1384 if (r == NET_SOFTERROR)
1385 break;
1386 i_errno = IESTREAMWRITE;
1387 return r;
1388 }
1389 streams_active = 1;
1390 test->bytes_sent += r;
1391 ++test->blocks_sent;
1392 if (test->settings->rate != 0 && test->settings->burst == 0)
1393 iperf_check_throttle(sp, &now);
1394 if (multisend > 1 && test->settings->bytes != 0 && test->bytes_sent >= test->settings->bytes)
1395 break;
1396 if (multisend > 1 && test->settings->blocks != 0 && test->blocks_sent >= test->settings->blocks)
1397 break;
1398 }
1399 }
1400 if (!streams_active)
1401 break;
1402 }
1403 if (test->settings->burst != 0) {
1404 iperf_time_now(&now);
1405 SLIST_FOREACH(sp, &test->streams, streams)
1406 iperf_check_throttle(sp, &now);
1407 }
1408 if (write_setP != NULL)
1409 SLIST_FOREACH(sp, &test->streams, streams)
1410 if (FD_ISSET(sp->socket, write_setP))
1411 FD_CLR(sp->socket, write_setP);
1412
1413 return 0;
1414 }
1415
1416 int
iperf_recv(struct iperf_test * test,fd_set * read_setP)1417 iperf_recv(struct iperf_test *test, fd_set *read_setP)
1418 {
1419 int r;
1420 struct iperf_stream *sp;
1421
1422 SLIST_FOREACH(sp, &test->streams, streams) {
1423 if (FD_ISSET(sp->socket, read_setP) && !sp->sender) {
1424 if ((r = sp->rcv(sp)) < 0) {
1425 i_errno = IESTREAMREAD;
1426 return r;
1427 }
1428 test->bytes_received += r;
1429 ++test->blocks_received;
1430 FD_CLR(sp->socket, read_setP);
1431 }
1432 }
1433
1434 return 0;
1435 }
1436
1437 int
iperf_init_test(struct iperf_test * test)1438 iperf_init_test(struct iperf_test *test)
1439 {
1440 struct iperf_time now;
1441 struct iperf_stream *sp;
1442
1443 if (test->protocol->init) {
1444 if (test->protocol->init(test) < 0)
1445 return -1;
1446 }
1447
1448 /* Init each stream. */
1449 if (iperf_time_now(&now) < 0) {
1450 i_errno = IEINITTEST;
1451 return -1;
1452 }
1453 SLIST_FOREACH(sp, &test->streams, streams) {
1454 sp->result->start_time = sp->result->start_time_fixed = now;
1455 }
1456
1457 if (test->on_test_start)
1458 test->on_test_start(test);
1459
1460 return 0;
1461 }
1462
1463 static void
send_timer_proc(TimerClientData client_data,struct iperf_time * nowP)1464 send_timer_proc(TimerClientData client_data, struct iperf_time *nowP)
1465 {
1466 struct iperf_stream *sp = client_data.p;
1467
1468 /* All we do here is set or clear the flag saying that this stream may
1469 ** be sent to. The actual sending gets done in the send proc, after
1470 ** checking the flag.
1471 */
1472 iperf_check_throttle(sp, nowP);
1473 }
1474
1475 int
iperf_create_send_timers(struct iperf_test * test)1476 iperf_create_send_timers(struct iperf_test * test)
1477 {
1478 struct iperf_time now;
1479 struct iperf_stream *sp;
1480 TimerClientData cd;
1481
1482 if (iperf_time_now(&now) < 0) {
1483 i_errno = IEINITTEST;
1484 return -1;
1485 }
1486 SLIST_FOREACH(sp, &test->streams, streams) {
1487 sp->green_light = 1;
1488 if (test->settings->rate != 0) {
1489 cd.p = sp;
1490 sp->send_timer = tmr_create(NULL, send_timer_proc, cd, test->settings->pacing_timer, 1);
1491 if (sp->send_timer == NULL) {
1492 i_errno = IEINITTEST;
1493 return -1;
1494 }
1495 }
1496 }
1497 return 0;
1498 }
1499
1500 #if defined(HAVE_SSL)
test_is_authorized(struct iperf_test * test)1501 int test_is_authorized(struct iperf_test *test){
1502 if ( !(test->server_rsa_private_key && test->server_authorized_users)) {
1503 return 0;
1504 }
1505
1506 if (test->settings->authtoken){
1507 char *username = NULL, *password = NULL;
1508 time_t ts;
1509 decode_auth_setting(test->debug, test->settings->authtoken, test->server_rsa_private_key, &username, &password, &ts);
1510 int ret = check_authentication(username, password, ts, test->server_authorized_users);
1511 if (ret == 0){
1512 iperf_printf(test, report_authetication_successed, username, ts);
1513 return 0;
1514 } else {
1515 iperf_printf(test, report_authetication_failed, username, ts);
1516 return -1;
1517 }
1518 }
1519 return -1;
1520 }
1521 #endif //HAVE_SSL
1522
1523 /**
1524 * iperf_exchange_parameters - handles the param_Exchange part for client
1525 *
1526 */
1527
1528 int
iperf_exchange_parameters(struct iperf_test * test)1529 iperf_exchange_parameters(struct iperf_test *test)
1530 {
1531 int s;
1532 int32_t err;
1533
1534 if (test->role == 'c') {
1535
1536 if (send_parameters(test) < 0)
1537 return -1;
1538
1539 } else {
1540
1541 if (get_parameters(test) < 0)
1542 return -1;
1543
1544 #if defined(HAVE_SSL)
1545 if (test_is_authorized(test) < 0){
1546 if (iperf_set_send_state(test, SERVER_ERROR) != 0)
1547 return -1;
1548 i_errno = IEAUTHTEST;
1549 err = htonl(i_errno);
1550 if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) {
1551 i_errno = IECTRLWRITE;
1552 return -1;
1553 }
1554 return -1;
1555 }
1556 #endif //HAVE_SSL
1557
1558 if ((s = test->protocol->listen(test)) < 0) {
1559 if (iperf_set_send_state(test, SERVER_ERROR) != 0)
1560 return -1;
1561 err = htonl(i_errno);
1562 if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) {
1563 i_errno = IECTRLWRITE;
1564 return -1;
1565 }
1566 err = htonl(errno);
1567 if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) {
1568 i_errno = IECTRLWRITE;
1569 return -1;
1570 }
1571 return -1;
1572 }
1573 FD_SET(s, &test->read_set);
1574 test->max_fd = (s > test->max_fd) ? s : test->max_fd;
1575 test->prot_listener = s;
1576
1577 // Send the control message to create streams and start the test
1578 if (iperf_set_send_state(test, CREATE_STREAMS) != 0)
1579 return -1;
1580
1581 }
1582
1583 return 0;
1584 }
1585
1586 /*************************************************************/
1587
1588 int
iperf_exchange_results(struct iperf_test * test)1589 iperf_exchange_results(struct iperf_test *test)
1590 {
1591 if (test->role == 'c') {
1592 /* Send results to server. */
1593 if (send_results(test) < 0)
1594 return -1;
1595 /* Get server results. */
1596 if (get_results(test) < 0)
1597 return -1;
1598 } else {
1599 /* Get client results. */
1600 if (get_results(test) < 0)
1601 return -1;
1602 /* Send results to client. */
1603 if (send_results(test) < 0)
1604 return -1;
1605 }
1606 return 0;
1607 }
1608
1609 /*************************************************************/
1610
1611 static int
send_parameters(struct iperf_test * test)1612 send_parameters(struct iperf_test *test)
1613 {
1614 int r = 0;
1615 cJSON *j;
1616
1617 j = cJSON_CreateObject();
1618 if (j == NULL) {
1619 i_errno = IESENDPARAMS;
1620 r = -1;
1621 } else {
1622 if (test->protocol->id == Ptcp)
1623 cJSON_AddTrueToObject(j, "tcp");
1624 else if (test->protocol->id == Pudp)
1625 cJSON_AddTrueToObject(j, "udp");
1626 else if (test->protocol->id == Psctp)
1627 cJSON_AddTrueToObject(j, "sctp");
1628 cJSON_AddNumberToObject(j, "omit", test->omit);
1629 if (test->server_affinity != -1)
1630 cJSON_AddNumberToObject(j, "server_affinity", test->server_affinity);
1631 cJSON_AddNumberToObject(j, "time", test->duration);
1632 if (test->settings->bytes)
1633 cJSON_AddNumberToObject(j, "num", test->settings->bytes);
1634 if (test->settings->blocks)
1635 cJSON_AddNumberToObject(j, "blockcount", test->settings->blocks);
1636 if (test->settings->mss)
1637 cJSON_AddNumberToObject(j, "MSS", test->settings->mss);
1638 if (test->no_delay)
1639 cJSON_AddTrueToObject(j, "nodelay");
1640 cJSON_AddNumberToObject(j, "parallel", test->num_streams);
1641 if (test->reverse)
1642 cJSON_AddTrueToObject(j, "reverse");
1643 if (test->bidirectional)
1644 cJSON_AddTrueToObject(j, "bidirectional");
1645 if (test->settings->socket_bufsize)
1646 cJSON_AddNumberToObject(j, "window", test->settings->socket_bufsize);
1647 if (test->settings->blksize)
1648 cJSON_AddNumberToObject(j, "len", test->settings->blksize);
1649 if (test->settings->rate)
1650 cJSON_AddNumberToObject(j, "bandwidth", test->settings->rate);
1651 if (test->settings->fqrate)
1652 cJSON_AddNumberToObject(j, "fqrate", test->settings->fqrate);
1653 if (test->settings->pacing_timer)
1654 cJSON_AddNumberToObject(j, "pacing_timer", test->settings->pacing_timer);
1655 if (test->settings->burst)
1656 cJSON_AddNumberToObject(j, "burst", test->settings->burst);
1657 if (test->settings->tos)
1658 cJSON_AddNumberToObject(j, "TOS", test->settings->tos);
1659 if (test->settings->flowlabel)
1660 cJSON_AddNumberToObject(j, "flowlabel", test->settings->flowlabel);
1661 if (test->title)
1662 cJSON_AddStringToObject(j, "title", test->title);
1663 if (test->extra_data)
1664 cJSON_AddStringToObject(j, "extra_data", test->extra_data);
1665 if (test->congestion)
1666 cJSON_AddStringToObject(j, "congestion", test->congestion);
1667 if (test->congestion_used)
1668 cJSON_AddStringToObject(j, "congestion_used", test->congestion_used);
1669 if (test->get_server_output)
1670 cJSON_AddNumberToObject(j, "get_server_output", iperf_get_test_get_server_output(test));
1671 if (test->udp_counters_64bit)
1672 cJSON_AddNumberToObject(j, "udp_counters_64bit", iperf_get_test_udp_counters_64bit(test));
1673 #if defined(HAVE_SSL)
1674 if (test->settings->client_username && test->settings->client_password && test->settings->client_rsa_pubkey){
1675 encode_auth_setting(test->settings->client_username, test->settings->client_password, test->settings->client_rsa_pubkey, &test->settings->authtoken);
1676 cJSON_AddStringToObject(j, "authtoken", test->settings->authtoken);
1677 }
1678 #endif // HAVE_SSL
1679 cJSON_AddStringToObject(j, "client_version", IPERF_VERSION);
1680
1681 if (test->debug) {
1682 printf("send_parameters:\n%s\n", cJSON_Print(j));
1683 }
1684
1685 if (JSON_write(test->ctrl_sck, j) < 0) {
1686 i_errno = IESENDPARAMS;
1687 r = -1;
1688 }
1689 cJSON_Delete(j);
1690 }
1691 return r;
1692 }
1693
1694 /*************************************************************/
1695
1696 static int
get_parameters(struct iperf_test * test)1697 get_parameters(struct iperf_test *test)
1698 {
1699 int r = 0;
1700 cJSON *j;
1701 cJSON *j_p;
1702
1703 j = JSON_read(test->ctrl_sck);
1704 if (j == NULL) {
1705 i_errno = IERECVPARAMS;
1706 r = -1;
1707 } else {
1708 if (test->debug) {
1709 printf("get_parameters:\n%s\n", cJSON_Print(j));
1710 }
1711
1712 if ((j_p = cJSON_GetObjectItem(j, "tcp")) != NULL)
1713 set_protocol(test, Ptcp);
1714 if ((j_p = cJSON_GetObjectItem(j, "udp")) != NULL)
1715 set_protocol(test, Pudp);
1716 if ((j_p = cJSON_GetObjectItem(j, "sctp")) != NULL)
1717 set_protocol(test, Psctp);
1718 if ((j_p = cJSON_GetObjectItem(j, "omit")) != NULL)
1719 test->omit = j_p->valueint;
1720 if ((j_p = cJSON_GetObjectItem(j, "server_affinity")) != NULL)
1721 test->server_affinity = j_p->valueint;
1722 if ((j_p = cJSON_GetObjectItem(j, "time")) != NULL)
1723 test->duration = j_p->valueint;
1724 if ((j_p = cJSON_GetObjectItem(j, "num")) != NULL)
1725 test->settings->bytes = j_p->valueint;
1726 if ((j_p = cJSON_GetObjectItem(j, "blockcount")) != NULL)
1727 test->settings->blocks = j_p->valueint;
1728 if ((j_p = cJSON_GetObjectItem(j, "MSS")) != NULL)
1729 test->settings->mss = j_p->valueint;
1730 if ((j_p = cJSON_GetObjectItem(j, "nodelay")) != NULL)
1731 test->no_delay = 1;
1732 if ((j_p = cJSON_GetObjectItem(j, "parallel")) != NULL)
1733 test->num_streams = j_p->valueint;
1734 if ((j_p = cJSON_GetObjectItem(j, "reverse")) != NULL)
1735 iperf_set_test_reverse(test, 1);
1736 if ((j_p = cJSON_GetObjectItem(j, "bidirectional")) != NULL)
1737 iperf_set_test_bidirectional(test, 1);
1738 if ((j_p = cJSON_GetObjectItem(j, "window")) != NULL)
1739 test->settings->socket_bufsize = j_p->valueint;
1740 if ((j_p = cJSON_GetObjectItem(j, "len")) != NULL)
1741 test->settings->blksize = j_p->valueint;
1742 if ((j_p = cJSON_GetObjectItem(j, "bandwidth")) != NULL)
1743 test->settings->rate = j_p->valueint;
1744 if ((j_p = cJSON_GetObjectItem(j, "fqrate")) != NULL)
1745 test->settings->fqrate = j_p->valueint;
1746 if ((j_p = cJSON_GetObjectItem(j, "pacing_timer")) != NULL)
1747 test->settings->pacing_timer = j_p->valueint;
1748 if ((j_p = cJSON_GetObjectItem(j, "burst")) != NULL)
1749 test->settings->burst = j_p->valueint;
1750 if ((j_p = cJSON_GetObjectItem(j, "TOS")) != NULL)
1751 test->settings->tos = j_p->valueint;
1752 if ((j_p = cJSON_GetObjectItem(j, "flowlabel")) != NULL)
1753 test->settings->flowlabel = j_p->valueint;
1754 if ((j_p = cJSON_GetObjectItem(j, "title")) != NULL)
1755 test->title = strdup(j_p->valuestring);
1756 if ((j_p = cJSON_GetObjectItem(j, "extra_data")) != NULL)
1757 test->extra_data = strdup(j_p->valuestring);
1758 if ((j_p = cJSON_GetObjectItem(j, "congestion")) != NULL)
1759 test->congestion = strdup(j_p->valuestring);
1760 if ((j_p = cJSON_GetObjectItem(j, "congestion_used")) != NULL)
1761 test->congestion_used = strdup(j_p->valuestring);
1762 if ((j_p = cJSON_GetObjectItem(j, "get_server_output")) != NULL)
1763 iperf_set_test_get_server_output(test, 1);
1764 if ((j_p = cJSON_GetObjectItem(j, "udp_counters_64bit")) != NULL)
1765 iperf_set_test_udp_counters_64bit(test, 1);
1766 #if defined(HAVE_SSL)
1767 if ((j_p = cJSON_GetObjectItem(j, "authtoken")) != NULL)
1768 test->settings->authtoken = strdup(j_p->valuestring);
1769 #endif //HAVE_SSL
1770 if (test->mode && test->protocol->id == Ptcp && has_tcpinfo_retransmits())
1771 test->sender_has_retransmits = 1;
1772 if (test->settings->rate)
1773 cJSON_AddNumberToObject(test->json_start, "target_bitrate", test->settings->rate);
1774 cJSON_Delete(j);
1775 }
1776 return r;
1777 }
1778
1779 /*************************************************************/
1780
1781 static int
send_results(struct iperf_test * test)1782 send_results(struct iperf_test *test)
1783 {
1784 int r = 0;
1785 cJSON *j;
1786 cJSON *j_streams;
1787 struct iperf_stream *sp;
1788 cJSON *j_stream;
1789 int sender_has_retransmits;
1790 iperf_size_t bytes_transferred;
1791 int retransmits;
1792 struct iperf_time temp_time;
1793 double start_time, end_time;
1794
1795 j = cJSON_CreateObject();
1796 if (j == NULL) {
1797 i_errno = IEPACKAGERESULTS;
1798 r = -1;
1799 } else {
1800 cJSON_AddNumberToObject(j, "cpu_util_total", test->cpu_util[0]);
1801 cJSON_AddNumberToObject(j, "cpu_util_user", test->cpu_util[1]);
1802 cJSON_AddNumberToObject(j, "cpu_util_system", test->cpu_util[2]);
1803 if ( test->mode == RECEIVER )
1804 sender_has_retransmits = -1;
1805 else
1806 sender_has_retransmits = test->sender_has_retransmits;
1807 cJSON_AddNumberToObject(j, "sender_has_retransmits", sender_has_retransmits);
1808 if ( test->congestion_used ) {
1809 cJSON_AddStringToObject(j, "congestion_used", test->congestion_used);
1810 }
1811
1812 /* If on the server and sending server output, then do this */
1813 if (test->role == 's' && test->get_server_output) {
1814 if (test->json_output) {
1815 /* Add JSON output */
1816 cJSON_AddItemReferenceToObject(j, "server_output_json", test->json_top);
1817 }
1818 else {
1819 /* Add textual output */
1820 size_t buflen = 0;
1821
1822 /* Figure out how much room we need to hold the complete output string */
1823 struct iperf_textline *t;
1824 TAILQ_FOREACH(t, &(test->server_output_list), textlineentries) {
1825 buflen += strlen(t->line);
1826 }
1827
1828 /* Allocate and build it up from the component lines */
1829 char *output = calloc(buflen + 1, 1);
1830 TAILQ_FOREACH(t, &(test->server_output_list), textlineentries) {
1831 strncat(output, t->line, buflen);
1832 buflen -= strlen(t->line);
1833 }
1834
1835 cJSON_AddStringToObject(j, "server_output_text", output);
1836 free(output);
1837 }
1838 }
1839
1840 j_streams = cJSON_CreateArray();
1841 if (j_streams == NULL) {
1842 i_errno = IEPACKAGERESULTS;
1843 r = -1;
1844 } else {
1845 cJSON_AddItemToObject(j, "streams", j_streams);
1846 SLIST_FOREACH(sp, &test->streams, streams) {
1847 j_stream = cJSON_CreateObject();
1848 if (j_stream == NULL) {
1849 i_errno = IEPACKAGERESULTS;
1850 r = -1;
1851 } else {
1852 cJSON_AddItemToArray(j_streams, j_stream);
1853 bytes_transferred = sp->sender ? (sp->result->bytes_sent - sp->result->bytes_sent_omit) : sp->result->bytes_received;
1854 retransmits = (sp->sender && test->sender_has_retransmits) ? sp->result->stream_retrans : -1;
1855 cJSON_AddNumberToObject(j_stream, "id", sp->id);
1856 cJSON_AddNumberToObject(j_stream, "bytes", bytes_transferred);
1857 cJSON_AddNumberToObject(j_stream, "retransmits", retransmits);
1858 cJSON_AddNumberToObject(j_stream, "jitter", sp->jitter);
1859 cJSON_AddNumberToObject(j_stream, "errors", sp->cnt_error);
1860 cJSON_AddNumberToObject(j_stream, "packets", sp->packet_count);
1861
1862 iperf_time_diff(&sp->result->start_time, &sp->result->start_time, &temp_time);
1863 start_time = iperf_time_in_secs(&temp_time);
1864 iperf_time_diff(&sp->result->start_time, &sp->result->end_time, &temp_time);
1865 end_time = iperf_time_in_secs(&temp_time);
1866 cJSON_AddNumberToObject(j_stream, "start_time", start_time);
1867 cJSON_AddNumberToObject(j_stream, "end_time", end_time);
1868
1869 }
1870 }
1871 if (r == 0 && test->debug) {
1872 printf("send_results\n%s\n", cJSON_Print(j));
1873 }
1874 if (r == 0 && JSON_write(test->ctrl_sck, j) < 0) {
1875 i_errno = IESENDRESULTS;
1876 r = -1;
1877 }
1878 }
1879 cJSON_Delete(j);
1880 }
1881 return r;
1882 }
1883
1884 /*************************************************************/
1885
1886 static int
get_results(struct iperf_test * test)1887 get_results(struct iperf_test *test)
1888 {
1889 int r = 0;
1890 cJSON *j;
1891 cJSON *j_cpu_util_total;
1892 cJSON *j_cpu_util_user;
1893 cJSON *j_cpu_util_system;
1894 cJSON *j_remote_congestion_used;
1895 cJSON *j_sender_has_retransmits;
1896 int result_has_retransmits;
1897 cJSON *j_streams;
1898 int n, i;
1899 cJSON *j_stream;
1900 cJSON *j_id;
1901 cJSON *j_bytes;
1902 cJSON *j_retransmits;
1903 cJSON *j_jitter;
1904 cJSON *j_errors;
1905 cJSON *j_packets;
1906 cJSON *j_server_output;
1907 cJSON *j_start_time, *j_end_time;
1908 int sid, cerror, pcount;
1909 double jitter;
1910 iperf_size_t bytes_transferred;
1911 int retransmits;
1912 struct iperf_stream *sp;
1913
1914 j = JSON_read(test->ctrl_sck);
1915 if (j == NULL) {
1916 i_errno = IERECVRESULTS;
1917 r = -1;
1918 } else {
1919 j_cpu_util_total = cJSON_GetObjectItem(j, "cpu_util_total");
1920 j_cpu_util_user = cJSON_GetObjectItem(j, "cpu_util_user");
1921 j_cpu_util_system = cJSON_GetObjectItem(j, "cpu_util_system");
1922 j_sender_has_retransmits = cJSON_GetObjectItem(j, "sender_has_retransmits");
1923 if (j_cpu_util_total == NULL || j_cpu_util_user == NULL || j_cpu_util_system == NULL || j_sender_has_retransmits == NULL) {
1924 i_errno = IERECVRESULTS;
1925 r = -1;
1926 } else {
1927 if (test->debug) {
1928 printf("get_results\n%s\n", cJSON_Print(j));
1929 }
1930
1931 test->remote_cpu_util[0] = j_cpu_util_total->valuedouble;
1932 test->remote_cpu_util[1] = j_cpu_util_user->valuedouble;
1933 test->remote_cpu_util[2] = j_cpu_util_system->valuedouble;
1934 result_has_retransmits = j_sender_has_retransmits->valueint;
1935 if ( test->mode == RECEIVER ) {
1936 test->sender_has_retransmits = result_has_retransmits;
1937 test->other_side_has_retransmits = 0;
1938 }
1939 else if ( test->mode == BIDIRECTIONAL )
1940 test->other_side_has_retransmits = result_has_retransmits;
1941
1942 j_streams = cJSON_GetObjectItem(j, "streams");
1943 if (j_streams == NULL) {
1944 i_errno = IERECVRESULTS;
1945 r = -1;
1946 } else {
1947 n = cJSON_GetArraySize(j_streams);
1948 for (i=0; i<n; ++i) {
1949 j_stream = cJSON_GetArrayItem(j_streams, i);
1950 if (j_stream == NULL) {
1951 i_errno = IERECVRESULTS;
1952 r = -1;
1953 } else {
1954 j_id = cJSON_GetObjectItem(j_stream, "id");
1955 j_bytes = cJSON_GetObjectItem(j_stream, "bytes");
1956 j_retransmits = cJSON_GetObjectItem(j_stream, "retransmits");
1957 j_jitter = cJSON_GetObjectItem(j_stream, "jitter");
1958 j_errors = cJSON_GetObjectItem(j_stream, "errors");
1959 j_packets = cJSON_GetObjectItem(j_stream, "packets");
1960 j_start_time = cJSON_GetObjectItem(j_stream, "start_time");
1961 j_end_time = cJSON_GetObjectItem(j_stream, "end_time");
1962 if (j_id == NULL || j_bytes == NULL || j_retransmits == NULL || j_jitter == NULL || j_errors == NULL || j_packets == NULL) {
1963 i_errno = IERECVRESULTS;
1964 r = -1;
1965 } else {
1966 sid = j_id->valueint;
1967 bytes_transferred = j_bytes->valueint;
1968 retransmits = j_retransmits->valueint;
1969 jitter = j_jitter->valuedouble;
1970 cerror = j_errors->valueint;
1971 pcount = j_packets->valueint;
1972 SLIST_FOREACH(sp, &test->streams, streams)
1973 if (sp->id == sid) break;
1974 if (sp == NULL) {
1975 i_errno = IESTREAMID;
1976 r = -1;
1977 } else {
1978 if (sp->sender) {
1979 sp->jitter = jitter;
1980 sp->cnt_error = cerror;
1981 sp->peer_packet_count = pcount;
1982 sp->result->bytes_received = bytes_transferred;
1983 /*
1984 * We have to handle the possibilty that
1985 * start_time and end_time might not be
1986 * available; this is the case for older (pre-3.2)
1987 * servers.
1988 *
1989 * We need to have result structure members to hold
1990 * the both sides' start_time and end_time.
1991 */
1992 if (j_start_time && j_end_time) {
1993 sp->result->receiver_time = j_end_time->valuedouble - j_start_time->valuedouble;
1994 }
1995 else {
1996 sp->result->receiver_time = 0.0;
1997 }
1998 } else {
1999 sp->peer_packet_count = pcount;
2000 sp->result->bytes_sent = bytes_transferred;
2001 sp->result->stream_retrans = retransmits;
2002 if (j_start_time && j_end_time) {
2003 sp->result->sender_time = j_end_time->valuedouble - j_start_time->valuedouble;
2004 }
2005 else {
2006 sp->result->sender_time = 0.0;
2007 }
2008 }
2009 }
2010 }
2011 }
2012 }
2013 /*
2014 * If we're the client and we're supposed to get remote results,
2015 * look them up and process accordingly.
2016 */
2017 if (test->role == 'c' && iperf_get_test_get_server_output(test)) {
2018 /* Look for JSON. If we find it, grab the object so it doesn't get deleted. */
2019 j_server_output = cJSON_DetachItemFromObject(j, "server_output_json");
2020 if (j_server_output != NULL) {
2021 test->json_server_output = j_server_output;
2022 }
2023 else {
2024 /* No JSON, look for textual output. Make a copy of the text for later. */
2025 j_server_output = cJSON_GetObjectItem(j, "server_output_text");
2026 if (j_server_output != NULL) {
2027 test->server_output_text = strdup(j_server_output->valuestring);
2028 }
2029 }
2030 }
2031 }
2032 }
2033
2034 j_remote_congestion_used = cJSON_GetObjectItem(j, "congestion_used");
2035 if (j_remote_congestion_used != NULL) {
2036 test->remote_congestion_used = strdup(j_remote_congestion_used->valuestring);
2037 }
2038
2039 cJSON_Delete(j);
2040 }
2041 return r;
2042 }
2043
2044 /*************************************************************/
2045
2046 static int
JSON_write(int fd,cJSON * json)2047 JSON_write(int fd, cJSON *json)
2048 {
2049 uint32_t hsize, nsize;
2050 char *str;
2051 int r = 0;
2052
2053 str = cJSON_PrintUnformatted(json);
2054 if (str == NULL)
2055 r = -1;
2056 else {
2057 hsize = strlen(str);
2058 nsize = htonl(hsize);
2059 if (Nwrite(fd, (char*) &nsize, sizeof(nsize), Ptcp) < 0)
2060 r = -1;
2061 else {
2062 if (Nwrite(fd, str, hsize, Ptcp) < 0)
2063 r = -1;
2064 }
2065 free(str);
2066 }
2067 return r;
2068 }
2069
2070 /*************************************************************/
2071
2072 static cJSON *
JSON_read(int fd)2073 JSON_read(int fd)
2074 {
2075 uint32_t hsize, nsize;
2076 char *str;
2077 cJSON *json = NULL;
2078 int rc;
2079
2080 /*
2081 * Read a four-byte integer, which is the length of the JSON to follow.
2082 * Then read the JSON into a buffer and parse it. Return a parsed JSON
2083 * structure, NULL if there was an error.
2084 */
2085 if (Nread(fd, (char*) &nsize, sizeof(nsize), Ptcp) >= 0) {
2086 hsize = ntohl(nsize);
2087 /* Allocate a buffer to hold the JSON */
2088 str = (char *) calloc(sizeof(char), hsize+1); /* +1 for trailing null */
2089 if (str != NULL) {
2090 rc = Nread(fd, str, hsize, Ptcp);
2091 if (rc >= 0) {
2092 /*
2093 * We should be reading in the number of bytes corresponding to the
2094 * length in that 4-byte integer. If we don't the socket might have
2095 * prematurely closed. Only do the JSON parsing if we got the
2096 * correct number of bytes.
2097 */
2098 if (rc == hsize) {
2099 json = cJSON_Parse(str);
2100 }
2101 else {
2102 printf("WARNING: Size of data read does not correspond to offered length\n");
2103 }
2104 }
2105 }
2106 free(str);
2107 }
2108 return json;
2109 }
2110
2111 /*************************************************************/
2112 /**
2113 * add_to_interval_list -- adds new interval to the interval_list
2114 */
2115
2116 void
add_to_interval_list(struct iperf_stream_result * rp,struct iperf_interval_results * new)2117 add_to_interval_list(struct iperf_stream_result * rp, struct iperf_interval_results * new)
2118 {
2119 struct iperf_interval_results *irp;
2120
2121 irp = (struct iperf_interval_results *) malloc(sizeof(struct iperf_interval_results));
2122 memcpy(irp, new, sizeof(struct iperf_interval_results));
2123 TAILQ_INSERT_TAIL(&rp->interval_results, irp, irlistentries);
2124 }
2125
2126
2127 /************************************************************/
2128
2129 /**
2130 * connect_msg -- displays connection message
2131 * denoting sender/receiver details
2132 *
2133 */
2134
2135 void
connect_msg(struct iperf_stream * sp)2136 connect_msg(struct iperf_stream *sp)
2137 {
2138 char ipl[INET6_ADDRSTRLEN], ipr[INET6_ADDRSTRLEN];
2139 int lport, rport;
2140
2141 if (getsockdomain(sp->socket) == AF_INET) {
2142 inet_ntop(AF_INET, (void *) &((struct sockaddr_in *) &sp->local_addr)->sin_addr, ipl, sizeof(ipl));
2143 mapped_v4_to_regular_v4(ipl);
2144 inet_ntop(AF_INET, (void *) &((struct sockaddr_in *) &sp->remote_addr)->sin_addr, ipr, sizeof(ipr));
2145 mapped_v4_to_regular_v4(ipr);
2146 lport = ntohs(((struct sockaddr_in *) &sp->local_addr)->sin_port);
2147 rport = ntohs(((struct sockaddr_in *) &sp->remote_addr)->sin_port);
2148 } else {
2149 inet_ntop(AF_INET6, (void *) &((struct sockaddr_in6 *) &sp->local_addr)->sin6_addr, ipl, sizeof(ipl));
2150 mapped_v4_to_regular_v4(ipl);
2151 inet_ntop(AF_INET6, (void *) &((struct sockaddr_in6 *) &sp->remote_addr)->sin6_addr, ipr, sizeof(ipr));
2152 mapped_v4_to_regular_v4(ipr);
2153 lport = ntohs(((struct sockaddr_in6 *) &sp->local_addr)->sin6_port);
2154 rport = ntohs(((struct sockaddr_in6 *) &sp->remote_addr)->sin6_port);
2155 }
2156
2157 if (sp->test->json_output)
2158 cJSON_AddItemToArray(sp->test->json_connected, iperf_json_printf("socket: %d local_host: %s local_port: %d remote_host: %s remote_port: %d", (int64_t) sp->socket, ipl, (int64_t) lport, ipr, (int64_t) rport));
2159 else
2160 iperf_printf(sp->test, report_connected, sp->socket, ipl, lport, ipr, rport);
2161 }
2162
2163
2164 /**************************************************************************/
2165
2166 struct iperf_test *
iperf_new_test()2167 iperf_new_test()
2168 {
2169 struct iperf_test *test;
2170
2171 test = (struct iperf_test *) malloc(sizeof(struct iperf_test));
2172 if (!test) {
2173 i_errno = IENEWTEST;
2174 return NULL;
2175 }
2176 /* initialize everything to zero */
2177 memset(test, 0, sizeof(struct iperf_test));
2178
2179 test->settings = (struct iperf_settings *) malloc(sizeof(struct iperf_settings));
2180 if (!test->settings) {
2181 free(test);
2182 i_errno = IENEWTEST;
2183 return NULL;
2184 }
2185 memset(test->settings, 0, sizeof(struct iperf_settings));
2186
2187 /* By default all output goes to stdout */
2188 test->outfile = stdout;
2189
2190 return test;
2191 }
2192
2193 /**************************************************************************/
2194
2195 struct protocol *
protocol_new(void)2196 protocol_new(void)
2197 {
2198 struct protocol *proto;
2199
2200 proto = malloc(sizeof(struct protocol));
2201 if(!proto) {
2202 return NULL;
2203 }
2204 memset(proto, 0, sizeof(struct protocol));
2205
2206 return proto;
2207 }
2208
2209 void
protocol_free(struct protocol * proto)2210 protocol_free(struct protocol *proto)
2211 {
2212 free(proto);
2213 }
2214
2215 /**************************************************************************/
2216 int
iperf_defaults(struct iperf_test * testp)2217 iperf_defaults(struct iperf_test *testp)
2218 {
2219 struct protocol *tcp, *udp;
2220 #if defined(HAVE_SCTP)
2221 struct protocol *sctp;
2222 #endif /* HAVE_SCTP */
2223
2224 testp->omit = OMIT;
2225 testp->duration = DURATION;
2226 testp->diskfile_name = (char*) 0;
2227 testp->affinity = -1;
2228 testp->server_affinity = -1;
2229 TAILQ_INIT(&testp->xbind_addrs);
2230 #if defined(HAVE_CPUSET_SETAFFINITY)
2231 CPU_ZERO(&testp->cpumask);
2232 #endif /* HAVE_CPUSET_SETAFFINITY */
2233 testp->title = NULL;
2234 testp->extra_data = NULL;
2235 testp->congestion = NULL;
2236 testp->congestion_used = NULL;
2237 testp->remote_congestion_used = NULL;
2238 testp->server_port = PORT;
2239 testp->ctrl_sck = -1;
2240 testp->prot_listener = -1;
2241 testp->other_side_has_retransmits = 0;
2242
2243 testp->stats_callback = iperf_stats_callback;
2244 testp->reporter_callback = iperf_reporter_callback;
2245
2246 testp->stats_interval = testp->reporter_interval = 1;
2247 testp->num_streams = 1;
2248
2249 testp->settings->domain = AF_UNSPEC;
2250 testp->settings->unit_format = 'a';
2251 testp->settings->socket_bufsize = 0; /* use autotuning */
2252 testp->settings->blksize = DEFAULT_TCP_BLKSIZE;
2253 testp->settings->rate = 0;
2254 testp->settings->fqrate = 0;
2255 testp->settings->pacing_timer = 1000;
2256 testp->settings->burst = 0;
2257 testp->settings->mss = 0;
2258 testp->settings->bytes = 0;
2259 testp->settings->blocks = 0;
2260 testp->settings->connect_timeout = -1;
2261 memset(testp->cookie, 0, COOKIE_SIZE);
2262
2263 testp->multisend = 10; /* arbitrary */
2264
2265 /* Set up protocol list */
2266 SLIST_INIT(&testp->streams);
2267 SLIST_INIT(&testp->protocols);
2268
2269 tcp = protocol_new();
2270 if (!tcp)
2271 return -1;
2272
2273 tcp->id = Ptcp;
2274 tcp->name = "TCP";
2275 tcp->accept = iperf_tcp_accept;
2276 tcp->listen = iperf_tcp_listen;
2277 tcp->connect = iperf_tcp_connect;
2278 tcp->send = iperf_tcp_send;
2279 tcp->recv = iperf_tcp_recv;
2280 tcp->init = NULL;
2281 SLIST_INSERT_HEAD(&testp->protocols, tcp, protocols);
2282
2283 udp = protocol_new();
2284 if (!udp) {
2285 protocol_free(tcp);
2286 return -1;
2287 }
2288
2289 udp->id = Pudp;
2290 udp->name = "UDP";
2291 udp->accept = iperf_udp_accept;
2292 udp->listen = iperf_udp_listen;
2293 udp->connect = iperf_udp_connect;
2294 udp->send = iperf_udp_send;
2295 udp->recv = iperf_udp_recv;
2296 udp->init = iperf_udp_init;
2297 SLIST_INSERT_AFTER(tcp, udp, protocols);
2298
2299 set_protocol(testp, Ptcp);
2300
2301 #if defined(HAVE_SCTP)
2302 sctp = protocol_new();
2303 if (!sctp) {
2304 protocol_free(tcp);
2305 protocol_free(udp);
2306 return -1;
2307 }
2308
2309 sctp->id = Psctp;
2310 sctp->name = "SCTP";
2311 sctp->accept = iperf_sctp_accept;
2312 sctp->listen = iperf_sctp_listen;
2313 sctp->connect = iperf_sctp_connect;
2314 sctp->send = iperf_sctp_send;
2315 sctp->recv = iperf_sctp_recv;
2316 sctp->init = iperf_sctp_init;
2317
2318 SLIST_INSERT_AFTER(udp, sctp, protocols);
2319 #endif /* HAVE_SCTP */
2320
2321 testp->on_new_stream = iperf_on_new_stream;
2322 testp->on_test_start = iperf_on_test_start;
2323 testp->on_connect = iperf_on_connect;
2324 testp->on_test_finish = iperf_on_test_finish;
2325
2326 TAILQ_INIT(&testp->server_output_list);
2327
2328 return 0;
2329 }
2330
2331
2332 /**************************************************************************/
2333 void
iperf_free_test(struct iperf_test * test)2334 iperf_free_test(struct iperf_test *test)
2335 {
2336 struct protocol *prot;
2337 struct iperf_stream *sp;
2338
2339 /* Free streams */
2340 while (!SLIST_EMPTY(&test->streams)) {
2341 sp = SLIST_FIRST(&test->streams);
2342 SLIST_REMOVE_HEAD(&test->streams, streams);
2343 iperf_free_stream(sp);
2344 }
2345
2346 if (test->server_hostname)
2347 free(test->server_hostname);
2348 if (test->tmp_template)
2349 free(test->tmp_template);
2350 if (test->bind_address)
2351 free(test->bind_address);
2352 if (!TAILQ_EMPTY(&test->xbind_addrs)) {
2353 struct xbind_entry *xbe;
2354
2355 while (!TAILQ_EMPTY(&test->xbind_addrs)) {
2356 xbe = TAILQ_FIRST(&test->xbind_addrs);
2357 TAILQ_REMOVE(&test->xbind_addrs, xbe, link);
2358 if (xbe->ai)
2359 freeaddrinfo(xbe->ai);
2360 free(xbe->name);
2361 free(xbe);
2362 }
2363 }
2364 if (test->settings)
2365 free(test->settings);
2366 if (test->title)
2367 free(test->title);
2368 if (test->extra_data)
2369 free(test->extra_data);
2370 if (test->congestion)
2371 free(test->congestion);
2372 if (test->congestion_used)
2373 free(test->congestion_used);
2374 if (test->remote_congestion_used)
2375 free(test->remote_congestion_used);
2376 if (test->omit_timer != NULL)
2377 tmr_cancel(test->omit_timer);
2378 if (test->timer != NULL)
2379 tmr_cancel(test->timer);
2380 if (test->stats_timer != NULL)
2381 tmr_cancel(test->stats_timer);
2382 if (test->reporter_timer != NULL)
2383 tmr_cancel(test->reporter_timer);
2384
2385 /* Free protocol list */
2386 while (!SLIST_EMPTY(&test->protocols)) {
2387 prot = SLIST_FIRST(&test->protocols);
2388 SLIST_REMOVE_HEAD(&test->protocols, protocols);
2389 free(prot);
2390 }
2391
2392 if (test->server_output_text) {
2393 free(test->server_output_text);
2394 test->server_output_text = NULL;
2395 }
2396
2397 if (test->json_output_string) {
2398 free(test->json_output_string);
2399 test->json_output_string = NULL;
2400 }
2401
2402 /* Free output line buffers, if any (on the server only) */
2403 struct iperf_textline *t;
2404 while (!TAILQ_EMPTY(&test->server_output_list)) {
2405 t = TAILQ_FIRST(&test->server_output_list);
2406 TAILQ_REMOVE(&test->server_output_list, t, textlineentries);
2407 free(t->line);
2408 free(t);
2409 }
2410
2411 /* sctp_bindx: do not free the arguments, only the resolver results */
2412 if (!TAILQ_EMPTY(&test->xbind_addrs)) {
2413 struct xbind_entry *xbe;
2414
2415 TAILQ_FOREACH(xbe, &test->xbind_addrs, link) {
2416 if (xbe->ai) {
2417 freeaddrinfo(xbe->ai);
2418 xbe->ai = NULL;
2419 }
2420 }
2421 }
2422
2423 /* XXX: Why are we setting these values to NULL? */
2424 // test->streams = NULL;
2425 test->stats_callback = NULL;
2426 test->reporter_callback = NULL;
2427 free(test);
2428 }
2429
2430
2431 void
iperf_reset_test(struct iperf_test * test)2432 iperf_reset_test(struct iperf_test *test)
2433 {
2434 struct iperf_stream *sp;
2435
2436 /* Free streams */
2437 while (!SLIST_EMPTY(&test->streams)) {
2438 sp = SLIST_FIRST(&test->streams);
2439 SLIST_REMOVE_HEAD(&test->streams, streams);
2440 iperf_free_stream(sp);
2441 }
2442 if (test->omit_timer != NULL) {
2443 tmr_cancel(test->omit_timer);
2444 test->omit_timer = NULL;
2445 }
2446 if (test->timer != NULL) {
2447 tmr_cancel(test->timer);
2448 test->timer = NULL;
2449 }
2450 if (test->stats_timer != NULL) {
2451 tmr_cancel(test->stats_timer);
2452 test->stats_timer = NULL;
2453 }
2454 if (test->reporter_timer != NULL) {
2455 tmr_cancel(test->reporter_timer);
2456 test->reporter_timer = NULL;
2457 }
2458 test->done = 0;
2459
2460 SLIST_INIT(&test->streams);
2461
2462 test->role = 's';
2463 test->mode = RECEIVER;
2464 test->sender_has_retransmits = 0;
2465 set_protocol(test, Ptcp);
2466 test->omit = OMIT;
2467 test->duration = DURATION;
2468 test->server_affinity = -1;
2469 #if defined(HAVE_CPUSET_SETAFFINITY)
2470 CPU_ZERO(&test->cpumask);
2471 #endif /* HAVE_CPUSET_SETAFFINITY */
2472 test->state = 0;
2473
2474 test->ctrl_sck = -1;
2475 test->prot_listener = -1;
2476
2477 test->bytes_sent = 0;
2478 test->blocks_sent = 0;
2479
2480 test->bytes_received = 0;
2481 test->blocks_received = 0;
2482
2483 test->other_side_has_retransmits = 0;
2484
2485 test->reverse = 0;
2486 test->bidirectional = 0;
2487 test->no_delay = 0;
2488
2489 FD_ZERO(&test->read_set);
2490 FD_ZERO(&test->write_set);
2491
2492 test->num_streams = 1;
2493 test->settings->socket_bufsize = 0;
2494 test->settings->blksize = DEFAULT_TCP_BLKSIZE;
2495 test->settings->rate = 0;
2496 test->settings->burst = 0;
2497 test->settings->mss = 0;
2498 test->settings->tos = 0;
2499
2500 #if defined(HAVE_SSL)
2501 if (test->settings->authtoken) {
2502 free(test->settings->authtoken);
2503 test->settings->authtoken = NULL;
2504 }
2505 if (test->settings->client_username) {
2506 free(test->settings->client_username);
2507 test->settings->client_username = NULL;
2508 }
2509 if (test->settings->client_password) {
2510 free(test->settings->client_password);
2511 test->settings->client_password = NULL;
2512 }
2513 if (test->settings->client_rsa_pubkey) {
2514 EVP_PKEY_free(test->settings->client_rsa_pubkey);
2515 test->settings->client_rsa_pubkey = NULL;
2516 }
2517 #endif /* HAVE_SSL */
2518
2519 memset(test->cookie, 0, COOKIE_SIZE);
2520 test->multisend = 10; /* arbitrary */
2521 test->udp_counters_64bit = 0;
2522 if (test->title) {
2523 free(test->title);
2524 test->title = NULL;
2525 }
2526 if (test->extra_data) {
2527 free(test->extra_data);
2528 test->extra_data = NULL;
2529 }
2530
2531 /* Free output line buffers, if any (on the server only) */
2532 struct iperf_textline *t;
2533 while (!TAILQ_EMPTY(&test->server_output_list)) {
2534 t = TAILQ_FIRST(&test->server_output_list);
2535 TAILQ_REMOVE(&test->server_output_list, t, textlineentries);
2536 free(t->line);
2537 free(t);
2538 }
2539 }
2540
2541
2542 /* Reset all of a test's stats back to zero. Called when the omitting
2543 ** period is over.
2544 */
2545 void
iperf_reset_stats(struct iperf_test * test)2546 iperf_reset_stats(struct iperf_test *test)
2547 {
2548 struct iperf_time now;
2549 struct iperf_stream *sp;
2550 struct iperf_stream_result *rp;
2551
2552 test->bytes_sent = 0;
2553 test->blocks_sent = 0;
2554 iperf_time_now(&now);
2555 SLIST_FOREACH(sp, &test->streams, streams) {
2556 sp->omitted_packet_count = sp->packet_count;
2557 sp->omitted_cnt_error = sp->cnt_error;
2558 sp->omitted_outoforder_packets = sp->outoforder_packets;
2559 sp->jitter = 0;
2560 rp = sp->result;
2561 rp->bytes_sent_omit = rp->bytes_sent;
2562 rp->bytes_received = 0;
2563 rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;
2564 if (test->sender_has_retransmits == 1) {
2565 struct iperf_interval_results ir; /* temporary results structure */
2566 save_tcpinfo(sp, &ir);
2567 rp->stream_prev_total_retrans = get_total_retransmits(&ir);
2568 }
2569 rp->stream_retrans = 0;
2570 rp->start_time = now;
2571 }
2572 }
2573
2574
2575 /**************************************************************************/
2576
2577 /**
2578 * Gather statistics during a test.
2579 * This function works for both the client and server side.
2580 */
2581 void
iperf_stats_callback(struct iperf_test * test)2582 iperf_stats_callback(struct iperf_test *test)
2583 {
2584 struct iperf_stream *sp;
2585 struct iperf_stream_result *rp = NULL;
2586 struct iperf_interval_results *irp, temp;
2587 struct iperf_time temp_time;
2588
2589 temp.omitted = test->omitting;
2590 SLIST_FOREACH(sp, &test->streams, streams) {
2591 rp = sp->result;
2592 temp.bytes_transferred = sp->sender ? rp->bytes_sent_this_interval : rp->bytes_received_this_interval;
2593
2594 irp = TAILQ_LAST(&rp->interval_results, irlisthead);
2595 /* result->end_time contains timestamp of previous interval */
2596 if ( irp != NULL ) /* not the 1st interval */
2597 memcpy(&temp.interval_start_time, &rp->end_time, sizeof(struct iperf_time));
2598 else /* or use timestamp from beginning */
2599 memcpy(&temp.interval_start_time, &rp->start_time, sizeof(struct iperf_time));
2600 /* now save time of end of this interval */
2601 iperf_time_now(&rp->end_time);
2602 memcpy(&temp.interval_end_time, &rp->end_time, sizeof(struct iperf_time));
2603 iperf_time_diff(&temp.interval_start_time, &temp.interval_end_time, &temp_time);
2604 temp.interval_duration = iperf_time_in_secs(&temp_time);
2605 if (test->protocol->id == Ptcp) {
2606 if ( has_tcpinfo()) {
2607 save_tcpinfo(sp, &temp);
2608 if (test->sender_has_retransmits == 1) {
2609 long total_retrans = get_total_retransmits(&temp);
2610 temp.interval_retrans = total_retrans - rp->stream_prev_total_retrans;
2611 rp->stream_retrans += temp.interval_retrans;
2612 rp->stream_prev_total_retrans = total_retrans;
2613
2614 temp.snd_cwnd = get_snd_cwnd(&temp);
2615 if (temp.snd_cwnd > rp->stream_max_snd_cwnd) {
2616 rp->stream_max_snd_cwnd = temp.snd_cwnd;
2617 }
2618
2619 temp.rtt = get_rtt(&temp);
2620 if (temp.rtt > rp->stream_max_rtt) {
2621 rp->stream_max_rtt = temp.rtt;
2622 }
2623 if (rp->stream_min_rtt == 0 ||
2624 temp.rtt < rp->stream_min_rtt) {
2625 rp->stream_min_rtt = temp.rtt;
2626 }
2627 rp->stream_sum_rtt += temp.rtt;
2628 rp->stream_count_rtt++;
2629
2630 temp.rttvar = get_rttvar(&temp);
2631 temp.pmtu = get_pmtu(&temp);
2632 }
2633 }
2634 } else {
2635 if (irp == NULL) {
2636 temp.interval_packet_count = sp->packet_count;
2637 temp.interval_outoforder_packets = sp->outoforder_packets;
2638 temp.interval_cnt_error = sp->cnt_error;
2639 } else {
2640 temp.interval_packet_count = sp->packet_count - irp->packet_count;
2641 temp.interval_outoforder_packets = sp->outoforder_packets - irp->outoforder_packets;
2642 temp.interval_cnt_error = sp->cnt_error - irp->cnt_error;
2643 }
2644 temp.packet_count = sp->packet_count;
2645 temp.jitter = sp->jitter;
2646 temp.outoforder_packets = sp->outoforder_packets;
2647 temp.cnt_error = sp->cnt_error;
2648 }
2649 add_to_interval_list(rp, &temp);
2650 rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;
2651 }
2652 }
2653
2654 /**
2655 * Print intermediate results during a test (interval report).
2656 * Uses print_interval_results to print the results for each stream,
2657 * then prints an interval summary for all streams in this
2658 * interval.
2659 */
2660 static void
iperf_print_intermediate(struct iperf_test * test)2661 iperf_print_intermediate(struct iperf_test *test)
2662 {
2663 struct iperf_stream *sp = NULL;
2664 struct iperf_interval_results *irp;
2665 struct iperf_time temp_time;
2666 cJSON *json_interval;
2667 cJSON *json_interval_streams;
2668
2669 int lower_mode, upper_mode;
2670 int current_mode;
2671
2672 /*
2673 * Due to timing oddities, there can be cases, especially on the
2674 * server side, where at the end of a test there is a fairly short
2675 * interval with no data transferred. This could caused by
2676 * the control and data flows sharing the same path in the network,
2677 * and having the control messages for stopping the test being
2678 * queued behind the data packets.
2679 *
2680 * We'd like to try to omit that last interval when it happens, to
2681 * avoid cluttering data and output with useless stuff.
2682 * So we're going to try to ignore very short intervals (less than
2683 * 10% of the interval time) that have no data.
2684 */
2685 int interval_ok = 0;
2686 SLIST_FOREACH(sp, &test->streams, streams) {
2687 irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);
2688 if (irp) {
2689 iperf_time_diff(&irp->interval_start_time, &irp->interval_end_time, &temp_time);
2690 double interval_len = iperf_time_in_secs(&temp_time);
2691 if (test->debug) {
2692 printf("interval_len %f bytes_transferred %" PRIu64 "\n", interval_len, irp->bytes_transferred);
2693 }
2694
2695 /*
2696 * If the interval is at least 10% the normal interval
2697 * length, or if there were actual bytes transferrred,
2698 * then we want to keep this interval.
2699 */
2700 if (interval_len >= test->stats_interval * 0.10 ||
2701 irp->bytes_transferred > 0) {
2702 interval_ok = 1;
2703 if (test->debug) {
2704 printf("interval forces keep\n");
2705 }
2706 }
2707 }
2708 }
2709 if (!interval_ok) {
2710 if (test->debug) {
2711 printf("ignoring short interval with no data\n");
2712 }
2713 return;
2714 }
2715
2716 if (test->json_output) {
2717 json_interval = cJSON_CreateObject();
2718 if (json_interval == NULL)
2719 return;
2720 cJSON_AddItemToArray(test->json_intervals, json_interval);
2721 json_interval_streams = cJSON_CreateArray();
2722 if (json_interval_streams == NULL)
2723 return;
2724 cJSON_AddItemToObject(json_interval, "streams", json_interval_streams);
2725 } else {
2726 json_interval = NULL;
2727 json_interval_streams = NULL;
2728 }
2729
2730 /*
2731 * We must to sum streams separately.
2732 * For bidirectional mode we must to display
2733 * information about sender and receiver streams.
2734 * For client side we must handle sender streams
2735 * firstly and receiver streams for server side.
2736 * The following design allows us to do this.
2737 */
2738
2739 if (test->mode == BIDIRECTIONAL) {
2740 if (test->role == 'c') {
2741 lower_mode = -1;
2742 upper_mode = 0;
2743 } else {
2744 lower_mode = 0;
2745 upper_mode = 1;
2746 }
2747 } else {
2748 lower_mode = test->mode;
2749 upper_mode = lower_mode;
2750 }
2751
2752
2753 for (current_mode = lower_mode; current_mode <= upper_mode; ++current_mode) {
2754 char ubuf[UNIT_LEN];
2755 char nbuf[UNIT_LEN];
2756 char mbuf[UNIT_LEN];
2757 char zbuf[] = " ";
2758
2759 iperf_size_t bytes = 0;
2760 double bandwidth;
2761 int retransmits = 0;
2762 double start_time, end_time;
2763
2764 int total_packets = 0, lost_packets = 0;
2765 double avg_jitter = 0.0, lost_percent;
2766 int stream_must_be_sender = current_mode * current_mode;
2767
2768 /* Print stream role just for bidirectional mode. */
2769
2770 if (test->mode == BIDIRECTIONAL) {
2771 sprintf(mbuf, "[%s-%s]", stream_must_be_sender?"TX":"RX", test->role == 'c'?"C":"S");
2772 } else {
2773 mbuf[0] = '\0';
2774 zbuf[0] = '\0';
2775 }
2776
2777 SLIST_FOREACH(sp, &test->streams, streams) {
2778 if (sp->sender == stream_must_be_sender) {
2779 print_interval_results(test, sp, json_interval_streams);
2780 /* sum up all streams */
2781 irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);
2782 if (irp == NULL) {
2783 iperf_err(test,
2784 "iperf_print_intermediate error: interval_results is NULL");
2785 return;
2786 }
2787 bytes += irp->bytes_transferred;
2788 if (test->protocol->id == Ptcp) {
2789 if (test->sender_has_retransmits == 1) {
2790 retransmits += irp->interval_retrans;
2791 }
2792 } else {
2793 total_packets += irp->interval_packet_count;
2794 lost_packets += irp->interval_cnt_error;
2795 avg_jitter += irp->jitter;
2796 }
2797 }
2798 }
2799
2800 /* next build string with sum of all streams */
2801 if (test->num_streams > 1 || test->json_output) {
2802 sp = SLIST_FIRST(&test->streams); /* reset back to 1st stream */
2803 /* Only do this of course if there was a first stream */
2804 if (sp) {
2805 irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); /* use 1st stream for timing info */
2806
2807 unit_snprintf(ubuf, UNIT_LEN, (double) bytes, 'A');
2808 bandwidth = (double) bytes / (double) irp->interval_duration;
2809 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
2810
2811 iperf_time_diff(&sp->result->start_time,&irp->interval_start_time, &temp_time);
2812 start_time = iperf_time_in_secs(&temp_time);
2813 iperf_time_diff(&sp->result->start_time,&irp->interval_end_time, &temp_time);
2814 end_time = iperf_time_in_secs(&temp_time);
2815 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
2816 if (test->sender_has_retransmits == 1 && stream_must_be_sender) {
2817 /* Interval sum, TCP with retransmits. */
2818 if (test->json_output)
2819 cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f retransmits: %d omitted: %b sender: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, (int64_t) retransmits, irp->omitted, stream_must_be_sender)); /* XXX irp->omitted or test->omitting? */
2820 else
2821 iperf_printf(test, report_sum_bw_retrans_format, mbuf, start_time, end_time, ubuf, nbuf, retransmits, irp->omitted?report_omitted:""); /* XXX irp->omitted or test->omitting? */
2822 } else {
2823 /* Interval sum, TCP without retransmits. */
2824 if (test->json_output)
2825 cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f omitted: %b sender: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, test->omitting, stream_must_be_sender));
2826 else
2827 iperf_printf(test, report_sum_bw_format, mbuf, start_time, end_time, ubuf, nbuf, test->omitting?report_omitted:"");
2828 }
2829 } else {
2830 /* Interval sum, UDP. */
2831 if (stream_must_be_sender) {
2832 if (test->json_output)
2833 cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f packets: %d omitted: %b sender: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, (int64_t) total_packets, test->omitting, stream_must_be_sender));
2834 else
2835 iperf_printf(test, report_sum_bw_udp_sender_format, mbuf, start_time, end_time, ubuf, nbuf, zbuf, total_packets, test->omitting?report_omitted:"");
2836 } else {
2837 avg_jitter /= test->num_streams;
2838 if (total_packets > 0) {
2839 lost_percent = 100.0 * lost_packets / total_packets;
2840 }
2841 else {
2842 lost_percent = 0.0;
2843 }
2844 if (test->json_output)
2845 cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f jitter_ms: %f lost_packets: %d packets: %d lost_percent: %f omitted: %b sender: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, (double) avg_jitter * 1000.0, (int64_t) lost_packets, (int64_t) total_packets, (double) lost_percent, test->omitting, stream_must_be_sender));
2846 else
2847 iperf_printf(test, report_sum_bw_udp_format, mbuf, start_time, end_time, ubuf, nbuf, avg_jitter * 1000.0, lost_packets, total_packets, lost_percent, test->omitting?report_omitted:"");
2848 }
2849 }
2850 }
2851 }
2852 }
2853 }
2854
2855 /**
2856 * Print overall summary statistics at the end of a test.
2857 */
2858 static void
iperf_print_results(struct iperf_test * test)2859 iperf_print_results(struct iperf_test *test)
2860 {
2861
2862 cJSON *json_summary_streams = NULL;
2863
2864 int lower_mode, upper_mode;
2865 int current_mode;
2866
2867 int tmp_sender_has_retransmits = test->sender_has_retransmits;
2868
2869 /* print final summary for all intervals */
2870
2871 if (test->json_output) {
2872 json_summary_streams = cJSON_CreateArray();
2873 if (json_summary_streams == NULL)
2874 return;
2875 cJSON_AddItemToObject(test->json_end, "streams", json_summary_streams);
2876 } else {
2877 iperf_printf(test, "%s", report_bw_separator);
2878 if (test->verbose)
2879 iperf_printf(test, "%s", report_summary);
2880 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
2881 if (test->sender_has_retransmits || test->other_side_has_retransmits) {
2882 if (test->bidirectional)
2883 iperf_printf(test, "%s", report_bw_retrans_header_bidir);
2884 else
2885 iperf_printf(test, "%s", report_bw_retrans_header);
2886 }
2887 else {
2888 if (test->bidirectional)
2889 iperf_printf(test, "%s", report_bw_header_bidir);
2890 else
2891 iperf_printf(test, "%s", report_bw_header);
2892 }
2893 } else {
2894 if (test->bidirectional)
2895 iperf_printf(test, "%s", report_bw_udp_header_bidir);
2896 else
2897 iperf_printf(test, "%s", report_bw_udp_header);
2898 }
2899 }
2900
2901 /*
2902 * We must to sum streams separately.
2903 * For bidirectional mode we must to display
2904 * information about sender and receiver streams.
2905 * For client side we must handle sender streams
2906 * firstly and receiver streams for server side.
2907 * The following design allows us to do this.
2908 */
2909
2910 if (test->mode == BIDIRECTIONAL) {
2911 if (test->role == 'c') {
2912 lower_mode = -1;
2913 upper_mode = 0;
2914 } else {
2915 lower_mode = 0;
2916 upper_mode = 1;
2917 }
2918 } else {
2919 lower_mode = test->mode;
2920 upper_mode = lower_mode;
2921 }
2922
2923
2924 for (current_mode = lower_mode; current_mode <= upper_mode; ++current_mode) {
2925 cJSON *json_summary_stream = NULL;
2926 int total_retransmits = 0;
2927 int total_packets = 0, lost_packets = 0;
2928 int sender_packet_count = 0, receiver_packet_count = 0; /* for this stream, this interval */
2929 int sender_total_packets = 0, receiver_total_packets = 0; /* running total */
2930 char ubuf[UNIT_LEN];
2931 char nbuf[UNIT_LEN];
2932 struct stat sb;
2933 char sbuf[UNIT_LEN];
2934 struct iperf_stream *sp = NULL;
2935 iperf_size_t bytes_sent, total_sent = 0;
2936 iperf_size_t bytes_received, total_received = 0;
2937 double start_time, end_time = 0.0, avg_jitter = 0.0, lost_percent = 0.0;
2938 double sender_time = 0.0, receiver_time = 0.0;
2939 struct iperf_time temp_time;
2940 double bandwidth;
2941
2942 char mbuf[UNIT_LEN];
2943 int stream_must_be_sender = current_mode * current_mode;
2944
2945
2946 /* Print stream role just for bidirectional mode. */
2947
2948 if (test->mode == BIDIRECTIONAL) {
2949 sprintf(mbuf, "[%s-%s]", stream_must_be_sender?"TX":"RX", test->role == 'c'?"C":"S");
2950 } else {
2951 mbuf[0] = '\0';
2952 }
2953
2954 /* Get sender_has_retransmits for each sender side (client and server) */
2955 if (test->mode == BIDIRECTIONAL && stream_must_be_sender)
2956 test->sender_has_retransmits = tmp_sender_has_retransmits;
2957 else if (test->mode == BIDIRECTIONAL && !stream_must_be_sender)
2958 test->sender_has_retransmits = test->other_side_has_retransmits;
2959
2960 start_time = 0.;
2961 sp = SLIST_FIRST(&test->streams);
2962
2963 /*
2964 * If there is at least one stream, then figure out the length of time
2965 * we were running the tests and print out some statistics about
2966 * the streams. It's possible to not have any streams at all
2967 * if the client got interrupted before it got to do anything.
2968 *
2969 * Also note that we try to keep seperate values for the sender
2970 * and receiver ending times. Earlier iperf (3.1 and earlier)
2971 * servers didn't send that to the clients, so in this case we fall
2972 * back to using the client's ending timestamp. The fallback is
2973 * basically emulating what iperf 3.1 did.
2974 */
2975
2976 if (sp) {
2977 iperf_time_diff(&sp->result->start_time, &sp->result->end_time, &temp_time);
2978 end_time = iperf_time_in_secs(&temp_time);
2979 if (sp->sender) {
2980 sp->result->sender_time = end_time;
2981 if (sp->result->receiver_time == 0.0) {
2982 sp->result->receiver_time = sp->result->sender_time;
2983 }
2984 }
2985 else {
2986 sp->result->receiver_time = end_time;
2987 if (sp->result->sender_time == 0.0) {
2988 sp->result->sender_time = sp->result->receiver_time;
2989 }
2990 }
2991 sender_time = sp->result->sender_time;
2992 receiver_time = sp->result->receiver_time;
2993 SLIST_FOREACH(sp, &test->streams, streams) {
2994 if (sp->sender == stream_must_be_sender) {
2995 if (test->json_output) {
2996 json_summary_stream = cJSON_CreateObject();
2997 if (json_summary_stream == NULL)
2998 return;
2999 cJSON_AddItemToArray(json_summary_streams, json_summary_stream);
3000 }
3001
3002 bytes_sent = sp->result->bytes_sent - sp->result->bytes_sent_omit;
3003 bytes_received = sp->result->bytes_received;
3004 total_sent += bytes_sent;
3005 total_received += bytes_received;
3006
3007 if (sp->sender) {
3008 sender_packet_count = sp->packet_count;
3009 receiver_packet_count = sp->peer_packet_count;
3010 }
3011 else {
3012 sender_packet_count = sp->peer_packet_count;
3013 receiver_packet_count = sp->packet_count;
3014 }
3015
3016 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
3017 if (test->sender_has_retransmits) {
3018 total_retransmits += sp->result->stream_retrans;
3019 }
3020 } else {
3021 /*
3022 * Running total of the total number of packets. Use the sender packet count if we
3023 * have it, otherwise use the receiver packet count.
3024 */
3025 int packet_count = sender_packet_count ? sender_packet_count : receiver_packet_count;
3026 total_packets += (packet_count - sp->omitted_packet_count);
3027 sender_total_packets += (sender_packet_count - sp->omitted_packet_count);
3028 receiver_total_packets += (receiver_packet_count - sp->omitted_packet_count);
3029 lost_packets += (sp->cnt_error - sp->omitted_cnt_error);
3030 avg_jitter += sp->jitter;
3031 }
3032
3033 unit_snprintf(ubuf, UNIT_LEN, (double) bytes_sent, 'A');
3034 if (sender_time > 0.0) {
3035 bandwidth = (double) bytes_sent / (double) sender_time;
3036 }
3037 else {
3038 bandwidth = 0.0;
3039 }
3040 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
3041 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
3042 if (test->sender_has_retransmits) {
3043 /* Sender summary, TCP and SCTP with retransmits. */
3044 if (test->json_output)
3045 cJSON_AddItemToObject(json_summary_stream, "sender", iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f retransmits: %d max_snd_cwnd: %d max_rtt: %d min_rtt: %d mean_rtt: %d sender: %b", (int64_t) sp->socket, (double) start_time, (double) sender_time, (double) sender_time, (int64_t) bytes_sent, bandwidth * 8, (int64_t) sp->result->stream_retrans, (int64_t) sp->result->stream_max_snd_cwnd, (int64_t) sp->result->stream_max_rtt, (int64_t) sp->result->stream_min_rtt, (int64_t) ((sp->result->stream_count_rtt == 0) ? 0 : sp->result->stream_sum_rtt / sp->result->stream_count_rtt), stream_must_be_sender));
3046 else
3047 if (test->role == 's' && !sp->sender) {
3048 if (test->verbose)
3049 iperf_printf(test, report_sender_not_available_format, sp->socket);
3050 }
3051 else {
3052 iperf_printf(test, report_bw_retrans_format, sp->socket, mbuf, start_time, sender_time, ubuf, nbuf, sp->result->stream_retrans, report_sender);
3053 }
3054 } else {
3055 /* Sender summary, TCP and SCTP without retransmits. */
3056 if (test->json_output)
3057 cJSON_AddItemToObject(json_summary_stream, "sender", iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f sender: %b", (int64_t) sp->socket, (double) start_time, (double) sender_time, (double) sender_time, (int64_t) bytes_sent, bandwidth * 8, stream_must_be_sender));
3058 else
3059 if (test->role == 's' && !sp->sender) {
3060 if (test->verbose)
3061 iperf_printf(test, report_sender_not_available_format, sp->socket);
3062 }
3063 else {
3064 iperf_printf(test, report_bw_format, sp->socket, mbuf, start_time, sender_time, ubuf, nbuf, report_sender);
3065 }
3066 }
3067 } else {
3068 /* Sender summary, UDP. */
3069 if (sender_packet_count - sp->omitted_packet_count > 0) {
3070 lost_percent = 100.0 * (sp->cnt_error - sp->omitted_cnt_error) / (sender_packet_count - sp->omitted_packet_count);
3071 }
3072 else {
3073 lost_percent = 0.0;
3074 }
3075 if (test->json_output) {
3076 /*
3077 * For hysterical raisins, we only emit one JSON
3078 * object for the UDP summary, and it contains
3079 * information for both the sender and receiver
3080 * side.
3081 *
3082 * The JSON format as currently defined only includes one
3083 * value for the number of packets. We usually want that
3084 * to be the sender's value (how many packets were sent
3085 * by the sender). However this value might not be
3086 * available on the receiver in certain circumstances
3087 * specifically on the server side for a normal test or
3088 * the client side for a reverse-mode test. If this
3089 * is the case, then use the receiver's count of packets
3090 * instead.
3091 */
3092 int packet_count = sender_packet_count ? sender_packet_count : receiver_packet_count;
3093 cJSON_AddItemToObject(json_summary_stream, "udp", iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f jitter_ms: %f lost_packets: %d packets: %d lost_percent: %f out_of_order: %d sender: %b", (int64_t) sp->socket, (double) start_time, (double) sender_time, (double) sender_time, (int64_t) bytes_sent, bandwidth * 8, (double) sp->jitter * 1000.0, (int64_t) (sp->cnt_error - sp->omitted_cnt_error), (int64_t) (packet_count - sp->omitted_packet_count), (double) lost_percent, (int64_t) (sp->outoforder_packets - sp->omitted_outoforder_packets), stream_must_be_sender));
3094 }
3095 else {
3096 /*
3097 * Due to ordering of messages on the control channel,
3098 * the server cannot report on client-side summary
3099 * statistics. If we're the server, omit one set of
3100 * summary statistics to avoid giving meaningless
3101 * results.
3102 */
3103 if (test->role == 's' && !sp->sender) {
3104 if (test->verbose)
3105 iperf_printf(test, report_sender_not_available_format, sp->socket);
3106 }
3107 else {
3108 iperf_printf(test, report_bw_udp_format, sp->socket, mbuf, start_time, sender_time, ubuf, nbuf, 0.0, 0, (sender_packet_count - sp->omitted_packet_count), (double) 0, report_sender);
3109 }
3110 if ((sp->outoforder_packets - sp->omitted_outoforder_packets) > 0)
3111 iperf_printf(test, report_sum_outoforder, mbuf, start_time, sender_time, (sp->outoforder_packets - sp->omitted_outoforder_packets));
3112 }
3113 }
3114
3115 if (sp->diskfile_fd >= 0) {
3116 if (fstat(sp->diskfile_fd, &sb) == 0) {
3117 /* In the odd case that it's a zero-sized file, say it was all transferred. */
3118 int percent_sent = 100, percent_received = 100;
3119 if (sb.st_size > 0) {
3120 percent_sent = (int) ( ( (double) bytes_sent / (double) sb.st_size ) * 100.0 );
3121 percent_received = (int) ( ( (double) bytes_received / (double) sb.st_size ) * 100.0 );
3122 }
3123 unit_snprintf(sbuf, UNIT_LEN, (double) sb.st_size, 'A');
3124 if (test->json_output)
3125 cJSON_AddItemToObject(json_summary_stream, "diskfile", iperf_json_printf("sent: %d received: %d size: %d percent_sent: %d percent_received: %d filename: %s", (int64_t) bytes_sent, (int64_t) bytes_received, (int64_t) sb.st_size, (int64_t) percent_sent, (int64_t) percent_received, test->diskfile_name));
3126 else
3127 if (stream_must_be_sender) {
3128 iperf_printf(test, report_diskfile, ubuf, sbuf, percent_sent, test->diskfile_name);
3129 }
3130 else {
3131 unit_snprintf(ubuf, UNIT_LEN, (double) bytes_received, 'A');
3132 iperf_printf(test, report_diskfile, ubuf, sbuf, percent_received, test->diskfile_name);
3133 }
3134 }
3135 }
3136
3137 unit_snprintf(ubuf, UNIT_LEN, (double) bytes_received, 'A');
3138 if (receiver_time > 0) {
3139 bandwidth = (double) bytes_received / (double) receiver_time;
3140 }
3141 else {
3142 bandwidth = 0.0;
3143 }
3144 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
3145 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
3146 /* Receiver summary, TCP and SCTP */
3147 if (test->json_output)
3148 cJSON_AddItemToObject(json_summary_stream, "receiver", iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f sender: %b", (int64_t) sp->socket, (double) start_time, (double) receiver_time, (double) end_time, (int64_t) bytes_received, bandwidth * 8, stream_must_be_sender));
3149 else
3150 if (test->role == 's' && sp->sender) {
3151 if (test->verbose)
3152 iperf_printf(test, report_receiver_not_available_format, sp->socket);
3153 }
3154 else {
3155 iperf_printf(test, report_bw_format, sp->socket, mbuf, start_time, receiver_time, ubuf, nbuf, report_receiver);
3156 }
3157 }
3158 else {
3159 /*
3160 * Receiver summary, UDP. Note that JSON was emitted with
3161 * the sender summary, so we only deal with human-readable
3162 * data here.
3163 */
3164 if (! test->json_output) {
3165 if (receiver_packet_count - sp->omitted_packet_count > 0) {
3166 lost_percent = 100.0 * (sp->cnt_error - sp->omitted_cnt_error) / (receiver_packet_count - sp->omitted_packet_count);
3167 }
3168 else {
3169 lost_percent = 0.0;
3170 }
3171
3172 if (test->role == 's' && sp->sender) {
3173 if (test->verbose)
3174 iperf_printf(test, report_receiver_not_available_format, sp->socket);
3175 }
3176 else {
3177 iperf_printf(test, report_bw_udp_format, sp->socket, mbuf, start_time, receiver_time, ubuf, nbuf, sp->jitter * 1000.0, (sp->cnt_error - sp->omitted_cnt_error), (receiver_packet_count - sp->omitted_packet_count), lost_percent, report_receiver);
3178 }
3179 }
3180 }
3181 }
3182 }
3183 }
3184
3185 if (test->num_streams > 1 || test->json_output) {
3186 unit_snprintf(ubuf, UNIT_LEN, (double) total_sent, 'A');
3187 /* If no tests were run, arbitrarily set bandwidth to 0. */
3188 if (sender_time > 0.0) {
3189 bandwidth = (double) total_sent / (double) sender_time;
3190 }
3191 else {
3192 bandwidth = 0.0;
3193 }
3194 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
3195 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
3196 if (test->sender_has_retransmits) {
3197 /* Summary sum, TCP with retransmits. */
3198 if (test->json_output)
3199 cJSON_AddItemToObject(test->json_end, "sum_sent", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f retransmits: %d sender: %b", (double) start_time, (double) sender_time, (double) sender_time, (int64_t) total_sent, bandwidth * 8, (int64_t) total_retransmits, stream_must_be_sender));
3200 else
3201 if (test->role == 's' && !stream_must_be_sender) {
3202 if (test->verbose)
3203 iperf_printf(test, report_sender_not_available_summary_format, "SUM");
3204 }
3205 else {
3206 iperf_printf(test, report_sum_bw_retrans_format, mbuf, start_time, sender_time, ubuf, nbuf, total_retransmits, report_sender);
3207 }
3208 } else {
3209 /* Summary sum, TCP without retransmits. */
3210 if (test->json_output)
3211 cJSON_AddItemToObject(test->json_end, "sum_sent", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f sender: %b", (double) start_time, (double) sender_time, (double) sender_time, (int64_t) total_sent, bandwidth * 8, stream_must_be_sender));
3212 else
3213 if (test->role == 's' && !stream_must_be_sender) {
3214 if (test->verbose)
3215 iperf_printf(test, report_sender_not_available_summary_format, "SUM");
3216 }
3217 else {
3218 iperf_printf(test, report_sum_bw_format, mbuf, start_time, sender_time, ubuf, nbuf, report_sender);
3219 }
3220 }
3221 unit_snprintf(ubuf, UNIT_LEN, (double) total_received, 'A');
3222 /* If no tests were run, set received bandwidth to 0 */
3223 if (receiver_time > 0.0) {
3224 bandwidth = (double) total_received / (double) receiver_time;
3225 }
3226 else {
3227 bandwidth = 0.0;
3228 }
3229 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
3230 if (test->json_output)
3231 cJSON_AddItemToObject(test->json_end, "sum_received", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f sender: %b", (double) start_time, (double) receiver_time, (double) receiver_time, (int64_t) total_received, bandwidth * 8, stream_must_be_sender));
3232 else
3233 if (test->role == 's' && stream_must_be_sender) {
3234 if (test->verbose)
3235 iperf_printf(test, report_receiver_not_available_summary_format, "SUM");
3236 }
3237 else {
3238 iperf_printf(test, report_sum_bw_format, mbuf, start_time, receiver_time, ubuf, nbuf, report_receiver);
3239 }
3240 } else {
3241 /* Summary sum, UDP. */
3242 avg_jitter /= test->num_streams;
3243 /* If no packets were sent, arbitrarily set loss percentage to 0. */
3244 if (total_packets > 0) {
3245 lost_percent = 100.0 * lost_packets / total_packets;
3246 }
3247 else {
3248 lost_percent = 0.0;
3249 }
3250 if (test->json_output)
3251 cJSON_AddItemToObject(test->json_end, "sum", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f jitter_ms: %f lost_packets: %d packets: %d lost_percent: %f sender: %b", (double) start_time, (double) receiver_time, (double) receiver_time, (int64_t) total_sent, bandwidth * 8, (double) avg_jitter * 1000.0, (int64_t) lost_packets, (int64_t) total_packets, (double) lost_percent, stream_must_be_sender));
3252 else {
3253 /*
3254 * On the client we have both sender and receiver overall summary
3255 * stats. On the server we have only the side that was on the
3256 * server. Output whatever we have.
3257 */
3258 if (! (test->role == 's' && !stream_must_be_sender) ) {
3259 unit_snprintf(ubuf, UNIT_LEN, (double) total_sent, 'A');
3260 iperf_printf(test, report_sum_bw_udp_format, mbuf, start_time, sender_time, ubuf, nbuf, 0.0, 0, sender_total_packets, 0.0, "sender");
3261 }
3262 if (! (test->role == 's' && stream_must_be_sender) ) {
3263
3264 unit_snprintf(ubuf, UNIT_LEN, (double) total_received, 'A');
3265 /* Compute received bandwidth. */
3266 if (end_time > 0.0) {
3267 bandwidth = (double) total_received / (double) receiver_time;
3268 }
3269 else {
3270 bandwidth = 0.0;
3271 }
3272 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
3273 iperf_printf(test, report_sum_bw_udp_format, mbuf, start_time, receiver_time, ubuf, nbuf, avg_jitter * 1000.0, lost_packets, receiver_total_packets, lost_percent, "receiver");
3274 }
3275 }
3276 }
3277 }
3278
3279 if (test->json_output && current_mode == upper_mode) {
3280 cJSON_AddItemToObject(test->json_end, "cpu_utilization_percent", iperf_json_printf("host_total: %f host_user: %f host_system: %f remote_total: %f remote_user: %f remote_system: %f", (double) test->cpu_util[0], (double) test->cpu_util[1], (double) test->cpu_util[2], (double) test->remote_cpu_util[0], (double) test->remote_cpu_util[1], (double) test->remote_cpu_util[2]));
3281 if (test->protocol->id == Ptcp) {
3282 char *snd_congestion = NULL, *rcv_congestion = NULL;
3283 if (stream_must_be_sender) {
3284 snd_congestion = test->congestion_used;
3285 rcv_congestion = test->remote_congestion_used;
3286 }
3287 else {
3288 snd_congestion = test->remote_congestion_used;
3289 rcv_congestion = test->congestion_used;
3290 }
3291 if (snd_congestion) {
3292 cJSON_AddStringToObject(test->json_end, "sender_tcp_congestion", snd_congestion);
3293 }
3294 if (rcv_congestion) {
3295 cJSON_AddStringToObject(test->json_end, "receiver_tcp_congestion", rcv_congestion);
3296 }
3297 }
3298 }
3299 else {
3300 if (test->verbose) {
3301 if (stream_must_be_sender) {
3302 if (test->bidirectional) {
3303 iperf_printf(test, report_cpu, report_local, stream_must_be_sender?report_sender:report_receiver, test->cpu_util[0], test->cpu_util[1], test->cpu_util[2], report_remote, stream_must_be_sender?report_receiver:report_sender, test->remote_cpu_util[0], test->remote_cpu_util[1], test->remote_cpu_util[2]);
3304 iperf_printf(test, report_cpu, report_local, !stream_must_be_sender?report_sender:report_receiver, test->cpu_util[0], test->cpu_util[1], test->cpu_util[2], report_remote, !stream_must_be_sender?report_receiver:report_sender, test->remote_cpu_util[0], test->remote_cpu_util[1], test->remote_cpu_util[2]);
3305 } else
3306 iperf_printf(test, report_cpu, report_local, stream_must_be_sender?report_sender:report_receiver, test->cpu_util[0], test->cpu_util[1], test->cpu_util[2], report_remote, stream_must_be_sender?report_receiver:report_sender, test->remote_cpu_util[0], test->remote_cpu_util[1], test->remote_cpu_util[2]);
3307 }
3308 if (test->protocol->id == Ptcp) {
3309 char *snd_congestion = NULL, *rcv_congestion = NULL;
3310 if (stream_must_be_sender) {
3311 snd_congestion = test->congestion_used;
3312 rcv_congestion = test->remote_congestion_used;
3313 }
3314 else {
3315 snd_congestion = test->remote_congestion_used;
3316 rcv_congestion = test->congestion_used;
3317 }
3318 if (snd_congestion) {
3319 iperf_printf(test, "snd_tcp_congestion %s\n", snd_congestion);
3320 }
3321 if (rcv_congestion) {
3322 iperf_printf(test, "rcv_tcp_congestion %s\n", rcv_congestion);
3323 }
3324 }
3325 }
3326
3327 /* Print server output if we're on the client and it was requested/provided */
3328 if (test->role == 'c' && iperf_get_test_get_server_output(test)) {
3329 if (test->json_server_output) {
3330 iperf_printf(test, "\nServer JSON output:\n%s\n", cJSON_Print(test->json_server_output));
3331 cJSON_Delete(test->json_server_output);
3332 test->json_server_output = NULL;
3333 }
3334 if (test->server_output_text) {
3335 iperf_printf(test, "\nServer output:\n%s\n", test->server_output_text);
3336 test->server_output_text = NULL;
3337 }
3338 }
3339 }
3340 }
3341
3342 /* Set real sender_has_retransmits for current side */
3343 if (test->mode == BIDIRECTIONAL)
3344 test->sender_has_retransmits = tmp_sender_has_retransmits;
3345 }
3346
3347 /**************************************************************************/
3348
3349 /**
3350 * Main report-printing callback.
3351 * Prints results either during a test (interval report only) or
3352 * after the entire test has been run (last interval report plus
3353 * overall summary).
3354 */
3355 void
iperf_reporter_callback(struct iperf_test * test)3356 iperf_reporter_callback(struct iperf_test *test)
3357 {
3358 switch (test->state) {
3359 case TEST_RUNNING:
3360 case STREAM_RUNNING:
3361 /* print interval results for each stream */
3362 iperf_print_intermediate(test);
3363 break;
3364 case TEST_END:
3365 case DISPLAY_RESULTS:
3366 iperf_print_intermediate(test);
3367 iperf_print_results(test);
3368 break;
3369 }
3370
3371 }
3372
3373 /**
3374 * Print the interval results for one stream.
3375 * This function needs to know about the overall test so it can determine the
3376 * context for printing headers, separators, etc.
3377 */
3378 static void
print_interval_results(struct iperf_test * test,struct iperf_stream * sp,cJSON * json_interval_streams)3379 print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *json_interval_streams)
3380 {
3381 char ubuf[UNIT_LEN];
3382 char nbuf[UNIT_LEN];
3383 char cbuf[UNIT_LEN];
3384 char mbuf[UNIT_LEN];
3385 char zbuf[] = " ";
3386 double st = 0., et = 0.;
3387 struct iperf_time temp_time;
3388 struct iperf_interval_results *irp = NULL;
3389 double bandwidth, lost_percent;
3390
3391 if (test->mode == BIDIRECTIONAL) {
3392 sprintf(mbuf, "[%s-%s]", sp->sender?"TX":"RX", test->role == 'c'?"C":"S");
3393 } else {
3394 mbuf[0] = '\0';
3395 zbuf[0] = '\0';
3396 }
3397
3398 irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); /* get last entry in linked list */
3399 if (irp == NULL) {
3400 iperf_err(test, "print_interval_results error: interval_results is NULL");
3401 return;
3402 }
3403 if (!test->json_output) {
3404 /* First stream? */
3405 if (sp == SLIST_FIRST(&test->streams)) {
3406 /* It it's the first interval, print the header;
3407 ** else if there's more than one stream, print the separator;
3408 ** else nothing.
3409 */
3410 if (iperf_time_compare(&sp->result->start_time, &irp->interval_start_time) == 0) {
3411 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
3412 if (test->sender_has_retransmits == 1) {
3413 if (test->bidirectional)
3414 iperf_printf(test, "%s", report_bw_retrans_cwnd_header_bidir);
3415 else
3416 iperf_printf(test, "%s", report_bw_retrans_cwnd_header);
3417 }
3418 else {
3419 if (test->bidirectional)
3420 iperf_printf(test, "%s", report_bw_header_bidir);
3421 else
3422 iperf_printf(test, "%s", report_bw_header);
3423 }
3424 } else {
3425 if (test->mode == SENDER) {
3426 iperf_printf(test, "%s", report_bw_udp_sender_header);
3427 } else if (test->mode == RECEIVER){
3428 iperf_printf(test, "%s", report_bw_udp_header);
3429 } else {
3430 /* BIDIRECTIONAL */
3431 iperf_printf(test, "%s", report_bw_udp_header_bidir);
3432 }
3433 }
3434 } else if (test->num_streams > 1)
3435 iperf_printf(test, "%s", report_bw_separator);
3436 }
3437 }
3438
3439 unit_snprintf(ubuf, UNIT_LEN, (double) (irp->bytes_transferred), 'A');
3440 if (irp->interval_duration > 0.0) {
3441 bandwidth = (double) irp->bytes_transferred / (double) irp->interval_duration;
3442 }
3443 else {
3444 bandwidth = 0.0;
3445 }
3446 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
3447
3448 iperf_time_diff(&sp->result->start_time, &irp->interval_start_time, &temp_time);
3449 st = iperf_time_in_secs(&temp_time);
3450 iperf_time_diff(&sp->result->start_time, &irp->interval_end_time, &temp_time);
3451 et = iperf_time_in_secs(&temp_time);
3452
3453 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
3454 if (test->sender_has_retransmits == 1 && sp->sender) {
3455 /* Interval, TCP with retransmits. */
3456 if (test->json_output)
3457 cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f retransmits: %d snd_cwnd: %d rtt: %d rttvar: %d pmtu: %d omitted: %b sender: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, (int64_t) irp->interval_retrans, (int64_t) irp->snd_cwnd, (int64_t) irp->rtt, (int64_t) irp->rttvar, (int64_t) irp->pmtu, irp->omitted, sp->sender));
3458 else {
3459 unit_snprintf(cbuf, UNIT_LEN, irp->snd_cwnd, 'A');
3460 iperf_printf(test, report_bw_retrans_cwnd_format, sp->socket, mbuf, st, et, ubuf, nbuf, irp->interval_retrans, cbuf, irp->omitted?report_omitted:"");
3461 }
3462 } else {
3463 /* Interval, TCP without retransmits. */
3464 if (test->json_output)
3465 cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f omitted: %b sender: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, irp->omitted, sp->sender));
3466 else
3467 iperf_printf(test, report_bw_format, sp->socket, mbuf, st, et, ubuf, nbuf, irp->omitted?report_omitted:"");
3468 }
3469 } else {
3470 /* Interval, UDP. */
3471 if (sp->sender) {
3472 if (test->json_output)
3473 cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f packets: %d omitted: %b sender: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, (int64_t) irp->interval_packet_count, irp->omitted, sp->sender));
3474 else
3475 iperf_printf(test, report_bw_udp_sender_format, sp->socket, mbuf, st, et, ubuf, nbuf, zbuf, irp->interval_packet_count, irp->omitted?report_omitted:"");
3476 } else {
3477 if (irp->interval_packet_count > 0) {
3478 lost_percent = 100.0 * irp->interval_cnt_error / irp->interval_packet_count;
3479 }
3480 else {
3481 lost_percent = 0.0;
3482 }
3483 if (test->json_output)
3484 cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f jitter_ms: %f lost_packets: %d packets: %d lost_percent: %f omitted: %b sender: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, (double) irp->jitter * 1000.0, (int64_t) irp->interval_cnt_error, (int64_t) irp->interval_packet_count, (double) lost_percent, irp->omitted, sp->sender));
3485 else
3486 iperf_printf(test, report_bw_udp_format, sp->socket, mbuf, st, et, ubuf, nbuf, irp->jitter * 1000.0, irp->interval_cnt_error, irp->interval_packet_count, lost_percent, irp->omitted?report_omitted:"");
3487 }
3488 }
3489
3490 if (test->logfile || test->forceflush)
3491 iflush(test);
3492 }
3493
3494 /**************************************************************************/
3495 void
iperf_free_stream(struct iperf_stream * sp)3496 iperf_free_stream(struct iperf_stream *sp)
3497 {
3498 struct iperf_interval_results *irp, *nirp;
3499
3500 /* XXX: need to free interval list too! */
3501 munmap(sp->buffer, sp->test->settings->blksize);
3502 close(sp->buffer_fd);
3503 if (sp->diskfile_fd >= 0)
3504 close(sp->diskfile_fd);
3505 for (irp = TAILQ_FIRST(&sp->result->interval_results); irp != NULL; irp = nirp) {
3506 nirp = TAILQ_NEXT(irp, irlistentries);
3507 free(irp);
3508 }
3509 free(sp->result);
3510 if (sp->send_timer != NULL)
3511 tmr_cancel(sp->send_timer);
3512 free(sp);
3513 }
3514
3515 /**************************************************************************/
3516 struct iperf_stream *
iperf_new_stream(struct iperf_test * test,int s,int sender)3517 iperf_new_stream(struct iperf_test *test, int s, int sender)
3518 {
3519 struct iperf_stream *sp;
3520 int ret = 0;
3521
3522 char template[1024];
3523 if (test->tmp_template) {
3524 snprintf(template, sizeof(template) / sizeof(char), "%s", test->tmp_template);
3525 } else {
3526 //find the system temporary dir *unix, windows, cygwin support
3527 char* tempdir = getenv("TMPDIR");
3528 if (tempdir == 0){
3529 tempdir = getenv("TEMP");
3530 }
3531 if (tempdir == 0){
3532 tempdir = getenv("TMP");
3533 }
3534 if (tempdir == 0){
3535 tempdir = "/tmp";
3536 }
3537 snprintf(template, sizeof(template) / sizeof(char), "%s/iperf3.XXXXXX", tempdir);
3538 }
3539
3540 sp = (struct iperf_stream *) malloc(sizeof(struct iperf_stream));
3541 if (!sp) {
3542 i_errno = IECREATESTREAM;
3543 return NULL;
3544 }
3545
3546 memset(sp, 0, sizeof(struct iperf_stream));
3547
3548 sp->sender = sender;
3549 sp->test = test;
3550 sp->settings = test->settings;
3551 sp->result = (struct iperf_stream_result *) malloc(sizeof(struct iperf_stream_result));
3552 if (!sp->result) {
3553 free(sp);
3554 i_errno = IECREATESTREAM;
3555 return NULL;
3556 }
3557
3558 memset(sp->result, 0, sizeof(struct iperf_stream_result));
3559 TAILQ_INIT(&sp->result->interval_results);
3560
3561 /* Create and randomize the buffer */
3562 sp->buffer_fd = mkstemp(template);
3563 if (sp->buffer_fd == -1) {
3564 i_errno = IECREATESTREAM;
3565 free(sp->result);
3566 free(sp);
3567 return NULL;
3568 }
3569 if (unlink(template) < 0) {
3570 i_errno = IECREATESTREAM;
3571 free(sp->result);
3572 free(sp);
3573 return NULL;
3574 }
3575 if (ftruncate(sp->buffer_fd, test->settings->blksize) < 0) {
3576 i_errno = IECREATESTREAM;
3577 free(sp->result);
3578 free(sp);
3579 return NULL;
3580 }
3581 sp->buffer = (char *) mmap(NULL, test->settings->blksize, PROT_READ|PROT_WRITE, MAP_PRIVATE, sp->buffer_fd, 0);
3582 if (sp->buffer == MAP_FAILED) {
3583 i_errno = IECREATESTREAM;
3584 free(sp->result);
3585 free(sp);
3586 return NULL;
3587 }
3588
3589 /* Set socket */
3590 sp->socket = s;
3591
3592 sp->snd = test->protocol->send;
3593 sp->rcv = test->protocol->recv;
3594
3595 if (test->diskfile_name != (char*) 0) {
3596 sp->diskfile_fd = open(test->diskfile_name, sender ? O_RDONLY : (O_WRONLY|O_CREAT|O_TRUNC), S_IRUSR|S_IWUSR);
3597 if (sp->diskfile_fd == -1) {
3598 i_errno = IEFILE;
3599 munmap(sp->buffer, sp->test->settings->blksize);
3600 free(sp->result);
3601 free(sp);
3602 return NULL;
3603 }
3604 sp->snd2 = sp->snd;
3605 sp->snd = diskfile_send;
3606 sp->rcv2 = sp->rcv;
3607 sp->rcv = diskfile_recv;
3608 } else
3609 sp->diskfile_fd = -1;
3610
3611 /* Initialize stream */
3612 if (test->repeating_payload)
3613 fill_with_repeating_pattern(sp->buffer, test->settings->blksize);
3614 else
3615 ret = readentropy(sp->buffer, test->settings->blksize);
3616
3617 if ((ret < 0) || (iperf_init_stream(sp, test) < 0)) {
3618 close(sp->buffer_fd);
3619 munmap(sp->buffer, sp->test->settings->blksize);
3620 free(sp->result);
3621 free(sp);
3622 return NULL;
3623 }
3624 iperf_add_stream(test, sp);
3625
3626 return sp;
3627 }
3628
3629 /**************************************************************************/
3630 int
iperf_init_stream(struct iperf_stream * sp,struct iperf_test * test)3631 iperf_init_stream(struct iperf_stream *sp, struct iperf_test *test)
3632 {
3633 socklen_t len;
3634 int opt;
3635
3636 len = sizeof(struct sockaddr_storage);
3637 if (getsockname(sp->socket, (struct sockaddr *) &sp->local_addr, &len) < 0) {
3638 i_errno = IEINITSTREAM;
3639 return -1;
3640 }
3641 len = sizeof(struct sockaddr_storage);
3642 if (getpeername(sp->socket, (struct sockaddr *) &sp->remote_addr, &len) < 0) {
3643 i_errno = IEINITSTREAM;
3644 return -1;
3645 }
3646
3647 /* Set IP TOS */
3648 if ((opt = test->settings->tos)) {
3649 if (getsockdomain(sp->socket) == AF_INET6) {
3650 #ifdef IPV6_TCLASS
3651 if (setsockopt(sp->socket, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt)) < 0) {
3652 i_errno = IESETCOS;
3653 return -1;
3654 }
3655 #else
3656 i_errno = IESETCOS;
3657 return -1;
3658 #endif
3659 } else {
3660 if (setsockopt(sp->socket, IPPROTO_IP, IP_TOS, &opt, sizeof(opt)) < 0) {
3661 i_errno = IESETTOS;
3662 return -1;
3663 }
3664 }
3665 }
3666
3667 return 0;
3668 }
3669
3670 /**************************************************************************/
3671 void
iperf_add_stream(struct iperf_test * test,struct iperf_stream * sp)3672 iperf_add_stream(struct iperf_test *test, struct iperf_stream *sp)
3673 {
3674 int i;
3675 struct iperf_stream *n, *prev;
3676
3677 if (SLIST_EMPTY(&test->streams)) {
3678 SLIST_INSERT_HEAD(&test->streams, sp, streams);
3679 sp->id = 1;
3680 } else {
3681 // for (n = test->streams, i = 2; n->next; n = n->next, ++i);
3682 i = 2;
3683 SLIST_FOREACH(n, &test->streams, streams) {
3684 prev = n;
3685 ++i;
3686 }
3687 SLIST_INSERT_AFTER(prev, sp, streams);
3688 sp->id = i;
3689 }
3690 }
3691
3692 /* This pair of routines gets inserted into the snd/rcv function pointers
3693 ** when there's a -F flag. They handle the file stuff and call the real
3694 ** snd/rcv functions, which have been saved in snd2/rcv2.
3695 **
3696 ** The advantage of doing it this way is that in the much more common
3697 ** case of no -F flag, there is zero extra overhead.
3698 */
3699
3700 static int
diskfile_send(struct iperf_stream * sp)3701 diskfile_send(struct iperf_stream *sp)
3702 {
3703 int r;
3704 static int rtot;
3705
3706 /* if needed, read enough data from the disk to fill up the buffer */
3707 if (sp->diskfile_left < sp->test->settings->blksize && !sp->test->done) {
3708 r = read(sp->diskfile_fd, sp->buffer, sp->test->settings->blksize -
3709 sp->diskfile_left);
3710 rtot += r;
3711 if (sp->test->debug) {
3712 printf("read %d bytes from file, %d total\n", r, rtot);
3713 if (r != sp->test->settings->blksize - sp->diskfile_left)
3714 printf("possible eof\n");
3715 }
3716 /* If there's no data left in the file or in the buffer, we're done */
3717 if (r == 0 && sp->diskfile_left == 0) {
3718 sp->test->done = 1;
3719 if (sp->test->debug)
3720 printf("done\n");
3721 }
3722 }
3723
3724 r = sp->snd2(sp);
3725 if (r < 0) {
3726 return r;
3727 }
3728 /*
3729 * Compute how much data is in the buffer but didn't get sent.
3730 * If there are bytes that got left behind, slide them to the
3731 * front of the buffer so they can hopefully go out on the next
3732 * pass.
3733 */
3734 sp->diskfile_left = sp->test->settings->blksize - r;
3735 if (sp->diskfile_left && sp->diskfile_left < sp->test->settings->blksize) {
3736 memcpy(sp->buffer,
3737 sp->buffer + (sp->test->settings->blksize - sp->diskfile_left),
3738 sp->diskfile_left);
3739 if (sp->test->debug)
3740 printf("Shifting %d bytes by %d\n", sp->diskfile_left, (sp->test->settings->blksize - sp->diskfile_left));
3741 }
3742 return r;
3743 }
3744
3745 static int
diskfile_recv(struct iperf_stream * sp)3746 diskfile_recv(struct iperf_stream *sp)
3747 {
3748 int r;
3749
3750 r = sp->rcv2(sp);
3751 if (r > 0) {
3752 (void) write(sp->diskfile_fd, sp->buffer, r);
3753 (void) fsync(sp->diskfile_fd);
3754 }
3755 return r;
3756 }
3757
3758
3759 void
iperf_catch_sigend(void (* handler)(int))3760 iperf_catch_sigend(void (*handler)(int))
3761 {
3762 signal(SIGINT, handler);
3763 signal(SIGTERM, handler);
3764 signal(SIGHUP, handler);
3765 }
3766
3767 /**
3768 * Called as a result of getting a signal.
3769 * Depending on the current state of the test (and the role of this
3770 * process) compute and report one more set of ending statistics
3771 * before cleaning up and exiting.
3772 */
3773 void
iperf_got_sigend(struct iperf_test * test)3774 iperf_got_sigend(struct iperf_test *test)
3775 {
3776 /*
3777 * If we're the client, or if we're a server and running a test,
3778 * then dump out the accumulated stats so far.
3779 */
3780 if (test->role == 'c' ||
3781 (test->role == 's' && test->state == TEST_RUNNING)) {
3782
3783 test->done = 1;
3784 cpu_util(test->cpu_util);
3785 test->stats_callback(test);
3786 test->state = DISPLAY_RESULTS; /* change local state only */
3787 if (test->on_test_finish)
3788 test->on_test_finish(test);
3789 test->reporter_callback(test);
3790 }
3791
3792 if (test->ctrl_sck >= 0) {
3793 test->state = (test->role == 'c') ? CLIENT_TERMINATE : SERVER_TERMINATE;
3794 (void) Nwrite(test->ctrl_sck, (char*) &test->state, sizeof(signed char), Ptcp);
3795 }
3796 i_errno = (test->role == 'c') ? IECLIENTTERM : IESERVERTERM;
3797 iperf_errexit(test, "interrupt - %s", iperf_strerror(i_errno));
3798 }
3799
3800 /* Try to write a PID file if requested, return -1 on an error. */
3801 int
iperf_create_pidfile(struct iperf_test * test)3802 iperf_create_pidfile(struct iperf_test *test)
3803 {
3804 if (test->pidfile) {
3805 int fd;
3806 char buf[8];
3807
3808 /* See if the file already exists and we can read it. */
3809 fd = open(test->pidfile, O_RDONLY, 0);
3810 if (fd >= 0) {
3811 if (read(fd, buf, sizeof(buf) - 1) >= 0) {
3812
3813 /* We read some bytes, see if they correspond to a valid PID */
3814 pid_t pid;
3815 pid = atoi(buf);
3816 if (pid > 0) {
3817
3818 /* See if the process exists. */
3819 if (kill(pid, 0) == 0) {
3820 /*
3821 * Make sure not to try to delete existing PID file by
3822 * scribbling over the pathname we'd use to refer to it.
3823 * Then exit with an error.
3824 */
3825 free(test->pidfile);
3826 test->pidfile = NULL;
3827 iperf_errexit(test, "Another instance of iperf3 appears to be running");
3828 }
3829 }
3830 }
3831 }
3832
3833 /*
3834 * File didn't exist, we couldn't read it, or it didn't correspond to
3835 * a running process. Try to create it.
3836 */
3837 fd = open(test->pidfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR|S_IWUSR);
3838 if (fd < 0) {
3839 return -1;
3840 }
3841 snprintf(buf, sizeof(buf), "%d", getpid()); /* no trailing newline */
3842 if (write(fd, buf, strlen(buf) + 1) < 0) {
3843 return -1;
3844 }
3845 if (close(fd) < 0) {
3846 return -1;
3847 };
3848 }
3849 return 0;
3850 }
3851
3852 /* Get rid of a PID file, return -1 on error. */
3853 int
iperf_delete_pidfile(struct iperf_test * test)3854 iperf_delete_pidfile(struct iperf_test *test)
3855 {
3856 if (test->pidfile) {
3857 if (unlink(test->pidfile) < 0) {
3858 return -1;
3859 }
3860 }
3861 return 0;
3862 }
3863
3864 int
iperf_json_start(struct iperf_test * test)3865 iperf_json_start(struct iperf_test *test)
3866 {
3867 test->json_top = cJSON_CreateObject();
3868 if (test->json_top == NULL)
3869 return -1;
3870 test->json_start = cJSON_CreateObject();
3871 if (test->json_start == NULL)
3872 return -1;
3873 cJSON_AddItemToObject(test->json_top, "start", test->json_start);
3874 test->json_connected = cJSON_CreateArray();
3875 if (test->json_connected == NULL)
3876 return -1;
3877 cJSON_AddItemToObject(test->json_start, "connected", test->json_connected);
3878 test->json_intervals = cJSON_CreateArray();
3879 if (test->json_intervals == NULL)
3880 return -1;
3881 cJSON_AddItemToObject(test->json_top, "intervals", test->json_intervals);
3882 test->json_end = cJSON_CreateObject();
3883 if (test->json_end == NULL)
3884 return -1;
3885 cJSON_AddItemToObject(test->json_top, "end", test->json_end);
3886 return 0;
3887 }
3888
3889 int
iperf_json_finish(struct iperf_test * test)3890 iperf_json_finish(struct iperf_test *test)
3891 {
3892 if (test->title)
3893 cJSON_AddStringToObject(test->json_top, "title", test->title);
3894 if (test->extra_data)
3895 cJSON_AddStringToObject(test->json_top, "extra_data", test->extra_data);
3896 /* Include server output */
3897 if (test->json_server_output) {
3898 cJSON_AddItemToObject(test->json_top, "server_output_json", test->json_server_output);
3899 }
3900 if (test->server_output_text) {
3901 cJSON_AddStringToObject(test->json_top, "server_output_text", test->server_output_text);
3902 }
3903 test->json_output_string = cJSON_Print(test->json_top);
3904 if (test->json_output_string == NULL)
3905 return -1;
3906 fprintf(test->outfile, "%s\n", test->json_output_string);
3907 iflush(test);
3908 cJSON_Delete(test->json_top);
3909 test->json_top = test->json_start = test->json_connected = test->json_intervals = test->json_server_output = test->json_end = NULL;
3910 return 0;
3911 }
3912
3913
3914 /* CPU affinity stuff - Linux, FreeBSD, and Windows only. */
3915
3916 int
iperf_setaffinity(struct iperf_test * test,int affinity)3917 iperf_setaffinity(struct iperf_test *test, int affinity)
3918 {
3919 #if defined(HAVE_SCHED_SETAFFINITY)
3920 cpu_set_t cpu_set;
3921
3922 CPU_ZERO(&cpu_set);
3923 CPU_SET(affinity, &cpu_set);
3924 if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) != 0) {
3925 i_errno = IEAFFINITY;
3926 return -1;
3927 }
3928 return 0;
3929 #elif defined(HAVE_CPUSET_SETAFFINITY)
3930 cpuset_t cpumask;
3931
3932 if(cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1,
3933 sizeof(cpuset_t), &test->cpumask) != 0) {
3934 i_errno = IEAFFINITY;
3935 return -1;
3936 }
3937
3938 CPU_ZERO(&cpumask);
3939 CPU_SET(affinity, &cpumask);
3940
3941 if(cpuset_setaffinity(CPU_LEVEL_WHICH,CPU_WHICH_PID, -1,
3942 sizeof(cpuset_t), &cpumask) != 0) {
3943 i_errno = IEAFFINITY;
3944 return -1;
3945 }
3946 return 0;
3947 #elif defined(HAVE_SETPROCESSAFFINITYMASK)
3948 HANDLE process = GetCurrentProcess();
3949 DWORD_PTR processAffinityMask = 1 << affinity;
3950
3951 if (SetProcessAffinityMask(process, processAffinityMask) == 0) {
3952 i_errno = IEAFFINITY;
3953 return -1;
3954 }
3955 return 0;
3956 #else /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY nor HAVE_SETPROCESSAFFINITYMASK */
3957 i_errno = IEAFFINITY;
3958 return -1;
3959 #endif /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY nor HAVE_SETPROCESSAFFINITYMASK */
3960 }
3961
3962 int
iperf_clearaffinity(struct iperf_test * test)3963 iperf_clearaffinity(struct iperf_test *test)
3964 {
3965 #if defined(HAVE_SCHED_SETAFFINITY)
3966 cpu_set_t cpu_set;
3967 int i;
3968
3969 CPU_ZERO(&cpu_set);
3970 for (i = 0; i < CPU_SETSIZE; ++i)
3971 CPU_SET(i, &cpu_set);
3972 if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) != 0) {
3973 i_errno = IEAFFINITY;
3974 return -1;
3975 }
3976 return 0;
3977 #elif defined(HAVE_CPUSET_SETAFFINITY)
3978 if(cpuset_setaffinity(CPU_LEVEL_WHICH,CPU_WHICH_PID, -1,
3979 sizeof(cpuset_t), &test->cpumask) != 0) {
3980 i_errno = IEAFFINITY;
3981 return -1;
3982 }
3983 return 0;
3984 #elif defined(HAVE_SETPROCESSAFFINITYMASK)
3985 HANDLE process = GetCurrentProcess();
3986 DWORD_PTR processAffinityMask;
3987 DWORD_PTR lpSystemAffinityMask;
3988
3989 if (GetProcessAffinityMask(process, &processAffinityMask, &lpSystemAffinityMask) == 0
3990 || SetProcessAffinityMask(process, lpSystemAffinityMask) == 0) {
3991 i_errno = IEAFFINITY;
3992 return -1;
3993 }
3994 return 0;
3995 #else /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY nor HAVE_SETPROCESSAFFINITYMASK */
3996 i_errno = IEAFFINITY;
3997 return -1;
3998 #endif /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY nor HAVE_SETPROCESSAFFINITYMASK */
3999 }
4000
4001 int
iperf_printf(struct iperf_test * test,const char * format,...)4002 iperf_printf(struct iperf_test *test, const char* format, ...)
4003 {
4004 va_list argp;
4005 int r = -1;
4006
4007 /*
4008 * There are roughly two use cases here. If we're the client,
4009 * want to print stuff directly to the output stream.
4010 * If we're the sender we might need to buffer up output to send
4011 * to the client.
4012 *
4013 * This doesn't make a whole lot of difference except there are
4014 * some chunks of output on the client (on particular the whole
4015 * of the server output with --get-server-output) that could
4016 * easily exceed the size of the line buffer, but which don't need
4017 * to be buffered up anyway.
4018 */
4019 if (test->role == 'c') {
4020 if (test->title)
4021 fprintf(test->outfile, "%s: ", test->title);
4022 va_start(argp, format);
4023 r = vfprintf(test->outfile, format, argp);
4024 va_end(argp);
4025 }
4026 else if (test->role == 's') {
4027 char linebuffer[1024];
4028 va_start(argp, format);
4029 r = vsnprintf(linebuffer, sizeof(linebuffer), format, argp);
4030 va_end(argp);
4031 fprintf(test->outfile, "%s", linebuffer);
4032
4033 if (test->role == 's' && iperf_get_test_get_server_output(test)) {
4034 struct iperf_textline *l = (struct iperf_textline *) malloc(sizeof(struct iperf_textline));
4035 l->line = strdup(linebuffer);
4036 TAILQ_INSERT_TAIL(&(test->server_output_list), l, textlineentries);
4037 }
4038 }
4039 return r;
4040 }
4041
4042 int
iflush(struct iperf_test * test)4043 iflush(struct iperf_test *test)
4044 {
4045 return fflush(test->outfile);
4046 }
4047