Annotation of embedaddon/iperf/src/iperf_api.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * iperf, Copyright (c) 2014, 2015, 2016, 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: #define _GNU_SOURCE
                     28: #define __USE_GNU
                     29: 
                     30: #include "iperf_config.h"
                     31: 
                     32: #include <stdio.h>
                     33: #include <stdlib.h>
                     34: #include <string.h>
                     35: #include <getopt.h>
                     36: #include <errno.h>
                     37: #include <signal.h>
                     38: #include <unistd.h>
                     39: #include <assert.h>
                     40: #include <fcntl.h>
                     41: #include <sys/socket.h>
                     42: #include <sys/types.h>
                     43: #include <netinet/in.h>
                     44: #include <arpa/inet.h>
                     45: #include <netdb.h>
                     46: #include <pthread.h>
                     47: #ifdef HAVE_STDINT_H
                     48: #include <stdint.h>
                     49: #endif
                     50: #include <netinet/tcp.h>
                     51: #include <sys/time.h>
                     52: #include <sys/resource.h>
                     53: #include <sys/mman.h>
                     54: #include <sys/stat.h>
                     55: #include <sched.h>
                     56: #include <setjmp.h>
                     57: #include <stdarg.h>
                     58: 
                     59: #if defined(HAVE_CPUSET_SETAFFINITY)
                     60: #include <sys/param.h>
                     61: #include <sys/cpuset.h>
                     62: #endif /* HAVE_CPUSET_SETAFFINITY */
                     63: 
                     64: #include "net.h"
                     65: #include "iperf.h"
                     66: #include "iperf_api.h"
                     67: #include "iperf_udp.h"
                     68: #include "iperf_tcp.h"
                     69: #if defined(HAVE_SCTP)
                     70: #include "iperf_sctp.h"
                     71: #endif /* HAVE_SCTP */
                     72: #include "timer.h"
                     73: 
                     74: #include "cjson.h"
                     75: #include "units.h"
                     76: #include "tcp_window_size.h"
                     77: #include "iperf_util.h"
                     78: #include "iperf_locale.h"
                     79: #include "version.h"
                     80: 
                     81: /* Forwards. */
                     82: static int send_parameters(struct iperf_test *test);
                     83: static int get_parameters(struct iperf_test *test);
                     84: static int send_results(struct iperf_test *test);
                     85: static int get_results(struct iperf_test *test);
                     86: static int diskfile_send(struct iperf_stream *sp);
                     87: static int diskfile_recv(struct iperf_stream *sp);
                     88: static int JSON_write(int fd, cJSON *json);
                     89: static void print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *json_interval_streams);
                     90: static cJSON *JSON_read(int fd);
                     91: 
                     92: 
                     93: /*************************** Print usage functions ****************************/
                     94: 
                     95: void
                     96: usage()
                     97: {
                     98:     fputs(usage_shortstr, stderr);
                     99: }
                    100: 
                    101: 
                    102: void
                    103: usage_long()
                    104: {
                    105:     fprintf(stderr, usage_longstr, UDP_RATE / (1024*1024), DURATION, DEFAULT_TCP_BLKSIZE / 1024, DEFAULT_UDP_BLKSIZE / 1024);
                    106: }
                    107: 
                    108: 
                    109: void warning(char *str)
                    110: {
                    111:     fprintf(stderr, "warning: %s\n", str);
                    112: }
                    113: 
                    114: 
                    115: /************** Getter routines for some fields inside iperf_test *************/
                    116: 
                    117: int
                    118: iperf_get_verbose(struct iperf_test *ipt)
                    119: {
                    120:     return ipt->verbose;
                    121: }
                    122: 
                    123: int
                    124: iperf_get_control_socket(struct iperf_test *ipt)
                    125: {
                    126:     return ipt->ctrl_sck;
                    127: }
                    128: 
                    129: int
                    130: iperf_get_test_omit(struct iperf_test *ipt)
                    131: {
                    132:     return ipt->omit;
                    133: }
                    134: 
                    135: int
                    136: iperf_get_test_duration(struct iperf_test *ipt)
                    137: {
                    138:     return ipt->duration;
                    139: }
                    140: 
                    141: uint64_t
                    142: iperf_get_test_rate(struct iperf_test *ipt)
                    143: {
                    144:     return ipt->settings->rate;
                    145: }
                    146: 
                    147: int
                    148: iperf_get_test_burst(struct iperf_test *ipt)
                    149: {
                    150:     return ipt->settings->burst;
                    151: }
                    152: 
                    153: char
                    154: iperf_get_test_role(struct iperf_test *ipt)
                    155: {
                    156:     return ipt->role;
                    157: }
                    158: 
                    159: int
                    160: iperf_get_test_reverse(struct iperf_test *ipt)
                    161: {
                    162:     return ipt->reverse;
                    163: }
                    164: 
                    165: int
                    166: iperf_get_test_blksize(struct iperf_test *ipt)
                    167: {
                    168:     return ipt->settings->blksize;
                    169: }
                    170: 
                    171: FILE *
                    172: iperf_get_test_outfile (struct iperf_test *ipt)
                    173: {
                    174:     return ipt->outfile;
                    175: }
                    176: 
                    177: int
                    178: iperf_get_test_socket_bufsize(struct iperf_test *ipt)
                    179: {
                    180:     return ipt->settings->socket_bufsize;
                    181: }
                    182: 
                    183: double
                    184: iperf_get_test_reporter_interval(struct iperf_test *ipt)
                    185: {
                    186:     return ipt->reporter_interval;
                    187: }
                    188: 
                    189: double
                    190: iperf_get_test_stats_interval(struct iperf_test *ipt)
                    191: {
                    192:     return ipt->stats_interval;
                    193: }
                    194: 
                    195: int
                    196: iperf_get_test_num_streams(struct iperf_test *ipt)
                    197: {
                    198:     return ipt->num_streams;
                    199: }
                    200: 
                    201: int
                    202: iperf_get_test_server_port(struct iperf_test *ipt)
                    203: {
                    204:     return ipt->server_port;
                    205: }
                    206: 
                    207: char*
                    208: iperf_get_test_server_hostname(struct iperf_test *ipt)
                    209: {
                    210:     return ipt->server_hostname;
                    211: }
                    212: 
                    213: char*
                    214: iperf_get_test_template(struct iperf_test *ipt)
                    215: {
                    216:     return ipt->tmp_template;
                    217: }
                    218: 
                    219: int
                    220: iperf_get_test_protocol_id(struct iperf_test *ipt)
                    221: {
                    222:     return ipt->protocol->id;
                    223: }
                    224: 
                    225: int
                    226: iperf_get_test_json_output(struct iperf_test *ipt)
                    227: {
                    228:     return ipt->json_output;
                    229: }
                    230: 
                    231: char *
                    232: iperf_get_test_json_output_string(struct iperf_test *ipt)
                    233: {
                    234:     return ipt->json_output_string;
                    235: }
                    236: 
                    237: int
                    238: iperf_get_test_zerocopy(struct iperf_test *ipt)
                    239: {
                    240:     return ipt->zerocopy;
                    241: }
                    242: 
                    243: int
                    244: iperf_get_test_get_server_output(struct iperf_test *ipt)
                    245: {
                    246:     return ipt->get_server_output;
                    247: }
                    248: 
                    249: char
                    250: iperf_get_test_unit_format(struct iperf_test *ipt)
                    251: {
                    252:     return ipt->settings->unit_format;
                    253: }
                    254: 
                    255: char *
                    256: iperf_get_test_bind_address(struct iperf_test *ipt)
                    257: {
                    258:     return ipt->bind_address;
                    259: }
                    260: 
                    261: int
                    262: iperf_get_test_udp_counters_64bit(struct iperf_test *ipt)
                    263: {
                    264:     return ipt->udp_counters_64bit;
                    265: }
                    266: 
                    267: int
                    268: iperf_get_test_one_off(struct iperf_test *ipt)
                    269: {
                    270:     return ipt->one_off;
                    271: }
                    272: 
                    273: int
                    274: iperf_get_no_fq_socket_pacing(struct iperf_test *ipt)
                    275: {
                    276:     return ipt->no_fq_socket_pacing;
                    277: }
                    278: 
                    279: /************** Setter routines for some fields inside iperf_test *************/
                    280: 
                    281: void
                    282: iperf_set_verbose(struct iperf_test *ipt, int verbose)
                    283: {
                    284:     ipt->verbose = verbose;
                    285: }
                    286: 
                    287: void
                    288: iperf_set_control_socket(struct iperf_test *ipt, int ctrl_sck)
                    289: {
                    290:     ipt->ctrl_sck = ctrl_sck;
                    291: }
                    292: 
                    293: void
                    294: iperf_set_test_omit(struct iperf_test *ipt, int omit)
                    295: {
                    296:     ipt->omit = omit;
                    297: }
                    298: 
                    299: void
                    300: iperf_set_test_duration(struct iperf_test *ipt, int duration)
                    301: {
                    302:     ipt->duration = duration;
                    303: }
                    304: 
                    305: void
                    306: iperf_set_test_reporter_interval(struct iperf_test *ipt, double reporter_interval)
                    307: {
                    308:     ipt->reporter_interval = reporter_interval;
                    309: }
                    310: 
                    311: void
                    312: iperf_set_test_stats_interval(struct iperf_test *ipt, double stats_interval)
                    313: {
                    314:     ipt->stats_interval = stats_interval;
                    315: }
                    316: 
                    317: void
                    318: iperf_set_test_state(struct iperf_test *ipt, signed char state)
                    319: {
                    320:     ipt->state = state;
                    321: }
                    322: 
                    323: void
                    324: iperf_set_test_blksize(struct iperf_test *ipt, int blksize)
                    325: {
                    326:     ipt->settings->blksize = blksize;
                    327: }
                    328: 
                    329: void
                    330: iperf_set_test_rate(struct iperf_test *ipt, uint64_t rate)
                    331: {
                    332:     ipt->settings->rate = rate;
                    333: }
                    334: 
                    335: void
                    336: iperf_set_test_burst(struct iperf_test *ipt, int burst)
                    337: {
                    338:     ipt->settings->burst = burst;
                    339: }
                    340: 
                    341: void
                    342: iperf_set_test_server_port(struct iperf_test *ipt, int server_port)
                    343: {
                    344:     ipt->server_port = server_port;
                    345: }
                    346: 
                    347: void
                    348: iperf_set_test_socket_bufsize(struct iperf_test *ipt, int socket_bufsize)
                    349: {
                    350:     ipt->settings->socket_bufsize = socket_bufsize;
                    351: }
                    352: 
                    353: void
                    354: iperf_set_test_num_streams(struct iperf_test *ipt, int num_streams)
                    355: {
                    356:     ipt->num_streams = num_streams;
                    357: }
                    358: 
                    359: static void
                    360: check_sender_has_retransmits(struct iperf_test *ipt)
                    361: {
                    362:     if (ipt->sender && ipt->protocol->id == Ptcp && has_tcpinfo_retransmits())
                    363:        ipt->sender_has_retransmits = 1;
                    364:     else
                    365:        ipt->sender_has_retransmits = 0;
                    366: }
                    367: 
                    368: void
                    369: iperf_set_test_role(struct iperf_test *ipt, char role)
                    370: {
                    371:     ipt->role = role;
                    372:     if (role == 'c')
                    373:        ipt->sender = 1;
                    374:     else if (role == 's')
                    375:        ipt->sender = 0;
                    376:     if (ipt->reverse)
                    377:         ipt->sender = ! ipt->sender;
                    378:     check_sender_has_retransmits(ipt);
                    379: }
                    380: 
                    381: void
                    382: iperf_set_test_server_hostname(struct iperf_test *ipt, char *server_hostname)
                    383: {
                    384:     ipt->server_hostname = strdup(server_hostname);
                    385: }
                    386: 
                    387: void
                    388: iperf_set_test_template(struct iperf_test *ipt, char *tmp_template)
                    389: {
                    390:     ipt->tmp_template = strdup(tmp_template);
                    391: }
                    392: 
                    393: void
                    394: iperf_set_test_reverse(struct iperf_test *ipt, int reverse)
                    395: {
                    396:     ipt->reverse = reverse;
                    397:     if (ipt->reverse)
                    398:         ipt->sender = ! ipt->sender;
                    399:     check_sender_has_retransmits(ipt);
                    400: }
                    401: 
                    402: void
                    403: iperf_set_test_json_output(struct iperf_test *ipt, int json_output)
                    404: {
                    405:     ipt->json_output = json_output;
                    406: }
                    407: 
                    408: int
                    409: iperf_has_zerocopy( void )
                    410: {
                    411:     return has_sendfile();
                    412: }
                    413: 
                    414: void
                    415: iperf_set_test_zerocopy(struct iperf_test *ipt, int zerocopy)
                    416: {
                    417:     ipt->zerocopy = (zerocopy && has_sendfile());
                    418: }
                    419: 
                    420: void
                    421: iperf_set_test_get_server_output(struct iperf_test *ipt, int get_server_output)
                    422: {
                    423:     ipt->get_server_output = get_server_output;
                    424: }
                    425: 
                    426: void
                    427: iperf_set_test_unit_format(struct iperf_test *ipt, char unit_format)
                    428: {
                    429:     ipt->settings->unit_format = unit_format;
                    430: }
                    431: 
                    432: void
                    433: iperf_set_test_bind_address(struct iperf_test *ipt, char *bind_address)
                    434: {
                    435:     ipt->bind_address = strdup(bind_address);
                    436: }
                    437: 
                    438: void
                    439: iperf_set_test_udp_counters_64bit(struct iperf_test *ipt, int udp_counters_64bit)
                    440: {
                    441:     ipt->udp_counters_64bit = udp_counters_64bit;
                    442: }
                    443: 
                    444: void
                    445: iperf_set_test_one_off(struct iperf_test *ipt, int one_off)
                    446: {
                    447:     ipt->one_off = one_off;
                    448: }
                    449: 
                    450: void
                    451: iperf_set_no_fq_socket_pacing(struct iperf_test *ipt, int no_pacing)
                    452: {
                    453:     ipt->no_fq_socket_pacing = no_pacing;
                    454: }
                    455: 
                    456: /********************** Get/set test protocol structure ***********************/
                    457: 
                    458: struct protocol *
                    459: get_protocol(struct iperf_test *test, int prot_id)
                    460: {
                    461:     struct protocol *prot;
                    462: 
                    463:     SLIST_FOREACH(prot, &test->protocols, protocols) {
                    464:         if (prot->id == prot_id)
                    465:             break;
                    466:     }
                    467: 
                    468:     if (prot == NULL)
                    469:         i_errno = IEPROTOCOL;
                    470: 
                    471:     return prot;
                    472: }
                    473: 
                    474: int
                    475: set_protocol(struct iperf_test *test, int prot_id)
                    476: {
                    477:     struct protocol *prot = NULL;
                    478: 
                    479:     SLIST_FOREACH(prot, &test->protocols, protocols) {
                    480:         if (prot->id == prot_id) {
                    481:             test->protocol = prot;
                    482:            check_sender_has_retransmits(test);
                    483:             return 0;
                    484:         }
                    485:     }
                    486: 
                    487:     i_errno = IEPROTOCOL;
                    488:     return -1;
                    489: }
                    490: 
                    491: 
                    492: /************************** Iperf callback functions **************************/
                    493: 
                    494: void
                    495: iperf_on_new_stream(struct iperf_stream *sp)
                    496: {
                    497:     connect_msg(sp);
                    498: }
                    499: 
                    500: void
                    501: iperf_on_test_start(struct iperf_test *test)
                    502: {
                    503:     if (test->json_output) {
                    504:        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", 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));
                    505:     } else {
                    506:        if (test->verbose) {
                    507:            if (test->settings->bytes)
                    508:                iprintf(test, test_start_bytes, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->settings->bytes);
                    509:            else if (test->settings->blocks)
                    510:                iprintf(test, test_start_blocks, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->settings->blocks);
                    511:            else
                    512:                iprintf(test, test_start_time, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->duration);
                    513:        }
                    514:     }
                    515: }
                    516: 
                    517: /* This converts an IPv6 string address from IPv4-mapped format into regular
                    518: ** old IPv4 format, which is easier on the eyes of network veterans.
                    519: **
                    520: ** If the v6 address is not v4-mapped it is left alone.
                    521: */
                    522: static void
                    523: mapped_v4_to_regular_v4(char *str)
                    524: {
                    525:     char *prefix = "::ffff:";
                    526:     int prefix_len;
                    527: 
                    528:     prefix_len = strlen(prefix);
                    529:     if (strncmp(str, prefix, prefix_len) == 0) {
                    530:        int str_len = strlen(str);
                    531:        memmove(str, str + prefix_len, str_len - prefix_len + 1);
                    532:     }
                    533: }
                    534: 
                    535: void
                    536: iperf_on_connect(struct iperf_test *test)
                    537: {
                    538:     time_t now_secs;
                    539:     const char* rfc1123_fmt = "%a, %d %b %Y %H:%M:%S GMT";
                    540:     char now_str[100];
                    541:     char ipr[INET6_ADDRSTRLEN];
                    542:     int port;
                    543:     struct sockaddr_storage sa;
                    544:     struct sockaddr_in *sa_inP;
                    545:     struct sockaddr_in6 *sa_in6P;
                    546:     socklen_t len;
                    547:     int opt;
                    548: 
                    549:     now_secs = time((time_t*) 0);
                    550:     (void) strftime(now_str, sizeof(now_str), rfc1123_fmt, gmtime(&now_secs));
                    551:     if (test->json_output)
                    552:        cJSON_AddItemToObject(test->json_start, "timestamp", iperf_json_printf("time: %s  timesecs: %d", now_str, (int64_t) now_secs));
                    553:     else if (test->verbose)
                    554:        iprintf(test, report_time, now_str);
                    555: 
                    556:     if (test->role == 'c') {
                    557:        if (test->json_output)
                    558:            cJSON_AddItemToObject(test->json_start, "connecting_to", iperf_json_printf("host: %s  port: %d", test->server_hostname, (int64_t) test->server_port));
                    559:        else {
                    560:            iprintf(test, report_connecting, test->server_hostname, test->server_port);
                    561:            if (test->reverse)
                    562:                iprintf(test, report_reverse, test->server_hostname);
                    563:        }
                    564:     } else {
                    565:         len = sizeof(sa);
                    566:         getpeername(test->ctrl_sck, (struct sockaddr *) &sa, &len);
                    567:         if (getsockdomain(test->ctrl_sck) == AF_INET) {
                    568:            sa_inP = (struct sockaddr_in *) &sa;
                    569:             inet_ntop(AF_INET, &sa_inP->sin_addr, ipr, sizeof(ipr));
                    570:            port = ntohs(sa_inP->sin_port);
                    571:         } else {
                    572:            sa_in6P = (struct sockaddr_in6 *) &sa;
                    573:             inet_ntop(AF_INET6, &sa_in6P->sin6_addr, ipr, sizeof(ipr));
                    574:            port = ntohs(sa_in6P->sin6_port);
                    575:         }
                    576:        mapped_v4_to_regular_v4(ipr);
                    577:        if (test->json_output)
                    578:            cJSON_AddItemToObject(test->json_start, "accepted_connection", iperf_json_printf("host: %s  port: %d", ipr, (int64_t) port));
                    579:        else
                    580:            iprintf(test, report_accepted, ipr, port);
                    581:     }
                    582:     if (test->json_output) {
                    583:        cJSON_AddStringToObject(test->json_start, "cookie", test->cookie);
                    584:         if (test->protocol->id == SOCK_STREAM) {
                    585:            if (test->settings->mss)
                    586:                cJSON_AddNumberToObject(test->json_start, "tcp_mss", test->settings->mss);
                    587:            else {
                    588:                len = sizeof(opt);
                    589:                getsockopt(test->ctrl_sck, IPPROTO_TCP, TCP_MAXSEG, &opt, &len);
                    590:                cJSON_AddNumberToObject(test->json_start, "tcp_mss_default", opt);
                    591:            }
                    592:        }
                    593:     } else if (test->verbose) {
                    594:         iprintf(test, report_cookie, test->cookie);
                    595:         if (test->protocol->id == SOCK_STREAM) {
                    596:             if (test->settings->mss)
                    597:                 iprintf(test, "      TCP MSS: %d\n", test->settings->mss);
                    598:             else {
                    599:                 len = sizeof(opt);
                    600:                 getsockopt(test->ctrl_sck, IPPROTO_TCP, TCP_MAXSEG, &opt, &len);
                    601:                 iprintf(test, "      TCP MSS: %d (default)\n", opt);
                    602:             }
                    603:         }
                    604: 
                    605:     }
                    606: }
                    607: 
                    608: void
                    609: iperf_on_test_finish(struct iperf_test *test)
                    610: {
                    611: }
                    612: 
                    613: 
                    614: /******************************************************************************/
                    615: 
                    616: int
                    617: iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
                    618: {
                    619:     static struct option longopts[] =
                    620:     {
                    621:         {"port", required_argument, NULL, 'p'},
                    622:         {"format", required_argument, NULL, 'f'},
                    623:         {"interval", required_argument, NULL, 'i'},
                    624:         {"daemon", no_argument, NULL, 'D'},
                    625:         {"one-off", no_argument, NULL, '1'},
                    626:         {"verbose", no_argument, NULL, 'V'},
                    627:         {"json", no_argument, NULL, 'J'},
                    628:         {"version", no_argument, NULL, 'v'},
                    629:         {"server", no_argument, NULL, 's'},
                    630:         {"client", required_argument, NULL, 'c'},
                    631:         {"udp", no_argument, NULL, 'u'},
                    632:         {"bandwidth", required_argument, NULL, 'b'},
                    633:         {"time", required_argument, NULL, 't'},
                    634:         {"bytes", required_argument, NULL, 'n'},
                    635:         {"blockcount", required_argument, NULL, 'k'},
                    636:         {"length", required_argument, NULL, 'l'},
                    637:         {"parallel", required_argument, NULL, 'P'},
                    638:         {"reverse", no_argument, NULL, 'R'},
                    639:         {"window", required_argument, NULL, 'w'},
                    640:         {"bind", required_argument, NULL, 'B'},
                    641:         {"cport", required_argument, NULL, OPT_CLIENT_PORT},
                    642:         {"set-mss", required_argument, NULL, 'M'},
                    643:         {"no-delay", no_argument, NULL, 'N'},
                    644:         {"version4", no_argument, NULL, '4'},
                    645:         {"version6", no_argument, NULL, '6'},
                    646:         {"tos", required_argument, NULL, 'S'},
                    647: #if defined(HAVE_FLOWLABEL)
                    648:         {"flowlabel", required_argument, NULL, 'L'},
                    649: #endif /* HAVE_FLOWLABEL */
                    650:         {"zerocopy", no_argument, NULL, 'Z'},
                    651:         {"omit", required_argument, NULL, 'O'},
                    652:         {"file", required_argument, NULL, 'F'},
                    653: #if defined(HAVE_CPU_AFFINITY)
                    654:         {"affinity", required_argument, NULL, 'A'},
                    655: #endif /* HAVE_CPU_AFFINITY */
                    656:         {"title", required_argument, NULL, 'T'},
                    657: #if defined(HAVE_TCP_CONGESTION)
                    658:         {"congestion", required_argument, NULL, 'C'},
                    659:         {"linux-congestion", required_argument, NULL, 'C'},
                    660: #endif /* HAVE_TCP_CONGESTION */
                    661: #if defined(HAVE_SCTP)
                    662:         {"sctp", no_argument, NULL, OPT_SCTP},
                    663:         {"nstreams", required_argument, NULL, OPT_NUMSTREAMS},
                    664:         {"xbind", required_argument, NULL, 'X'},
                    665: #endif
                    666:        {"pidfile", required_argument, NULL, 'I'},
                    667:        {"logfile", required_argument, NULL, OPT_LOGFILE},
                    668:        {"get-server-output", no_argument, NULL, OPT_GET_SERVER_OUTPUT},
                    669:        {"udp-counters-64bit", no_argument, NULL, OPT_UDP_COUNTERS_64BIT},
                    670:        {"no-fq-socket-pacing", no_argument, NULL, OPT_NO_FQ_SOCKET_PACING},
                    671:         {"debug", no_argument, NULL, 'd'},
                    672:         {"help", no_argument, NULL, 'h'},
                    673:         {NULL, 0, NULL, 0}
                    674:     };
                    675:     int flag;
                    676:     int blksize;
                    677:     int server_flag, client_flag, rate_flag, duration_flag;
                    678:     char *endptr;
                    679: #if defined(HAVE_CPU_AFFINITY)
                    680:     char* comma;
                    681: #endif /* HAVE_CPU_AFFINITY */
                    682:     char* slash;
                    683:     struct xbind_entry *xbe;
                    684: 
                    685:     blksize = 0;
                    686:     server_flag = client_flag = rate_flag = duration_flag = 0;
                    687:     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) {
                    688:         switch (flag) {
                    689:             case 'p':
                    690:                 test->server_port = atoi(optarg);
                    691:                 break;
                    692:             case 'f':
                    693:                 test->settings->unit_format = *optarg;
                    694:                 break;
                    695:             case 'i':
                    696:                 /* XXX: could potentially want separate stat collection and reporting intervals,
                    697:                    but just set them to be the same for now */
                    698:                 test->stats_interval = test->reporter_interval = atof(optarg);
                    699:                 if ((test->stats_interval < MIN_INTERVAL || test->stats_interval > MAX_INTERVAL) && test->stats_interval != 0) {
                    700:                     i_errno = IEINTERVAL;
                    701:                     return -1;
                    702:                 }
                    703:                 break;
                    704:             case 'D':
                    705:                test->daemon = 1;
                    706:                server_flag = 1;
                    707:                break;
                    708:             case '1':
                    709:                test->one_off = 1;
                    710:                server_flag = 1;
                    711:                break;
                    712:             case 'V':
                    713:                 test->verbose = 1;
                    714:                 break;
                    715:             case 'J':
                    716:                 test->json_output = 1;
                    717:                 break;
                    718:             case 'v':
                    719:                 printf("%s\n%s\n%s\n", version, get_system_info(), 
                    720:                       get_optional_features());
                    721:                 exit(0);
                    722:             case 's':
                    723:                 if (test->role == 'c') {
                    724:                     i_errno = IESERVCLIENT;
                    725:                     return -1;
                    726:                 }
                    727:                iperf_set_test_role(test, 's');
                    728:                 break;
                    729:             case 'c':
                    730:                 if (test->role == 's') {
                    731:                     i_errno = IESERVCLIENT;
                    732:                     return -1;
                    733:                 }
                    734:                iperf_set_test_role(test, 'c');
                    735:                iperf_set_test_server_hostname(test, optarg);
                    736:                 break;
                    737:             case 'u':
                    738:                 set_protocol(test, Pudp);
                    739:                client_flag = 1;
                    740:                 break;
                    741:             case OPT_SCTP:
                    742: #if defined(HAVE_SCTP)
                    743:                 set_protocol(test, Psctp);
                    744:                 client_flag = 1;
                    745: #else /* HAVE_SCTP */
                    746:                 i_errno = IEUNIMP;
                    747:                 return -1;
                    748: #endif /* HAVE_SCTP */
                    749:             break;
                    750: 
                    751:             case OPT_NUMSTREAMS:
                    752: #if defined(linux) || defined(__FreeBSD__)
                    753:                 test->settings->num_ostreams = unit_atoi(optarg);
                    754:                 client_flag = 1;
                    755: #else /* linux */
                    756:                 i_errno = IEUNIMP;
                    757:                 return -1;
                    758: #endif /* linux */
                    759:             case 'b':
                    760:                slash = strchr(optarg, '/');
                    761:                if (slash) {
                    762:                    *slash = '\0';
                    763:                    ++slash;
                    764:                    test->settings->burst = atoi(slash);
                    765:                    if (test->settings->burst <= 0 ||
                    766:                        test->settings->burst > MAX_BURST) {
                    767:                        i_errno = IEBURST;
                    768:                        return -1;
                    769:                    }
                    770:                }
                    771:                 test->settings->rate = unit_atof_rate(optarg);
                    772:                rate_flag = 1;
                    773:                client_flag = 1;
                    774:                 break;
                    775:             case 't':
                    776:                 test->duration = atoi(optarg);
                    777:                 if (test->duration > MAX_TIME) {
                    778:                     i_errno = IEDURATION;
                    779:                     return -1;
                    780:                 }
                    781:                duration_flag = 1;
                    782:                client_flag = 1;
                    783:                 break;
                    784:             case 'n':
                    785:                 test->settings->bytes = unit_atoi(optarg);
                    786:                client_flag = 1;
                    787:                 break;
                    788:             case 'k':
                    789:                 test->settings->blocks = unit_atoi(optarg);
                    790:                client_flag = 1;
                    791:                 break;
                    792:             case 'l':
                    793:                 blksize = unit_atoi(optarg);
                    794:                client_flag = 1;
                    795:                 break;
                    796:             case 'P':
                    797:                 test->num_streams = atoi(optarg);
                    798:                 if (test->num_streams > MAX_STREAMS) {
                    799:                     i_errno = IENUMSTREAMS;
                    800:                     return -1;
                    801:                 }
                    802:                client_flag = 1;
                    803:                 break;
                    804:             case 'R':
                    805:                iperf_set_test_reverse(test, 1);
                    806:                client_flag = 1;
                    807:                 break;
                    808:             case 'w':
                    809:                 // XXX: This is a socket buffer, not specific to TCP
                    810:                 test->settings->socket_bufsize = unit_atof(optarg);
                    811:                 if (test->settings->socket_bufsize > MAX_TCP_BUFFER) {
                    812:                     i_errno = IEBUFSIZE;
                    813:                     return -1;
                    814:                 }
                    815:                client_flag = 1;
                    816:                 break;
                    817:             case 'B':
                    818:                 test->bind_address = strdup(optarg);
                    819:                 break;
                    820:             case OPT_CLIENT_PORT:
                    821:                 test->bind_port = atoi(optarg);
                    822:                 break;
                    823:             case 'M':
                    824:                 test->settings->mss = atoi(optarg);
                    825:                 if (test->settings->mss > MAX_MSS) {
                    826:                     i_errno = IEMSS;
                    827:                     return -1;
                    828:                 }
                    829:                client_flag = 1;
                    830:                 break;
                    831:             case 'N':
                    832:                 test->no_delay = 1;
                    833:                client_flag = 1;
                    834:                 break;
                    835:             case '4':
                    836:                 test->settings->domain = AF_INET;
                    837:                 break;
                    838:             case '6':
                    839:                 test->settings->domain = AF_INET6;
                    840:                 break;
                    841:             case 'S':
                    842:                 test->settings->tos = strtol(optarg, &endptr, 0);
                    843:                if (endptr == optarg ||
                    844:                    test->settings->tos < 0 ||
                    845:                    test->settings->tos > 255) {
                    846:                    i_errno = IEBADTOS;
                    847:                    return -1;
                    848:                }
                    849:                client_flag = 1;
                    850:                 break;
                    851:             case 'L':
                    852: #if defined(HAVE_FLOWLABEL)
                    853:                 test->settings->flowlabel = strtol(optarg, &endptr, 0);
                    854:                if (endptr == optarg ||
                    855:                    test->settings->flowlabel < 1 || test->settings->flowlabel > 0xfffff) {
                    856:                     i_errno = IESETFLOW;
                    857:                     return -1;
                    858:                }
                    859:                client_flag = 1;
                    860: #else /* HAVE_FLOWLABEL */
                    861:                 i_errno = IEUNIMP;
                    862:                 return -1;
                    863: #endif /* HAVE_FLOWLABEL */
                    864:                 break;
                    865:             case 'X':
                    866:                xbe = (struct xbind_entry *)malloc(sizeof(struct xbind_entry));
                    867:                 if (!xbe) {
                    868:                    i_errno = IESETSCTPBINDX;
                    869:                     return -1;
                    870:                 }
                    871:                memset(xbe, 0, sizeof(*xbe));
                    872:                 xbe->name = strdup(optarg);
                    873:                 if (!xbe->name) {
                    874:                    i_errno = IESETSCTPBINDX;
                    875:                     return -1;
                    876:                 }
                    877:                TAILQ_INSERT_TAIL(&test->xbind_addrs, xbe, link);
                    878:                 break;
                    879:             case 'Z':
                    880:                 if (!has_sendfile()) {
                    881:                     i_errno = IENOSENDFILE;
                    882:                     return -1;
                    883:                 }
                    884:                 test->zerocopy = 1;
                    885:                client_flag = 1;
                    886:                 break;
                    887:             case 'O':
                    888:                 test->omit = atoi(optarg);
                    889:                 if (test->omit < 0 || test->omit > 60) {
                    890:                     i_errno = IEOMIT;
                    891:                     return -1;
                    892:                 }
                    893:                client_flag = 1;
                    894:                 break;
                    895:             case 'F':
                    896:                 test->diskfile_name = optarg;
                    897:                 break;
                    898:             case 'A':
                    899: #if defined(HAVE_CPU_AFFINITY)
                    900:                 test->affinity = strtol(optarg, &endptr, 0);
                    901:                 if (endptr == optarg || 
                    902:                    test->affinity < 0 || test->affinity > 1024) {
                    903:                     i_errno = IEAFFINITY;
                    904:                     return -1;
                    905:                 }
                    906:                comma = strchr(optarg, ',');
                    907:                if (comma != NULL) {
                    908:                    test->server_affinity = atoi(comma+1);
                    909:                    if (test->server_affinity < 0 || test->server_affinity > 1024) {
                    910:                        i_errno = IEAFFINITY;
                    911:                        return -1;
                    912:                    }
                    913:                    client_flag = 1;
                    914:                }
                    915: #else /* HAVE_CPU_AFFINITY */
                    916:                 i_errno = IEUNIMP;
                    917:                 return -1;
                    918: #endif /* HAVE_CPU_AFFINITY */
                    919:                 break;
                    920:             case 'T':
                    921:                 test->title = strdup(optarg);
                    922:                client_flag = 1;
                    923:                 break;
                    924:            case 'C':
                    925: #if defined(HAVE_TCP_CONGESTION)
                    926:                test->congestion = strdup(optarg);
                    927:                client_flag = 1;
                    928: #else /* HAVE_TCP_CONGESTION */
                    929:                i_errno = IEUNIMP;
                    930:                return -1;
                    931: #endif /* HAVE_TCP_CONGESTION */
                    932:                break;
                    933:            case 'd':
                    934:                test->debug = 1;
                    935:                break;
                    936:            case 'I':
                    937:                test->pidfile = strdup(optarg);
                    938:                server_flag = 1;
                    939:                break;
                    940:            case OPT_LOGFILE:
                    941:                test->logfile = strdup(optarg);
                    942:                break;
                    943:            case OPT_GET_SERVER_OUTPUT:
                    944:                test->get_server_output = 1;
                    945:                client_flag = 1;
                    946:                break;
                    947:            case OPT_UDP_COUNTERS_64BIT:
                    948:                test->udp_counters_64bit = 1;
                    949:                break;
                    950:            case OPT_NO_FQ_SOCKET_PACING:
                    951: #if defined(HAVE_SO_MAX_PACING_RATE)
                    952:                test->no_fq_socket_pacing = 1;
                    953: #else /* HAVE_SO_MAX_PACING_RATE */
                    954:                i_errno = IEUNIMP;
                    955:                return -1;
                    956: #endif
                    957:                break;
                    958:             case 'h':
                    959:             default:
                    960:                 usage_long();
                    961:                 exit(1);
                    962:         }
                    963:     }
                    964: 
                    965:     /* Set logging to a file if specified, otherwise use the default (stdout) */
                    966:     if (test->logfile) {
                    967:        test->outfile = fopen(test->logfile, "a+");
                    968:        if (test->outfile == NULL) {
                    969:            i_errno = IELOGFILE;
                    970:            return -1;
                    971:        }
                    972:     }
                    973: 
                    974:     /* Check flag / role compatibility. */
                    975:     if (test->role == 'c' && server_flag) {
                    976:        i_errno = IESERVERONLY;
                    977:        return -1;
                    978:     }
                    979:     if (test->role == 's' && client_flag) {
                    980:        i_errno = IECLIENTONLY;
                    981:        return -1;
                    982:     }
                    983: 
                    984:     if (!test->bind_address && test->bind_port) {
                    985:         i_errno = IEBIND;
                    986:         return -1;
                    987:     }
                    988:     if (blksize == 0) {
                    989:        if (test->protocol->id == Pudp)
                    990:            blksize = DEFAULT_UDP_BLKSIZE;
                    991:        else if (test->protocol->id == Psctp)
                    992:            blksize = DEFAULT_SCTP_BLKSIZE;
                    993:        else
                    994:            blksize = DEFAULT_TCP_BLKSIZE;
                    995:     }
                    996:     if (blksize <= 0 || blksize > MAX_BLOCKSIZE) {
                    997:        i_errno = IEBLOCKSIZE;
                    998:        return -1;
                    999:     }
                   1000:     if (test->protocol->id == Pudp &&
                   1001:        blksize > MAX_UDP_BLOCKSIZE) {
                   1002:        i_errno = IEUDPBLOCKSIZE;
                   1003:        return -1;
                   1004:     }
                   1005:     test->settings->blksize = blksize;
                   1006: 
                   1007:     if (!rate_flag)
                   1008:        test->settings->rate = test->protocol->id == Pudp ? UDP_RATE : 0;
                   1009: 
                   1010:     if ((test->settings->bytes != 0 || test->settings->blocks != 0) && ! duration_flag)
                   1011:         test->duration = 0;
                   1012: 
                   1013:     /* Disallow specifying multiple test end conditions. The code actually
                   1014:     ** works just fine without this prohibition. As soon as any one of the
                   1015:     ** three possible end conditions is met, the test ends. So this check
                   1016:     ** could be removed if desired.
                   1017:     */
                   1018:     if ((duration_flag && test->settings->bytes != 0) ||
                   1019:         (duration_flag && test->settings->blocks != 0) ||
                   1020:        (test->settings->bytes != 0 && test->settings->blocks != 0)) {
                   1021:         i_errno = IEENDCONDITIONS;
                   1022:         return -1;
                   1023:     }
                   1024: 
                   1025:     /* For subsequent calls to getopt */
                   1026: #ifdef __APPLE__
                   1027:     optreset = 1;
                   1028: #endif
                   1029:     optind = 0;
                   1030: 
                   1031:     if ((test->role != 'c') && (test->role != 's')) {
                   1032:         i_errno = IENOROLE;
                   1033:         return -1;
                   1034:     }
                   1035: 
                   1036:     return 0;
                   1037: }
                   1038: 
                   1039: int
                   1040: iperf_set_send_state(struct iperf_test *test, signed char state)
                   1041: {
                   1042:     test->state = state;
                   1043:     if (Nwrite(test->ctrl_sck, (char*) &state, sizeof(state), Ptcp) < 0) {
                   1044:        i_errno = IESENDMESSAGE;
                   1045:        return -1;
                   1046:     }
                   1047:     return 0;
                   1048: }
                   1049: 
                   1050: void
                   1051: iperf_check_throttle(struct iperf_stream *sp, struct timeval *nowP)
                   1052: {
                   1053:     double seconds;
                   1054:     uint64_t bits_per_second;
                   1055: 
                   1056:     if (sp->test->done)
                   1057:         return;
                   1058:     seconds = timeval_diff(&sp->result->start_time_fixed, nowP);
                   1059:     bits_per_second = sp->result->bytes_sent * 8 / seconds;
                   1060:     if (bits_per_second < sp->test->settings->rate) {
                   1061:         sp->green_light = 1;
                   1062:         FD_SET(sp->socket, &sp->test->write_set);
                   1063:     } else {
                   1064:         sp->green_light = 0;
                   1065:         FD_CLR(sp->socket, &sp->test->write_set);
                   1066:     }
                   1067: }
                   1068: 
                   1069: int
                   1070: iperf_send(struct iperf_test *test, fd_set *write_setP)
                   1071: {
                   1072:     register int multisend, r, streams_active;
                   1073:     register struct iperf_stream *sp;
                   1074:     struct timeval now;
                   1075: 
                   1076:     /* Can we do multisend mode? */
                   1077:     if (test->settings->burst != 0)
                   1078:         multisend = test->settings->burst;
                   1079:     else if (test->settings->rate == 0)
                   1080:         multisend = test->multisend;
                   1081:     else
                   1082:         multisend = 1; /* nope */
                   1083: 
                   1084:     for (; multisend > 0; --multisend) {
                   1085:        if (test->settings->rate != 0 && test->settings->burst == 0)
                   1086:            gettimeofday(&now, NULL);
                   1087:        streams_active = 0;
                   1088:        SLIST_FOREACH(sp, &test->streams, streams) {
                   1089:            if (! test->no_fq_socket_pacing ||
                   1090:                (sp->green_light &&
                   1091:                 (write_setP == NULL || FD_ISSET(sp->socket, write_setP)))) {
                   1092:                if ((r = sp->snd(sp)) < 0) {
                   1093:                    if (r == NET_SOFTERROR)
                   1094:                        break;
                   1095:                    i_errno = IESTREAMWRITE;
                   1096:                    return r;
                   1097:                }
                   1098:                streams_active = 1;
                   1099:                test->bytes_sent += r;
                   1100:                ++test->blocks_sent;
                   1101:                if (test->settings->rate != 0 && test->settings->burst == 0)
                   1102:                    iperf_check_throttle(sp, &now);
                   1103:                if (multisend > 1 && test->settings->bytes != 0 && test->bytes_sent >= test->settings->bytes)
                   1104:                    break;
                   1105:                if (multisend > 1 && test->settings->blocks != 0 && test->blocks_sent >= test->settings->blocks)
                   1106:                    break;
                   1107:            }
                   1108:        }
                   1109:        if (!streams_active)
                   1110:            break;
                   1111:     }
                   1112:     if (test->settings->burst != 0) {
                   1113:        gettimeofday(&now, NULL);
                   1114:        SLIST_FOREACH(sp, &test->streams, streams)
                   1115:            iperf_check_throttle(sp, &now);
                   1116:     }
                   1117:     if (write_setP != NULL)
                   1118:        SLIST_FOREACH(sp, &test->streams, streams)
                   1119:            if (FD_ISSET(sp->socket, write_setP))
                   1120:                FD_CLR(sp->socket, write_setP);
                   1121: 
                   1122:     return 0;
                   1123: }
                   1124: 
                   1125: int
                   1126: iperf_recv(struct iperf_test *test, fd_set *read_setP)
                   1127: {
                   1128:     int r;
                   1129:     struct iperf_stream *sp;
                   1130: 
                   1131:     SLIST_FOREACH(sp, &test->streams, streams) {
                   1132:        if (FD_ISSET(sp->socket, read_setP)) {
                   1133:            if ((r = sp->rcv(sp)) < 0) {
                   1134:                i_errno = IESTREAMREAD;
                   1135:                return r;
                   1136:            }
                   1137:            test->bytes_sent += r;
                   1138:            ++test->blocks_sent;
                   1139:            FD_CLR(sp->socket, read_setP);
                   1140:        }
                   1141:     }
                   1142: 
                   1143:     return 0;
                   1144: }
                   1145: 
                   1146: int
                   1147: iperf_init_test(struct iperf_test *test)
                   1148: {
                   1149:     struct timeval now;
                   1150:     struct iperf_stream *sp;
                   1151: 
                   1152:     if (test->protocol->init) {
                   1153:         if (test->protocol->init(test) < 0)
                   1154:             return -1;
                   1155:     }
                   1156: 
                   1157:     /* Init each stream. */
                   1158:     if (gettimeofday(&now, NULL) < 0) {
                   1159:        i_errno = IEINITTEST;
                   1160:        return -1;
                   1161:     }
                   1162:     SLIST_FOREACH(sp, &test->streams, streams) {
                   1163:        sp->result->start_time = sp->result->start_time_fixed = now;
                   1164:     }
                   1165: 
                   1166:     if (test->on_test_start)
                   1167:         test->on_test_start(test);
                   1168: 
                   1169:     return 0;
                   1170: }
                   1171: 
                   1172: static void
                   1173: send_timer_proc(TimerClientData client_data, struct timeval *nowP)
                   1174: {
                   1175:     struct iperf_stream *sp = client_data.p;
                   1176: 
                   1177:     /* All we do here is set or clear the flag saying that this stream may
                   1178:     ** be sent to.  The actual sending gets done in the send proc, after
                   1179:     ** checking the flag.
                   1180:     */
                   1181:     iperf_check_throttle(sp, nowP);
                   1182: }
                   1183: 
                   1184: int
                   1185: iperf_create_send_timers(struct iperf_test * test)
                   1186: {
                   1187:     struct timeval now;
                   1188:     struct iperf_stream *sp;
                   1189:     TimerClientData cd;
                   1190: 
                   1191:     if (gettimeofday(&now, NULL) < 0) {
                   1192:        i_errno = IEINITTEST;
                   1193:        return -1;
                   1194:     }
                   1195:     SLIST_FOREACH(sp, &test->streams, streams) {
                   1196:         sp->green_light = 1;
                   1197:        if (test->settings->rate != 0) {
                   1198:            cd.p = sp;
                   1199:            sp->send_timer = tmr_create((struct timeval*) 0, send_timer_proc, cd, 100000L, 1);
                   1200:            /* (Repeat every tenth second - arbitrary often value.) */
                   1201:            if (sp->send_timer == NULL) {
                   1202:                i_errno = IEINITTEST;
                   1203:                return -1;
                   1204:            }
                   1205:        }
                   1206:     }
                   1207:     return 0;
                   1208: }
                   1209: 
                   1210: /**
                   1211:  * iperf_exchange_parameters - handles the param_Exchange part for client
                   1212:  *
                   1213:  */
                   1214: 
                   1215: int
                   1216: iperf_exchange_parameters(struct iperf_test *test)
                   1217: {
                   1218:     int s;
                   1219:     int32_t err;
                   1220: 
                   1221:     if (test->role == 'c') {
                   1222: 
                   1223:         if (send_parameters(test) < 0)
                   1224:             return -1;
                   1225: 
                   1226:     } else {
                   1227: 
                   1228:         if (get_parameters(test) < 0)
                   1229:             return -1;
                   1230: 
                   1231:         if ((s = test->protocol->listen(test)) < 0) {
                   1232:            if (iperf_set_send_state(test, SERVER_ERROR) != 0)
                   1233:                 return -1;
                   1234:             err = htonl(i_errno);
                   1235:             if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) {
                   1236:                 i_errno = IECTRLWRITE;
                   1237:                 return -1;
                   1238:             }
                   1239:             err = htonl(errno);
                   1240:             if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) {
                   1241:                 i_errno = IECTRLWRITE;
                   1242:                 return -1;
                   1243:             }
                   1244:             return -1;
                   1245:         }
                   1246:         FD_SET(s, &test->read_set);
                   1247:         test->max_fd = (s > test->max_fd) ? s : test->max_fd;
                   1248:         test->prot_listener = s;
                   1249: 
                   1250:         // Send the control message to create streams and start the test
                   1251:        if (iperf_set_send_state(test, CREATE_STREAMS) != 0)
                   1252:             return -1;
                   1253: 
                   1254:     }
                   1255: 
                   1256:     return 0;
                   1257: }
                   1258: 
                   1259: /*************************************************************/
                   1260: 
                   1261: int
                   1262: iperf_exchange_results(struct iperf_test *test)
                   1263: {
                   1264:     if (test->role == 'c') {
                   1265:         /* Send results to server. */
                   1266:        if (send_results(test) < 0)
                   1267:             return -1;
                   1268:         /* Get server results. */
                   1269:         if (get_results(test) < 0)
                   1270:             return -1;
                   1271:     } else {
                   1272:         /* Get client results. */
                   1273:         if (get_results(test) < 0)
                   1274:             return -1;
                   1275:         /* Send results to client. */
                   1276:        if (send_results(test) < 0)
                   1277:             return -1;
                   1278:     }
                   1279:     return 0;
                   1280: }
                   1281: 
                   1282: /*************************************************************/
                   1283: 
                   1284: static int
                   1285: send_parameters(struct iperf_test *test)
                   1286: {
                   1287:     int r = 0;
                   1288:     cJSON *j;
                   1289: 
                   1290:     j = cJSON_CreateObject();
                   1291:     if (j == NULL) {
                   1292:        i_errno = IESENDPARAMS;
                   1293:        r = -1;
                   1294:     } else {
                   1295:        if (test->protocol->id == Ptcp)
                   1296:            cJSON_AddTrueToObject(j, "tcp");
                   1297:        else if (test->protocol->id == Pudp)
                   1298:            cJSON_AddTrueToObject(j, "udp");
                   1299:         else if (test->protocol->id == Psctp)
                   1300:             cJSON_AddTrueToObject(j, "sctp");
                   1301:        cJSON_AddNumberToObject(j, "omit", test->omit);
                   1302:        if (test->server_affinity != -1)
                   1303:            cJSON_AddNumberToObject(j, "server_affinity", test->server_affinity);
                   1304:        if (test->duration)
                   1305:            cJSON_AddNumberToObject(j, "time", test->duration);
                   1306:        if (test->settings->bytes)
                   1307:            cJSON_AddNumberToObject(j, "num", test->settings->bytes);
                   1308:        if (test->settings->blocks)
                   1309:            cJSON_AddNumberToObject(j, "blockcount", test->settings->blocks);
                   1310:        if (test->settings->mss)
                   1311:            cJSON_AddNumberToObject(j, "MSS", test->settings->mss);
                   1312:        if (test->no_delay)
                   1313:            cJSON_AddTrueToObject(j, "nodelay");
                   1314:        cJSON_AddNumberToObject(j, "parallel", test->num_streams);
                   1315:        if (test->reverse)
                   1316:            cJSON_AddTrueToObject(j, "reverse");
                   1317:        if (test->settings->socket_bufsize)
                   1318:            cJSON_AddNumberToObject(j, "window", test->settings->socket_bufsize);
                   1319:        if (test->settings->blksize)
                   1320:            cJSON_AddNumberToObject(j, "len", test->settings->blksize);
                   1321:        if (test->settings->rate)
                   1322:            cJSON_AddNumberToObject(j, "bandwidth", test->settings->rate);
                   1323:        if (test->settings->burst)
                   1324:            cJSON_AddNumberToObject(j, "burst", test->settings->burst);
                   1325:        if (test->settings->tos)
                   1326:            cJSON_AddNumberToObject(j, "TOS", test->settings->tos);
                   1327:        if (test->settings->flowlabel)
                   1328:            cJSON_AddNumberToObject(j, "flowlabel", test->settings->flowlabel);
                   1329:        if (test->title)
                   1330:            cJSON_AddStringToObject(j, "title", test->title);
                   1331:        if (test->congestion)
                   1332:            cJSON_AddStringToObject(j, "congestion", test->congestion);
                   1333:        if (test->get_server_output)
                   1334:            cJSON_AddNumberToObject(j, "get_server_output", iperf_get_test_get_server_output(test));
                   1335:        if (test->udp_counters_64bit)
                   1336:            cJSON_AddNumberToObject(j, "udp_counters_64bit", iperf_get_test_udp_counters_64bit(test));
                   1337:        if (test->no_fq_socket_pacing)
                   1338:            cJSON_AddNumberToObject(j, "no_fq_socket_pacing", iperf_get_no_fq_socket_pacing(test));
                   1339: 
                   1340:        cJSON_AddStringToObject(j, "client_version", IPERF_VERSION);
                   1341: 
                   1342:        if (test->debug) {
                   1343:            printf("send_parameters:\n%s\n", cJSON_Print(j));
                   1344:        }
                   1345: 
                   1346:        if (JSON_write(test->ctrl_sck, j) < 0) {
                   1347:            i_errno = IESENDPARAMS;
                   1348:            r = -1;
                   1349:        }
                   1350:        cJSON_Delete(j);
                   1351:     }
                   1352:     return r;
                   1353: }
                   1354: 
                   1355: /*************************************************************/
                   1356: 
                   1357: static int
                   1358: get_parameters(struct iperf_test *test)
                   1359: {
                   1360:     int r = 0;
                   1361:     cJSON *j;
                   1362:     cJSON *j_p;
                   1363: 
                   1364:     j = JSON_read(test->ctrl_sck);
                   1365:     if (j == NULL) {
                   1366:        i_errno = IERECVPARAMS;
                   1367:         r = -1;
                   1368:     } else {
                   1369:        if (test->debug) {
                   1370:            printf("get_parameters:\n%s\n", cJSON_Print(j));
                   1371:        }
                   1372: 
                   1373:        if ((j_p = cJSON_GetObjectItem(j, "tcp")) != NULL)
                   1374:            set_protocol(test, Ptcp);
                   1375:        if ((j_p = cJSON_GetObjectItem(j, "udp")) != NULL)
                   1376:            set_protocol(test, Pudp);
                   1377:         if ((j_p = cJSON_GetObjectItem(j, "sctp")) != NULL)
                   1378:             set_protocol(test, Psctp);
                   1379:        if ((j_p = cJSON_GetObjectItem(j, "omit")) != NULL)
                   1380:            test->omit = j_p->valueint;
                   1381:        if ((j_p = cJSON_GetObjectItem(j, "server_affinity")) != NULL)
                   1382:            test->server_affinity = j_p->valueint;
                   1383:        if ((j_p = cJSON_GetObjectItem(j, "time")) != NULL)
                   1384:            test->duration = j_p->valueint;
                   1385:        if ((j_p = cJSON_GetObjectItem(j, "num")) != NULL)
                   1386:            test->settings->bytes = j_p->valueint;
                   1387:        if ((j_p = cJSON_GetObjectItem(j, "blockcount")) != NULL)
                   1388:            test->settings->blocks = j_p->valueint;
                   1389:        if ((j_p = cJSON_GetObjectItem(j, "MSS")) != NULL)
                   1390:            test->settings->mss = j_p->valueint;
                   1391:        if ((j_p = cJSON_GetObjectItem(j, "nodelay")) != NULL)
                   1392:            test->no_delay = 1;
                   1393:        if ((j_p = cJSON_GetObjectItem(j, "parallel")) != NULL)
                   1394:            test->num_streams = j_p->valueint;
                   1395:        if ((j_p = cJSON_GetObjectItem(j, "reverse")) != NULL)
                   1396:            iperf_set_test_reverse(test, 1);
                   1397:        if ((j_p = cJSON_GetObjectItem(j, "window")) != NULL)
                   1398:            test->settings->socket_bufsize = j_p->valueint;
                   1399:        if ((j_p = cJSON_GetObjectItem(j, "len")) != NULL)
                   1400:            test->settings->blksize = j_p->valueint;
                   1401:        if ((j_p = cJSON_GetObjectItem(j, "bandwidth")) != NULL)
                   1402:            test->settings->rate = j_p->valueint;
                   1403:        if ((j_p = cJSON_GetObjectItem(j, "burst")) != NULL)
                   1404:            test->settings->burst = j_p->valueint;
                   1405:        if ((j_p = cJSON_GetObjectItem(j, "TOS")) != NULL)
                   1406:            test->settings->tos = j_p->valueint;
                   1407:        if ((j_p = cJSON_GetObjectItem(j, "flowlabel")) != NULL)
                   1408:            test->settings->flowlabel = j_p->valueint;
                   1409:        if ((j_p = cJSON_GetObjectItem(j, "title")) != NULL)
                   1410:            test->title = strdup(j_p->valuestring);
                   1411:        if ((j_p = cJSON_GetObjectItem(j, "congestion")) != NULL)
                   1412:            test->congestion = strdup(j_p->valuestring);
                   1413:        if ((j_p = cJSON_GetObjectItem(j, "get_server_output")) != NULL)
                   1414:            iperf_set_test_get_server_output(test, 1);
                   1415:        if ((j_p = cJSON_GetObjectItem(j, "udp_counters_64bit")) != NULL)
                   1416:            iperf_set_test_udp_counters_64bit(test, 1);
                   1417:        if ((j_p = cJSON_GetObjectItem(j, "no_fq_socket_pacing")) != NULL)
                   1418:            iperf_set_no_fq_socket_pacing(test, 1);
                   1419:        
                   1420:        if (test->sender && test->protocol->id == Ptcp && has_tcpinfo_retransmits())
                   1421:            test->sender_has_retransmits = 1;
                   1422:        cJSON_Delete(j);
                   1423:     }
                   1424:     return r;
                   1425: }
                   1426: 
                   1427: /*************************************************************/
                   1428: 
                   1429: static int
                   1430: send_results(struct iperf_test *test)
                   1431: {
                   1432:     int r = 0;
                   1433:     cJSON *j;
                   1434:     cJSON *j_streams;
                   1435:     struct iperf_stream *sp;
                   1436:     cJSON *j_stream;
                   1437:     int sender_has_retransmits;
                   1438:     iperf_size_t bytes_transferred;
                   1439:     int retransmits;
                   1440: 
                   1441:     j = cJSON_CreateObject();
                   1442:     if (j == NULL) {
                   1443:        i_errno = IEPACKAGERESULTS;
                   1444:        r = -1;
                   1445:     } else {
                   1446:        cJSON_AddNumberToObject(j, "cpu_util_total", test->cpu_util[0]);
                   1447:        cJSON_AddNumberToObject(j, "cpu_util_user", test->cpu_util[1]);
                   1448:        cJSON_AddNumberToObject(j, "cpu_util_system", test->cpu_util[2]);
                   1449:        if ( ! test->sender )
                   1450:            sender_has_retransmits = -1;
                   1451:        else
                   1452:            sender_has_retransmits = test->sender_has_retransmits;
                   1453:        cJSON_AddNumberToObject(j, "sender_has_retransmits", sender_has_retransmits);
                   1454: 
                   1455:        /* If on the server and sending server output, then do this */
                   1456:        if (test->role == 's' && test->get_server_output) {
                   1457:            if (test->json_output) {
                   1458:                /* Add JSON output */
                   1459:                cJSON_AddItemReferenceToObject(j, "server_output_json", test->json_top);
                   1460:            }
                   1461:            else {
                   1462:                /* Add textual output */
                   1463:                size_t buflen = 0;
                   1464: 
                   1465:                /* Figure out how much room we need to hold the complete output string */
                   1466:                struct iperf_textline *t;
                   1467:                TAILQ_FOREACH(t, &(test->server_output_list), textlineentries) {
                   1468:                    buflen += strlen(t->line);
                   1469:                }
                   1470: 
                   1471:                /* Allocate and build it up from the component lines */
                   1472:                char *output = calloc(buflen + 1, 1);
                   1473:                TAILQ_FOREACH(t, &(test->server_output_list), textlineentries) {
                   1474:                    strncat(output, t->line, buflen);
                   1475:                    buflen -= strlen(t->line);
                   1476:                }
                   1477: 
                   1478:                cJSON_AddStringToObject(j, "server_output_text", output);
                   1479:            }
                   1480:        }
                   1481: 
                   1482:        j_streams = cJSON_CreateArray();
                   1483:        if (j_streams == NULL) {
                   1484:            i_errno = IEPACKAGERESULTS;
                   1485:            r = -1;
                   1486:        } else {
                   1487:            cJSON_AddItemToObject(j, "streams", j_streams);
                   1488:            SLIST_FOREACH(sp, &test->streams, streams) {
                   1489:                j_stream = cJSON_CreateObject();
                   1490:                if (j_stream == NULL) {
                   1491:                    i_errno = IEPACKAGERESULTS;
                   1492:                    r = -1;
                   1493:                } else {
                   1494:                    cJSON_AddItemToArray(j_streams, j_stream);
                   1495:                    bytes_transferred = test->sender ? (sp->result->bytes_sent - sp->result->bytes_sent_omit) : sp->result->bytes_received;
                   1496:                    retransmits = (test->sender && test->sender_has_retransmits) ? sp->result->stream_retrans : -1;
                   1497:                    cJSON_AddNumberToObject(j_stream, "id", sp->id);
                   1498:                    cJSON_AddNumberToObject(j_stream, "bytes", bytes_transferred);
                   1499:                    cJSON_AddNumberToObject(j_stream, "retransmits", retransmits);
                   1500:                    cJSON_AddNumberToObject(j_stream, "jitter", sp->jitter);
                   1501:                    cJSON_AddNumberToObject(j_stream, "errors", sp->cnt_error);
                   1502:                    cJSON_AddNumberToObject(j_stream, "packets", sp->packet_count);
                   1503:                }
                   1504:            }
                   1505:            if (r == 0 && test->debug) {
                   1506:                printf("send_results\n%s\n", cJSON_Print(j));
                   1507:            }
                   1508:            if (r == 0 && JSON_write(test->ctrl_sck, j) < 0) {
                   1509:                i_errno = IESENDRESULTS;
                   1510:                r = -1;
                   1511:            }
                   1512:        }
                   1513:        cJSON_Delete(j);
                   1514:     }
                   1515:     return r;
                   1516: }
                   1517: 
                   1518: /*************************************************************/
                   1519: 
                   1520: static int
                   1521: get_results(struct iperf_test *test)
                   1522: {
                   1523:     int r = 0;
                   1524:     cJSON *j;
                   1525:     cJSON *j_cpu_util_total;
                   1526:     cJSON *j_cpu_util_user;
                   1527:     cJSON *j_cpu_util_system;
                   1528:     cJSON *j_sender_has_retransmits;
                   1529:     int result_has_retransmits;
                   1530:     cJSON *j_streams;
                   1531:     int n, i;
                   1532:     cJSON *j_stream;
                   1533:     cJSON *j_id;
                   1534:     cJSON *j_bytes;
                   1535:     cJSON *j_retransmits;
                   1536:     cJSON *j_jitter;
                   1537:     cJSON *j_errors;
                   1538:     cJSON *j_packets;
                   1539:     cJSON *j_server_output;
                   1540:     int sid, cerror, pcount;
                   1541:     double jitter;
                   1542:     iperf_size_t bytes_transferred;
                   1543:     int retransmits;
                   1544:     struct iperf_stream *sp;
                   1545: 
                   1546:     j = JSON_read(test->ctrl_sck);
                   1547:     if (j == NULL) {
                   1548:        i_errno = IERECVRESULTS;
                   1549:         r = -1;
                   1550:     } else {
                   1551:        j_cpu_util_total = cJSON_GetObjectItem(j, "cpu_util_total");
                   1552:        j_cpu_util_user = cJSON_GetObjectItem(j, "cpu_util_user");
                   1553:        j_cpu_util_system = cJSON_GetObjectItem(j, "cpu_util_system");
                   1554:        j_sender_has_retransmits = cJSON_GetObjectItem(j, "sender_has_retransmits");
                   1555:        if (j_cpu_util_total == NULL || j_cpu_util_user == NULL || j_cpu_util_system == NULL || j_sender_has_retransmits == NULL) {
                   1556:            i_errno = IERECVRESULTS;
                   1557:            r = -1;
                   1558:        } else {
                   1559:            if (test->debug) {
                   1560:                printf("get_results\n%s\n", cJSON_Print(j));
                   1561:            }
                   1562: 
                   1563:            test->remote_cpu_util[0] = j_cpu_util_total->valuedouble;
                   1564:            test->remote_cpu_util[1] = j_cpu_util_user->valuedouble;
                   1565:            test->remote_cpu_util[2] = j_cpu_util_system->valuedouble;
                   1566:            result_has_retransmits = j_sender_has_retransmits->valueint;
                   1567:            if (! test->sender)
                   1568:                test->sender_has_retransmits = result_has_retransmits;
                   1569:            j_streams = cJSON_GetObjectItem(j, "streams");
                   1570:            if (j_streams == NULL) {
                   1571:                i_errno = IERECVRESULTS;
                   1572:                r = -1;
                   1573:            } else {
                   1574:                n = cJSON_GetArraySize(j_streams);
                   1575:                for (i=0; i<n; ++i) {
                   1576:                    j_stream = cJSON_GetArrayItem(j_streams, i);
                   1577:                    if (j_stream == NULL) {
                   1578:                        i_errno = IERECVRESULTS;
                   1579:                        r = -1;
                   1580:                    } else {
                   1581:                        j_id = cJSON_GetObjectItem(j_stream, "id");
                   1582:                        j_bytes = cJSON_GetObjectItem(j_stream, "bytes");
                   1583:                        j_retransmits = cJSON_GetObjectItem(j_stream, "retransmits");
                   1584:                        j_jitter = cJSON_GetObjectItem(j_stream, "jitter");
                   1585:                        j_errors = cJSON_GetObjectItem(j_stream, "errors");
                   1586:                        j_packets = cJSON_GetObjectItem(j_stream, "packets");
                   1587:                        if (j_id == NULL || j_bytes == NULL || j_retransmits == NULL || j_jitter == NULL || j_errors == NULL || j_packets == NULL) {
                   1588:                            i_errno = IERECVRESULTS;
                   1589:                            r = -1;
                   1590:                        } else {
                   1591:                            sid = j_id->valueint;
                   1592:                            bytes_transferred = j_bytes->valueint;
                   1593:                            retransmits = j_retransmits->valueint;
                   1594:                            jitter = j_jitter->valuedouble;
                   1595:                            cerror = j_errors->valueint;
                   1596:                            pcount = j_packets->valueint;
                   1597:                            SLIST_FOREACH(sp, &test->streams, streams)
                   1598:                                if (sp->id == sid) break;
                   1599:                            if (sp == NULL) {
                   1600:                                i_errno = IESTREAMID;
                   1601:                                r = -1;
                   1602:                            } else {
                   1603:                                if (test->sender) {
                   1604:                                    sp->jitter = jitter;
                   1605:                                    sp->cnt_error = cerror;
                   1606:                                    sp->packet_count = pcount;
                   1607:                                    sp->result->bytes_received = bytes_transferred;
                   1608:                                } else {
                   1609:                                    sp->result->bytes_sent = bytes_transferred;
                   1610:                                    sp->result->stream_retrans = retransmits;
                   1611:                                }
                   1612:                            }
                   1613:                        }
                   1614:                    }
                   1615:                }
                   1616:                /*
                   1617:                 * If we're the client and we're supposed to get remote results,
                   1618:                 * look them up and process accordingly.
                   1619:                 */
                   1620:                if (test->role == 'c' && iperf_get_test_get_server_output(test)) {
                   1621:                    /* Look for JSON.  If we find it, grab the object so it doesn't get deleted. */
                   1622:                    j_server_output = cJSON_DetachItemFromObject(j, "server_output_json");
                   1623:                    if (j_server_output != NULL) {
                   1624:                        test->json_server_output = j_server_output;
                   1625:                    }
                   1626:                    else {
                   1627:                        /* No JSON, look for textual output.  Make a copy of the text for later. */
                   1628:                        j_server_output = cJSON_GetObjectItem(j, "server_output_text");
                   1629:                        if (j_server_output != NULL) {
                   1630:                            test->server_output_text = strdup(j_server_output->valuestring);
                   1631:                        }
                   1632:                    }
                   1633:                }
                   1634:            }
                   1635:        }
                   1636:        cJSON_Delete(j);
                   1637:     }
                   1638:     return r;
                   1639: }
                   1640: 
                   1641: /*************************************************************/
                   1642: 
                   1643: static int
                   1644: JSON_write(int fd, cJSON *json)
                   1645: {
                   1646:     uint32_t hsize, nsize;
                   1647:     char *str;
                   1648:     int r = 0;
                   1649: 
                   1650:     str = cJSON_PrintUnformatted(json);
                   1651:     if (str == NULL)
                   1652:        r = -1;
                   1653:     else {
                   1654:        hsize = strlen(str);
                   1655:        nsize = htonl(hsize);
                   1656:        if (Nwrite(fd, (char*) &nsize, sizeof(nsize), Ptcp) < 0)
                   1657:            r = -1;
                   1658:        else {
                   1659:            if (Nwrite(fd, str, hsize, Ptcp) < 0)
                   1660:                r = -1;
                   1661:        }
                   1662:        free(str);
                   1663:     }
                   1664:     return r;
                   1665: }
                   1666: 
                   1667: /*************************************************************/
                   1668: 
                   1669: static cJSON *
                   1670: JSON_read(int fd)
                   1671: {
                   1672:     uint32_t hsize, nsize;
                   1673:     char *str;
                   1674:     cJSON *json = NULL;
                   1675:     int rc;
                   1676: 
                   1677:     /*
                   1678:      * Read a four-byte integer, which is the length of the JSON to follow.
                   1679:      * Then read the JSON into a buffer and parse it.  Return a parsed JSON
                   1680:      * structure, NULL if there was an error.
                   1681:      */
                   1682:     if (Nread(fd, (char*) &nsize, sizeof(nsize), Ptcp) >= 0) {
                   1683:        hsize = ntohl(nsize);
                   1684:        /* Allocate a buffer to hold the JSON */
                   1685:        str = (char *) calloc(sizeof(char), hsize+1);   /* +1 for trailing null */
                   1686:        if (str != NULL) {
                   1687:            rc = Nread(fd, str, hsize, Ptcp);
                   1688:            if (rc >= 0) {
                   1689:                /*
                   1690:                 * We should be reading in the number of bytes corresponding to the
                   1691:                 * length in that 4-byte integer.  If we don't the socket might have
                   1692:                 * prematurely closed.  Only do the JSON parsing if we got the
                   1693:                 * correct number of bytes.
                   1694:                 */
                   1695:                if (rc == hsize) {
                   1696:                    json = cJSON_Parse(str);
                   1697:                }
                   1698:                else {
                   1699:                    printf("WARNING:  Size of data read does not correspond to offered length\n");
                   1700:                }
                   1701:            }
                   1702:        }
                   1703:        free(str);
                   1704:     }
                   1705:     return json;
                   1706: }
                   1707: 
                   1708: /*************************************************************/
                   1709: /**
                   1710:  * add_to_interval_list -- adds new interval to the interval_list
                   1711:  */
                   1712: 
                   1713: void
                   1714: add_to_interval_list(struct iperf_stream_result * rp, struct iperf_interval_results * new)
                   1715: {
                   1716:     struct iperf_interval_results *irp;
                   1717: 
                   1718:     irp = (struct iperf_interval_results *) malloc(sizeof(struct iperf_interval_results));
                   1719:     memcpy(irp, new, sizeof(struct iperf_interval_results));
                   1720:     TAILQ_INSERT_TAIL(&rp->interval_results, irp, irlistentries);
                   1721: }
                   1722: 
                   1723: 
                   1724: /************************************************************/
                   1725: 
                   1726: /**
                   1727:  * connect_msg -- displays connection message
                   1728:  * denoting sender/receiver details
                   1729:  *
                   1730:  */
                   1731: 
                   1732: void
                   1733: connect_msg(struct iperf_stream *sp)
                   1734: {
                   1735:     char ipl[INET6_ADDRSTRLEN], ipr[INET6_ADDRSTRLEN];
                   1736:     int lport, rport;
                   1737: 
                   1738:     if (getsockdomain(sp->socket) == AF_INET) {
                   1739:         inet_ntop(AF_INET, (void *) &((struct sockaddr_in *) &sp->local_addr)->sin_addr, ipl, sizeof(ipl));
                   1740:        mapped_v4_to_regular_v4(ipl);
                   1741:         inet_ntop(AF_INET, (void *) &((struct sockaddr_in *) &sp->remote_addr)->sin_addr, ipr, sizeof(ipr));
                   1742:        mapped_v4_to_regular_v4(ipr);
                   1743:         lport = ntohs(((struct sockaddr_in *) &sp->local_addr)->sin_port);
                   1744:         rport = ntohs(((struct sockaddr_in *) &sp->remote_addr)->sin_port);
                   1745:     } else {
                   1746:         inet_ntop(AF_INET6, (void *) &((struct sockaddr_in6 *) &sp->local_addr)->sin6_addr, ipl, sizeof(ipl));
                   1747:        mapped_v4_to_regular_v4(ipl);
                   1748:         inet_ntop(AF_INET6, (void *) &((struct sockaddr_in6 *) &sp->remote_addr)->sin6_addr, ipr, sizeof(ipr));
                   1749:        mapped_v4_to_regular_v4(ipr);
                   1750:         lport = ntohs(((struct sockaddr_in6 *) &sp->local_addr)->sin6_port);
                   1751:         rport = ntohs(((struct sockaddr_in6 *) &sp->remote_addr)->sin6_port);
                   1752:     }
                   1753: 
                   1754:     if (sp->test->json_output)
                   1755:         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));
                   1756:     else
                   1757:        iprintf(sp->test, report_connected, sp->socket, ipl, lport, ipr, rport);
                   1758: }
                   1759: 
                   1760: 
                   1761: /**************************************************************************/
                   1762: 
                   1763: struct iperf_test *
                   1764: iperf_new_test()
                   1765: {
                   1766:     struct iperf_test *test;
                   1767: 
                   1768:     test = (struct iperf_test *) malloc(sizeof(struct iperf_test));
                   1769:     if (!test) {
                   1770:         i_errno = IENEWTEST;
                   1771:         return NULL;
                   1772:     }
                   1773:     /* initialize everything to zero */
                   1774:     memset(test, 0, sizeof(struct iperf_test));
                   1775: 
                   1776:     test->settings = (struct iperf_settings *) malloc(sizeof(struct iperf_settings));
                   1777:     if (!test->settings) {
                   1778:         free(test);
                   1779:        i_errno = IENEWTEST;
                   1780:        return NULL;
                   1781:     }
                   1782:     memset(test->settings, 0, sizeof(struct iperf_settings));
                   1783: 
                   1784:     /* By default all output goes to stdout */
                   1785:     test->outfile = stdout;
                   1786: 
                   1787:     return test;
                   1788: }
                   1789: 
                   1790: /**************************************************************************/
                   1791: 
                   1792: struct protocol *
                   1793: protocol_new(void)
                   1794: {
                   1795:     struct protocol *proto;
                   1796: 
                   1797:     proto = malloc(sizeof(struct protocol));
                   1798:     if(!proto) {
                   1799:         return NULL;
                   1800:     }
                   1801:     memset(proto, 0, sizeof(struct protocol));
                   1802: 
                   1803:     return proto;
                   1804: }
                   1805: 
                   1806: void
                   1807: protocol_free(struct protocol *proto)
                   1808: {
                   1809:     free(proto); 
                   1810: }
                   1811: 
                   1812: /**************************************************************************/
                   1813: int
                   1814: iperf_defaults(struct iperf_test *testp)
                   1815: {
                   1816:     struct protocol *tcp, *udp;
                   1817: #if defined(HAVE_SCTP)
                   1818:     struct protocol *sctp;
                   1819: #endif /* HAVE_SCTP */
                   1820: 
                   1821:     testp->omit = OMIT;
                   1822:     testp->duration = DURATION;
                   1823:     testp->diskfile_name = (char*) 0;
                   1824:     testp->affinity = -1;
                   1825:     testp->server_affinity = -1;
                   1826:     TAILQ_INIT(&testp->xbind_addrs);
                   1827: #if defined(HAVE_CPUSET_SETAFFINITY)
                   1828:     CPU_ZERO(&testp->cpumask);
                   1829: #endif /* HAVE_CPUSET_SETAFFINITY */
                   1830:     testp->title = NULL;
                   1831:     testp->congestion = NULL;
                   1832:     testp->server_port = PORT;
                   1833:     testp->ctrl_sck = -1;
                   1834:     testp->prot_listener = -1;
                   1835: 
                   1836:     testp->stats_callback = iperf_stats_callback;
                   1837:     testp->reporter_callback = iperf_reporter_callback;
                   1838: 
                   1839:     testp->stats_interval = testp->reporter_interval = 1;
                   1840:     testp->num_streams = 1;
                   1841: 
                   1842:     testp->settings->domain = AF_UNSPEC;
                   1843:     testp->settings->unit_format = 'a';
                   1844:     testp->settings->socket_bufsize = 0;    /* use autotuning */
                   1845:     testp->settings->blksize = DEFAULT_TCP_BLKSIZE;
                   1846:     testp->settings->rate = 0;
                   1847:     testp->settings->burst = 0;
                   1848:     testp->settings->mss = 0;
                   1849:     testp->settings->bytes = 0;
                   1850:     testp->settings->blocks = 0;
                   1851:     memset(testp->cookie, 0, COOKIE_SIZE);
                   1852: 
                   1853:     testp->multisend = 10;     /* arbitrary */
                   1854: 
                   1855:     /* Set up protocol list */
                   1856:     SLIST_INIT(&testp->streams);
                   1857:     SLIST_INIT(&testp->protocols);
                   1858: 
                   1859:     tcp = protocol_new();
                   1860:     if (!tcp)
                   1861:         return -1;
                   1862: 
                   1863:     tcp->id = Ptcp;
                   1864:     tcp->name = "TCP";
                   1865:     tcp->accept = iperf_tcp_accept;
                   1866:     tcp->listen = iperf_tcp_listen;
                   1867:     tcp->connect = iperf_tcp_connect;
                   1868:     tcp->send = iperf_tcp_send;
                   1869:     tcp->recv = iperf_tcp_recv;
                   1870:     tcp->init = NULL;
                   1871:     SLIST_INSERT_HEAD(&testp->protocols, tcp, protocols);
                   1872: 
                   1873:     udp = protocol_new();
                   1874:     if (!udp) {
                   1875:         protocol_free(tcp);
                   1876:         return -1;
                   1877:     }
                   1878: 
                   1879:     udp->id = Pudp;
                   1880:     udp->name = "UDP";
                   1881:     udp->accept = iperf_udp_accept;
                   1882:     udp->listen = iperf_udp_listen;
                   1883:     udp->connect = iperf_udp_connect;
                   1884:     udp->send = iperf_udp_send;
                   1885:     udp->recv = iperf_udp_recv;
                   1886:     udp->init = iperf_udp_init;
                   1887:     SLIST_INSERT_AFTER(tcp, udp, protocols);
                   1888: 
                   1889:     set_protocol(testp, Ptcp);
                   1890: 
                   1891: #if defined(HAVE_SCTP)
                   1892:     sctp = protocol_new();
                   1893:     if (!sctp) {
                   1894:         protocol_free(tcp);
                   1895:         protocol_free(udp);
                   1896:         return -1;
                   1897:     }
                   1898: 
                   1899:     sctp->id = Psctp;
                   1900:     sctp->name = "SCTP";
                   1901:     sctp->accept = iperf_sctp_accept;
                   1902:     sctp->listen = iperf_sctp_listen;
                   1903:     sctp->connect = iperf_sctp_connect;
                   1904:     sctp->send = iperf_sctp_send;
                   1905:     sctp->recv = iperf_sctp_recv;
                   1906:     sctp->init = iperf_sctp_init;
                   1907: 
                   1908:     SLIST_INSERT_AFTER(udp, sctp, protocols);
                   1909: #endif /* HAVE_SCTP */
                   1910: 
                   1911:     testp->on_new_stream = iperf_on_new_stream;
                   1912:     testp->on_test_start = iperf_on_test_start;
                   1913:     testp->on_connect = iperf_on_connect;
                   1914:     testp->on_test_finish = iperf_on_test_finish;
                   1915: 
                   1916:     TAILQ_INIT(&testp->server_output_list);
                   1917: 
                   1918:     return 0;
                   1919: }
                   1920: 
                   1921: 
                   1922: /**************************************************************************/
                   1923: void
                   1924: iperf_free_test(struct iperf_test *test)
                   1925: {
                   1926:     struct protocol *prot;
                   1927:     struct iperf_stream *sp;
                   1928: 
                   1929:     /* Free streams */
                   1930:     while (!SLIST_EMPTY(&test->streams)) {
                   1931:         sp = SLIST_FIRST(&test->streams);
                   1932:         SLIST_REMOVE_HEAD(&test->streams, streams);
                   1933:         iperf_free_stream(sp);
                   1934:     }
                   1935: 
                   1936:     if (test->server_hostname)
                   1937:        free(test->server_hostname);
                   1938:     if (test->tmp_template)
                   1939:        free(test->tmp_template);
                   1940:     if (test->bind_address)
                   1941:        free(test->bind_address);
                   1942:     if (!TAILQ_EMPTY(&test->xbind_addrs)) {
                   1943:         struct xbind_entry *xbe;
                   1944: 
                   1945:         while (!TAILQ_EMPTY(&test->xbind_addrs)) {
                   1946:             xbe = TAILQ_FIRST(&test->xbind_addrs);
                   1947:             TAILQ_REMOVE(&test->xbind_addrs, xbe, link);
                   1948:             if (xbe->ai)
                   1949:                 freeaddrinfo(xbe->ai);
                   1950:             free(xbe->name);
                   1951:             free(xbe);
                   1952:         }
                   1953:     }
                   1954:     if (test->settings)
                   1955:     free(test->settings);
                   1956:     if (test->title)
                   1957:        free(test->title);
                   1958:     if (test->congestion)
                   1959:        free(test->congestion);
                   1960:     if (test->omit_timer != NULL)
                   1961:        tmr_cancel(test->omit_timer);
                   1962:     if (test->timer != NULL)
                   1963:        tmr_cancel(test->timer);
                   1964:     if (test->stats_timer != NULL)
                   1965:        tmr_cancel(test->stats_timer);
                   1966:     if (test->reporter_timer != NULL)
                   1967:        tmr_cancel(test->reporter_timer);
                   1968: 
                   1969:     /* Free protocol list */
                   1970:     while (!SLIST_EMPTY(&test->protocols)) {
                   1971:         prot = SLIST_FIRST(&test->protocols);
                   1972:         SLIST_REMOVE_HEAD(&test->protocols, protocols);        
                   1973:         free(prot);
                   1974:     }
                   1975: 
                   1976:     if (test->server_output_text) {
                   1977:        free(test->server_output_text);
                   1978:        test->server_output_text = NULL;
                   1979:     }
                   1980: 
                   1981:     if (test->json_output_string) {
                   1982:        free(test->json_output_string);
                   1983:        test->json_output_string = NULL;
                   1984:     }
                   1985: 
                   1986:     /* Free output line buffers, if any (on the server only) */
                   1987:     struct iperf_textline *t;
                   1988:     while (!TAILQ_EMPTY(&test->server_output_list)) {
                   1989:        t = TAILQ_FIRST(&test->server_output_list);
                   1990:        TAILQ_REMOVE(&test->server_output_list, t, textlineentries);
                   1991:        free(t->line);
                   1992:        free(t);
                   1993:     }
                   1994: 
                   1995:     /* sctp_bindx: do not free the arguments, only the resolver results */
                   1996:     if (!TAILQ_EMPTY(&test->xbind_addrs)) {
                   1997:         struct xbind_entry *xbe;
                   1998: 
                   1999:         TAILQ_FOREACH(xbe, &test->xbind_addrs, link) {
                   2000:             if (xbe->ai) {
                   2001:                 freeaddrinfo(xbe->ai);
                   2002:                 xbe->ai = NULL;
                   2003:             }
                   2004:         }
                   2005:     }
                   2006: 
                   2007:     /* XXX: Why are we setting these values to NULL? */
                   2008:     // test->streams = NULL;
                   2009:     test->stats_callback = NULL;
                   2010:     test->reporter_callback = NULL;
                   2011:     free(test);
                   2012: }
                   2013: 
                   2014: 
                   2015: void
                   2016: iperf_reset_test(struct iperf_test *test)
                   2017: {
                   2018:     struct iperf_stream *sp;
                   2019: 
                   2020:     /* Free streams */
                   2021:     while (!SLIST_EMPTY(&test->streams)) {
                   2022:         sp = SLIST_FIRST(&test->streams);
                   2023:         SLIST_REMOVE_HEAD(&test->streams, streams);
                   2024:         iperf_free_stream(sp);
                   2025:     }
                   2026:     if (test->omit_timer != NULL) {
                   2027:        tmr_cancel(test->omit_timer);
                   2028:        test->omit_timer = NULL;
                   2029:     }
                   2030:     if (test->timer != NULL) {
                   2031:        tmr_cancel(test->timer);
                   2032:        test->timer = NULL;
                   2033:     }
                   2034:     if (test->stats_timer != NULL) {
                   2035:        tmr_cancel(test->stats_timer);
                   2036:        test->stats_timer = NULL;
                   2037:     }
                   2038:     if (test->reporter_timer != NULL) {
                   2039:        tmr_cancel(test->reporter_timer);
                   2040:        test->reporter_timer = NULL;
                   2041:     }
                   2042:     test->done = 0;
                   2043: 
                   2044:     SLIST_INIT(&test->streams);
                   2045: 
                   2046:     test->role = 's';
                   2047:     test->sender = 0;
                   2048:     test->sender_has_retransmits = 0;
                   2049:     set_protocol(test, Ptcp);
                   2050:     test->omit = OMIT;
                   2051:     test->duration = DURATION;
                   2052:     test->server_affinity = -1;
                   2053: #if defined(HAVE_CPUSET_SETAFFINITY)
                   2054:     CPU_ZERO(&test->cpumask);
                   2055: #endif /* HAVE_CPUSET_SETAFFINITY */
                   2056:     test->state = 0;
                   2057:     
                   2058:     test->ctrl_sck = -1;
                   2059:     test->prot_listener = -1;
                   2060: 
                   2061:     test->bytes_sent = 0;
                   2062:     test->blocks_sent = 0;
                   2063: 
                   2064:     test->reverse = 0;
                   2065:     test->no_delay = 0;
                   2066: 
                   2067:     FD_ZERO(&test->read_set);
                   2068:     FD_ZERO(&test->write_set);
                   2069:     
                   2070:     test->num_streams = 1;
                   2071:     test->settings->socket_bufsize = 0;
                   2072:     test->settings->blksize = DEFAULT_TCP_BLKSIZE;
                   2073:     test->settings->rate = 0;
                   2074:     test->settings->burst = 0;
                   2075:     test->settings->mss = 0;
                   2076:     memset(test->cookie, 0, COOKIE_SIZE);
                   2077:     test->multisend = 10;      /* arbitrary */
                   2078:     test->udp_counters_64bit = 0;
                   2079: 
                   2080:     /* Free output line buffers, if any (on the server only) */
                   2081:     struct iperf_textline *t;
                   2082:     while (!TAILQ_EMPTY(&test->server_output_list)) {
                   2083:        t = TAILQ_FIRST(&test->server_output_list);
                   2084:        TAILQ_REMOVE(&test->server_output_list, t, textlineentries);
                   2085:        free(t->line);
                   2086:        free(t);
                   2087:     }
                   2088: }
                   2089: 
                   2090: 
                   2091: /* Reset all of a test's stats back to zero.  Called when the omitting
                   2092: ** period is over.
                   2093: */
                   2094: void
                   2095: iperf_reset_stats(struct iperf_test *test)
                   2096: {
                   2097:     struct timeval now;
                   2098:     struct iperf_stream *sp;
                   2099:     struct iperf_stream_result *rp;
                   2100: 
                   2101:     test->bytes_sent = 0;
                   2102:     test->blocks_sent = 0;
                   2103:     gettimeofday(&now, NULL);
                   2104:     SLIST_FOREACH(sp, &test->streams, streams) {
                   2105:        sp->omitted_packet_count = sp->packet_count;
                   2106:         sp->omitted_cnt_error = sp->cnt_error;
                   2107:         sp->omitted_outoforder_packets = sp->outoforder_packets;
                   2108:        sp->jitter = 0;
                   2109:        rp = sp->result;
                   2110:         rp->bytes_sent_omit = rp->bytes_sent;
                   2111:         rp->bytes_received = 0;
                   2112:         rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;
                   2113:        if (test->sender && test->sender_has_retransmits) {
                   2114:            struct iperf_interval_results ir; /* temporary results structure */
                   2115:            save_tcpinfo(sp, &ir);
                   2116:            rp->stream_prev_total_retrans = get_total_retransmits(&ir);
                   2117:        }
                   2118:        rp->stream_retrans = 0;
                   2119:        rp->start_time = now;
                   2120:     }
                   2121: }
                   2122: 
                   2123: 
                   2124: /**************************************************************************/
                   2125: 
                   2126: /**
                   2127:  * Gather statistics during a test.
                   2128:  * This function works for both the client and server side.
                   2129:  */
                   2130: void
                   2131: iperf_stats_callback(struct iperf_test *test)
                   2132: {
                   2133:     struct iperf_stream *sp;
                   2134:     struct iperf_stream_result *rp = NULL;
                   2135:     struct iperf_interval_results *irp, temp;
                   2136: 
                   2137:     temp.omitted = test->omitting;
                   2138:     SLIST_FOREACH(sp, &test->streams, streams) {
                   2139:         rp = sp->result;
                   2140: 
                   2141:        temp.bytes_transferred = test->sender ? rp->bytes_sent_this_interval : rp->bytes_received_this_interval;
                   2142:      
                   2143:        irp = TAILQ_LAST(&rp->interval_results, irlisthead);
                   2144:         /* result->end_time contains timestamp of previous interval */
                   2145:         if ( irp != NULL ) /* not the 1st interval */
                   2146:             memcpy(&temp.interval_start_time, &rp->end_time, sizeof(struct timeval));
                   2147:         else /* or use timestamp from beginning */
                   2148:             memcpy(&temp.interval_start_time, &rp->start_time, sizeof(struct timeval));
                   2149:         /* now save time of end of this interval */
                   2150:         gettimeofday(&rp->end_time, NULL);
                   2151:         memcpy(&temp.interval_end_time, &rp->end_time, sizeof(struct timeval));
                   2152:         temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time);
                   2153:         //temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time);
                   2154:        if (test->protocol->id == Ptcp) {
                   2155:            if ( has_tcpinfo()) {
                   2156:                save_tcpinfo(sp, &temp);
                   2157:                if (test->sender && test->sender_has_retransmits) {
                   2158:                    long total_retrans = get_total_retransmits(&temp);
                   2159:                    temp.interval_retrans = total_retrans - rp->stream_prev_total_retrans;
                   2160:                    rp->stream_retrans += temp.interval_retrans;
                   2161:                    rp->stream_prev_total_retrans = total_retrans;
                   2162: 
                   2163:                    temp.snd_cwnd = get_snd_cwnd(&temp);
                   2164:                    if (temp.snd_cwnd > rp->stream_max_snd_cwnd) {
                   2165:                        rp->stream_max_snd_cwnd = temp.snd_cwnd;
                   2166:                    }
                   2167:                    
                   2168:                    temp.rtt = get_rtt(&temp);
                   2169:                    if (temp.rtt > rp->stream_max_rtt) {
                   2170:                        rp->stream_max_rtt = temp.rtt;
                   2171:                    }
                   2172:                    if (rp->stream_min_rtt == 0 ||
                   2173:                        temp.rtt < rp->stream_min_rtt) {
                   2174:                        rp->stream_min_rtt = temp.rtt;
                   2175:                    }
                   2176:                    rp->stream_sum_rtt += temp.rtt;
                   2177:                    rp->stream_count_rtt++;
                   2178:                }
                   2179:            }
                   2180:        } else {
                   2181:            if (irp == NULL) {
                   2182:                temp.interval_packet_count = sp->packet_count;
                   2183:                temp.interval_outoforder_packets = sp->outoforder_packets;
                   2184:                temp.interval_cnt_error = sp->cnt_error;
                   2185:            } else {
                   2186:                temp.interval_packet_count = sp->packet_count - irp->packet_count;
                   2187:                temp.interval_outoforder_packets = sp->outoforder_packets - irp->outoforder_packets;
                   2188:                temp.interval_cnt_error = sp->cnt_error - irp->cnt_error;
                   2189:            }
                   2190:            temp.packet_count = sp->packet_count;
                   2191:            temp.jitter = sp->jitter;
                   2192:            temp.outoforder_packets = sp->outoforder_packets;
                   2193:            temp.cnt_error = sp->cnt_error;
                   2194:        }
                   2195:         add_to_interval_list(rp, &temp);
                   2196:         rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;
                   2197:     }
                   2198: }
                   2199: 
                   2200: /**
                   2201:  * Print intermediate results during a test (interval report).
                   2202:  * Uses print_interval_results to print the results for each stream,
                   2203:  * then prints an interval summary for all streams in this
                   2204:  * interval.
                   2205:  */
                   2206: static void
                   2207: iperf_print_intermediate(struct iperf_test *test)
                   2208: {
                   2209:     char ubuf[UNIT_LEN];
                   2210:     char nbuf[UNIT_LEN];
                   2211:     struct iperf_stream *sp = NULL;
                   2212:     struct iperf_interval_results *irp;
                   2213:     iperf_size_t bytes = 0;
                   2214:     double bandwidth;
                   2215:     int retransmits = 0;
                   2216:     double start_time, end_time;
                   2217:     cJSON *json_interval;
                   2218:     cJSON *json_interval_streams;
                   2219:     int total_packets = 0, lost_packets = 0;
                   2220:     double avg_jitter = 0.0, lost_percent;
                   2221: 
                   2222:     if (test->json_output) {
                   2223:         json_interval = cJSON_CreateObject();
                   2224:        if (json_interval == NULL)
                   2225:            return;
                   2226:        cJSON_AddItemToArray(test->json_intervals, json_interval);
                   2227:         json_interval_streams = cJSON_CreateArray();
                   2228:        if (json_interval_streams == NULL)
                   2229:            return;
                   2230:        cJSON_AddItemToObject(json_interval, "streams", json_interval_streams);
                   2231:     } else {
                   2232:         json_interval = NULL;
                   2233:         json_interval_streams = NULL;
                   2234:     }
                   2235: 
                   2236:     SLIST_FOREACH(sp, &test->streams, streams) {
                   2237:         print_interval_results(test, sp, json_interval_streams);
                   2238:        /* sum up all streams */
                   2239:        irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);
                   2240:        if (irp == NULL) {
                   2241:            iperf_err(test, "iperf_print_intermediate error: interval_results is NULL");
                   2242:            return;
                   2243:        }
                   2244:         bytes += irp->bytes_transferred;
                   2245:        if (test->protocol->id == Ptcp) {
                   2246:            if (test->sender && test->sender_has_retransmits) {
                   2247:                retransmits += irp->interval_retrans;
                   2248:            }
                   2249:        } else {
                   2250:             total_packets += irp->interval_packet_count;
                   2251:             lost_packets += irp->interval_cnt_error;
                   2252:             avg_jitter += irp->jitter;
                   2253:        }
                   2254:     }
                   2255: 
                   2256:     /* next build string with sum of all streams */
                   2257:     if (test->num_streams > 1 || test->json_output) {
                   2258:         sp = SLIST_FIRST(&test->streams); /* reset back to 1st stream */
                   2259:        /* Only do this of course if there was a first stream */
                   2260:        if (sp) {
                   2261:         irp = TAILQ_LAST(&sp->result->interval_results, irlisthead);    /* use 1st stream for timing info */
                   2262: 
                   2263:         unit_snprintf(ubuf, UNIT_LEN, (double) bytes, 'A');
                   2264:        bandwidth = (double) bytes / (double) irp->interval_duration;
                   2265:         unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
                   2266: 
                   2267:         start_time = timeval_diff(&sp->result->start_time,&irp->interval_start_time);
                   2268:         end_time = timeval_diff(&sp->result->start_time,&irp->interval_end_time);
                   2269:        if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
                   2270:            if (test->sender && test->sender_has_retransmits) {
                   2271:                /* Interval sum, TCP with retransmits. */
                   2272:                if (test->json_output)
                   2273:                    cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  retransmits: %d  omitted: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, (int64_t) retransmits, irp->omitted)); /* XXX irp->omitted or test->omitting? */
                   2274:                else
                   2275:                    iprintf(test, report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, retransmits, irp->omitted?report_omitted:""); /* XXX irp->omitted or test->omitting? */
                   2276:            } else {
                   2277:                /* Interval sum, TCP without retransmits. */
                   2278:                if (test->json_output)
                   2279:                    cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  omitted: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, test->omitting));
                   2280:                else
                   2281:                    iprintf(test, report_sum_bw_format, start_time, end_time, ubuf, nbuf, test->omitting?report_omitted:"");
                   2282:            }
                   2283:        } else {
                   2284:            /* Interval sum, UDP. */
                   2285:            if (test->sender) {
                   2286:                if (test->json_output)
                   2287:                    cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  packets: %d  omitted: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, (int64_t) total_packets, test->omitting));
                   2288:                else
                   2289:                    iprintf(test, report_sum_bw_udp_sender_format, start_time, end_time, ubuf, nbuf, total_packets, test->omitting?report_omitted:"");
                   2290:            } else {
                   2291:                avg_jitter /= test->num_streams;
                   2292:                if (total_packets > 0) {
                   2293:                    lost_percent = 100.0 * lost_packets / total_packets;
                   2294:                }
                   2295:                else {
                   2296:                    lost_percent = 0.0;
                   2297:                }
                   2298:                if (test->json_output)
                   2299:                    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", (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));
                   2300:                else
                   2301:                    iprintf(test, report_sum_bw_udp_format, start_time, end_time, ubuf, nbuf, avg_jitter * 1000.0, lost_packets, total_packets, lost_percent, test->omitting?report_omitted:"");
                   2302:            }
                   2303:        }
                   2304:        }
                   2305:     }
                   2306: }
                   2307: 
                   2308: /**
                   2309:  * Print overall summary statistics at the end of a test.
                   2310:  */
                   2311: static void
                   2312: iperf_print_results(struct iperf_test *test)
                   2313: {
                   2314: 
                   2315:     cJSON *json_summary_streams = NULL;
                   2316:     cJSON *json_summary_stream = NULL;
                   2317:     int total_retransmits = 0;
                   2318:     int total_packets = 0, lost_packets = 0;
                   2319:     char ubuf[UNIT_LEN];
                   2320:     char nbuf[UNIT_LEN];
                   2321:     struct stat sb;
                   2322:     char sbuf[UNIT_LEN];
                   2323:     struct iperf_stream *sp = NULL;
                   2324:     iperf_size_t bytes_sent, total_sent = 0;
                   2325:     iperf_size_t bytes_received, total_received = 0;
                   2326:     double start_time, end_time, avg_jitter = 0.0, lost_percent;
                   2327:     double bandwidth;
                   2328: 
                   2329:     /* print final summary for all intervals */
                   2330: 
                   2331:     if (test->json_output) {
                   2332:         json_summary_streams = cJSON_CreateArray();
                   2333:        if (json_summary_streams == NULL)
                   2334:            return;
                   2335:        cJSON_AddItemToObject(test->json_end, "streams", json_summary_streams);
                   2336:     } else {
                   2337:        iprintf(test, "%s", report_bw_separator);
                   2338:        if (test->verbose)
                   2339:            iprintf(test, "%s", report_summary);
                   2340:        if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
                   2341:            if (test->sender_has_retransmits)
                   2342:                iprintf(test, "%s", report_bw_retrans_header);
                   2343:            else
                   2344:                iprintf(test, "%s", report_bw_header);
                   2345:        } else
                   2346:            iprintf(test, "%s", report_bw_udp_header);
                   2347:     }
                   2348: 
                   2349:     start_time = 0.;
                   2350:     sp = SLIST_FIRST(&test->streams);
                   2351:     /* 
                   2352:      * If there is at least one stream, then figure out the length of time
                   2353:      * we were running the tests and print out some statistics about
                   2354:      * the streams.  It's possible to not have any streams at all
                   2355:      * if the client got interrupted before it got to do anything.
                   2356:      */
                   2357:     if (sp) {
                   2358:     end_time = timeval_diff(&sp->result->start_time, &sp->result->end_time);
                   2359:     SLIST_FOREACH(sp, &test->streams, streams) {
                   2360:        if (test->json_output) {
                   2361:            json_summary_stream = cJSON_CreateObject();
                   2362:            if (json_summary_stream == NULL)
                   2363:                return;
                   2364:            cJSON_AddItemToArray(json_summary_streams, json_summary_stream);
                   2365:        }
                   2366: 
                   2367:         bytes_sent = sp->result->bytes_sent - sp->result->bytes_sent_omit;
                   2368:         bytes_received = sp->result->bytes_received;
                   2369:         total_sent += bytes_sent;
                   2370:         total_received += bytes_received;
                   2371: 
                   2372:         if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
                   2373:            if (test->sender_has_retransmits) {
                   2374:                total_retransmits += sp->result->stream_retrans;
                   2375:            }
                   2376:        } else {
                   2377:             total_packets += (sp->packet_count - sp->omitted_packet_count);
                   2378:             lost_packets += (sp->cnt_error - sp->omitted_cnt_error);
                   2379:             avg_jitter += sp->jitter;
                   2380:         }
                   2381: 
                   2382:        unit_snprintf(ubuf, UNIT_LEN, (double) bytes_sent, 'A');
                   2383:        bandwidth = (double) bytes_sent / (double) end_time;
                   2384:        unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
                   2385:        if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
                   2386:            if (test->sender_has_retransmits) {
                   2387:                /* Summary, TCP with retransmits. */
                   2388:                if (test->json_output)
                   2389:                    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", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_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)));
                   2390:                else
                   2391:                    iprintf(test, report_bw_retrans_format, sp->socket, start_time, end_time, ubuf, nbuf, sp->result->stream_retrans, report_sender);
                   2392:            } else {
                   2393:                /* Summary, TCP without retransmits. */
                   2394:                if (test->json_output)
                   2395:                    cJSON_AddItemToObject(json_summary_stream, "sender", iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_time, (int64_t) bytes_sent, bandwidth * 8));
                   2396:                else
                   2397:                    iprintf(test, report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf, report_sender);
                   2398:            }
                   2399:        } else {
                   2400:            /* Summary, UDP. */
                   2401:            if (sp->packet_count - sp->omitted_packet_count > 0) {
                   2402:               lost_percent = 100.0 * (sp->cnt_error - sp->omitted_cnt_error) / (sp->packet_count - sp->omitted_packet_count);
                   2403:            }
                   2404:            else {
                   2405:                lost_percent = 0.0;
                   2406:            }
                   2407:            if (test->json_output)
                   2408:               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", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_time, (int64_t) bytes_sent, bandwidth * 8, (double) sp->jitter * 1000.0, (int64_t) (sp->cnt_error - sp->omitted_cnt_error), (int64_t) (sp->packet_count - sp->omitted_packet_count), (double) lost_percent, (int64_t) (sp->outoforder_packets - sp->omitted_outoforder_packets)));
                   2409:            else {
                   2410:               iprintf(test, report_bw_udp_format, sp->socket, start_time, end_time, ubuf, nbuf, sp->jitter * 1000.0, (sp->cnt_error - sp->omitted_cnt_error), (sp->packet_count - sp->omitted_packet_count), lost_percent, "");
                   2411:                if (test->role == 'c')
                   2412:                    iprintf(test, report_datagrams, sp->socket, (sp->packet_count - sp->omitted_packet_count));
                   2413:                if ((sp->outoforder_packets - sp->omitted_outoforder_packets) > 0)
                   2414:                   iprintf(test, report_sum_outoforder, start_time, end_time, (sp->outoforder_packets - sp->omitted_outoforder_packets));
                   2415:            }
                   2416:        }
                   2417: 
                   2418:        if (sp->diskfile_fd >= 0) {
                   2419:            if (fstat(sp->diskfile_fd, &sb) == 0) {
                   2420:                int percent = (int) ( ( (double) bytes_sent / (double) sb.st_size ) * 100.0 );
                   2421:                unit_snprintf(sbuf, UNIT_LEN, (double) sb.st_size, 'A');
                   2422:                if (test->json_output)
                   2423:                    cJSON_AddItemToObject(json_summary_stream, "diskfile", iperf_json_printf("sent: %d  size: %d  percent: %d  filename: %s", (int64_t) bytes_sent, (int64_t) sb.st_size, (int64_t) percent, test->diskfile_name));
                   2424:                else
                   2425:                    iprintf(test, report_diskfile, ubuf, sbuf, percent, test->diskfile_name);
                   2426:            }
                   2427:        }
                   2428: 
                   2429:        unit_snprintf(ubuf, UNIT_LEN, (double) bytes_received, 'A');
                   2430:        bandwidth = (double) bytes_received / (double) end_time;
                   2431:        unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
                   2432:        if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
                   2433:            if (test->json_output)
                   2434:                cJSON_AddItemToObject(json_summary_stream, "receiver", iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_time, (int64_t) bytes_received, bandwidth * 8));
                   2435:            else
                   2436:                iprintf(test, report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf, report_receiver);
                   2437:        }
                   2438:     }
                   2439:     }
                   2440: 
                   2441:     if (test->num_streams > 1 || test->json_output) {
                   2442:         unit_snprintf(ubuf, UNIT_LEN, (double) total_sent, 'A');
                   2443:        /* If no tests were run, arbitrariliy set bandwidth to 0. */
                   2444:        if (end_time > 0.0) {
                   2445:            bandwidth = (double) total_sent / (double) end_time;
                   2446:        }
                   2447:        else {
                   2448:            bandwidth = 0.0;
                   2449:        }
                   2450:         unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
                   2451:         if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
                   2452:            if (test->sender_has_retransmits) {
                   2453:                /* Summary sum, TCP with retransmits. */
                   2454:                if (test->json_output)
                   2455:                    cJSON_AddItemToObject(test->json_end, "sum_sent", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  retransmits: %d", (double) start_time, (double) end_time, (double) end_time, (int64_t) total_sent, bandwidth * 8, (int64_t) total_retransmits));
                   2456:                else
                   2457:                    iprintf(test, report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, total_retransmits, report_sender);
                   2458:            } else {
                   2459:                /* Summary sum, TCP without retransmits. */
                   2460:                if (test->json_output)
                   2461:                    cJSON_AddItemToObject(test->json_end, "sum_sent", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f", (double) start_time, (double) end_time, (double) end_time, (int64_t) total_sent, bandwidth * 8));
                   2462:                else
                   2463:                    iprintf(test, report_sum_bw_format, start_time, end_time, ubuf, nbuf, report_sender);
                   2464:            }
                   2465:             unit_snprintf(ubuf, UNIT_LEN, (double) total_received, 'A');
                   2466:            /* If no tests were run, set received bandwidth to 0 */
                   2467:            if (end_time > 0.0) {
                   2468:                bandwidth = (double) total_received / (double) end_time;
                   2469:            }
                   2470:            else {
                   2471:                bandwidth = 0.0;
                   2472:            }
                   2473:             unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
                   2474:            if (test->json_output)
                   2475:                cJSON_AddItemToObject(test->json_end, "sum_received", iperf_json_printf("start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f", (double) start_time, (double) end_time, (double) end_time, (int64_t) total_received, bandwidth * 8));
                   2476:            else
                   2477:                iprintf(test, report_sum_bw_format, start_time, end_time, ubuf, nbuf, report_receiver);
                   2478:         } else {
                   2479:            /* Summary sum, UDP. */
                   2480:             avg_jitter /= test->num_streams;
                   2481:            /* If no packets were sent, arbitrarily set loss percentage to 0. */
                   2482:            if (total_packets > 0) {
                   2483:                lost_percent = 100.0 * lost_packets / total_packets;
                   2484:            }
                   2485:            else {
                   2486:                lost_percent = 0.0;
                   2487:            }
                   2488:            if (test->json_output)
                   2489:                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", (double) start_time, (double) end_time, (double) end_time, (int64_t) total_sent, bandwidth * 8, (double) avg_jitter * 1000.0, (int64_t) lost_packets, (int64_t) total_packets, (double) lost_percent));
                   2490:            else
                   2491:                iprintf(test, report_sum_bw_udp_format, start_time, end_time, ubuf, nbuf, avg_jitter * 1000.0, lost_packets, total_packets, lost_percent, "");
                   2492:         }
                   2493:     }
                   2494: 
                   2495:     if (test->json_output)
                   2496:        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]));
                   2497:     else {
                   2498:        if (test->verbose) {
                   2499:            iprintf(test, report_cpu, report_local, test->sender?report_sender:report_receiver, test->cpu_util[0], test->cpu_util[1], test->cpu_util[2], report_remote, test->sender?report_receiver:report_sender, test->remote_cpu_util[0], test->remote_cpu_util[1], test->remote_cpu_util[2]);
                   2500:        }
                   2501: 
                   2502:        /* Print server output if we're on the client and it was requested/provided */
                   2503:        if (test->role == 'c' && iperf_get_test_get_server_output(test)) {
                   2504:            if (test->json_server_output) {
                   2505:                iprintf(test, "\nServer JSON output:\n%s\n", cJSON_Print(test->json_server_output));
                   2506:                cJSON_Delete(test->json_server_output);
                   2507:                test->json_server_output = NULL;
                   2508:            }
                   2509:            if (test->server_output_text) {
                   2510:                iprintf(test, "\nServer output:\n%s\n", test->server_output_text);
                   2511:                test->server_output_text = NULL;
                   2512:            }
                   2513:        }
                   2514:     }
                   2515: }
                   2516: 
                   2517: /**************************************************************************/
                   2518: 
                   2519: /**
                   2520:  * Main report-printing callback.
                   2521:  * Prints results either during a test (interval report only) or 
                   2522:  * after the entire test has been run (last interval report plus 
                   2523:  * overall summary).
                   2524:  */
                   2525: void
                   2526: iperf_reporter_callback(struct iperf_test *test)
                   2527: {
                   2528:     switch (test->state) {
                   2529:         case TEST_RUNNING:
                   2530:         case STREAM_RUNNING:
                   2531:             /* print interval results for each stream */
                   2532:             iperf_print_intermediate(test);
                   2533:             break;
                   2534:         case TEST_END:
                   2535:         case DISPLAY_RESULTS:
                   2536:             iperf_print_intermediate(test);
                   2537:             iperf_print_results(test);
                   2538:             break;
                   2539:     } 
                   2540: 
                   2541: }
                   2542: 
                   2543: /**
                   2544:  * Print the interval results for one stream.
                   2545:  * This function needs to know about the overall test so it can determine the
                   2546:  * context for printing headers, separators, etc.
                   2547:  */
                   2548: static void
                   2549: print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *json_interval_streams)
                   2550: {
                   2551:     char ubuf[UNIT_LEN];
                   2552:     char nbuf[UNIT_LEN];
                   2553:     char cbuf[UNIT_LEN];
                   2554:     double st = 0., et = 0.;
                   2555:     struct iperf_interval_results *irp = NULL;
                   2556:     double bandwidth, lost_percent;
                   2557: 
                   2558:     irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); /* get last entry in linked list */
                   2559:     if (irp == NULL) {
                   2560:        iperf_err(test, "print_interval_results error: interval_results is NULL");
                   2561:         return;
                   2562:     }
                   2563:     if (!test->json_output) {
                   2564:        /* First stream? */
                   2565:        if (sp == SLIST_FIRST(&test->streams)) {
                   2566:            /* It it's the first interval, print the header;
                   2567:            ** else if there's more than one stream, print the separator;
                   2568:            ** else nothing.
                   2569:            */
                   2570:            if (timeval_equals(&sp->result->start_time, &irp->interval_start_time)) {
                   2571:                if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
                   2572:                    if (test->sender && test->sender_has_retransmits)
                   2573:                        iprintf(test, "%s", report_bw_retrans_cwnd_header);
                   2574:                    else
                   2575:                        iprintf(test, "%s", report_bw_header);
                   2576:                } else {
                   2577:                    if (test->sender)
                   2578:                        iprintf(test, "%s", report_bw_udp_sender_header);
                   2579:                    else
                   2580:                        iprintf(test, "%s", report_bw_udp_header);
                   2581:                }
                   2582:            } else if (test->num_streams > 1)
                   2583:                iprintf(test, "%s", report_bw_separator);
                   2584:        }
                   2585:     }
                   2586: 
                   2587:     unit_snprintf(ubuf, UNIT_LEN, (double) (irp->bytes_transferred), 'A');
                   2588:     bandwidth = (double) irp->bytes_transferred / (double) irp->interval_duration;
                   2589:     unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
                   2590:     
                   2591:     st = timeval_diff(&sp->result->start_time, &irp->interval_start_time);
                   2592:     et = timeval_diff(&sp->result->start_time, &irp->interval_end_time);
                   2593:     
                   2594:     if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
                   2595:        if (test->sender && test->sender_has_retransmits) {
                   2596:            /* Interval, TCP with retransmits. */
                   2597:            if (test->json_output)
                   2598:                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  omitted: %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, irp->omitted));
                   2599:            else {
                   2600:                unit_snprintf(cbuf, UNIT_LEN, irp->snd_cwnd, 'A');
                   2601:                iprintf(test, report_bw_retrans_cwnd_format, sp->socket, st, et, ubuf, nbuf, irp->interval_retrans, cbuf, irp->omitted?report_omitted:"");
                   2602:            }
                   2603:        } else {
                   2604:            /* Interval, TCP without retransmits. */
                   2605:            if (test->json_output)
                   2606:                cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d  start: %f  end: %f  seconds: %f  bytes: %d  bits_per_second: %f  omitted: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, irp->omitted));
                   2607:            else
                   2608:                iprintf(test, report_bw_format, sp->socket, st, et, ubuf, nbuf, irp->omitted?report_omitted:"");
                   2609:        }
                   2610:     } else {
                   2611:        /* Interval, UDP. */
                   2612:        if (test->sender) {
                   2613:            if (test->json_output)
                   2614:                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", (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));
                   2615:            else
                   2616:                iprintf(test, report_bw_udp_sender_format, sp->socket, st, et, ubuf, nbuf, irp->interval_packet_count, irp->omitted?report_omitted:"");
                   2617:        } else {
                   2618:            if (irp->interval_packet_count > 0) {
                   2619:                lost_percent = 100.0 * irp->interval_cnt_error / irp->interval_packet_count;
                   2620:            }
                   2621:            else {
                   2622:                lost_percent = 0.0;
                   2623:            }
                   2624:            if (test->json_output)
                   2625:                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", (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));
                   2626:            else
                   2627:                iprintf(test, report_bw_udp_format, sp->socket, st, et, ubuf, nbuf, irp->jitter * 1000.0, irp->interval_cnt_error, irp->interval_packet_count, lost_percent, irp->omitted?report_omitted:"");
                   2628:        }
                   2629:     }
                   2630: 
                   2631:     if (test->logfile)
                   2632:         iflush(test);
                   2633: }
                   2634: 
                   2635: /**************************************************************************/
                   2636: void
                   2637: iperf_free_stream(struct iperf_stream *sp)
                   2638: {
                   2639:     struct iperf_interval_results *irp, *nirp;
                   2640: 
                   2641:     /* XXX: need to free interval list too! */
                   2642:     munmap(sp->buffer, sp->test->settings->blksize);
                   2643:     close(sp->buffer_fd);
                   2644:     if (sp->diskfile_fd >= 0)
                   2645:        close(sp->diskfile_fd);
                   2646:     for (irp = TAILQ_FIRST(&sp->result->interval_results); irp != NULL; irp = nirp) {
                   2647:         nirp = TAILQ_NEXT(irp, irlistentries);
                   2648:         free(irp);
                   2649:     }
                   2650:     free(sp->result);
                   2651:     if (sp->send_timer != NULL)
                   2652:        tmr_cancel(sp->send_timer);
                   2653:     free(sp);
                   2654: }
                   2655: 
                   2656: /**************************************************************************/
                   2657: struct iperf_stream *
                   2658: iperf_new_stream(struct iperf_test *test, int s)
                   2659: {
                   2660:     int i;
                   2661:     struct iperf_stream *sp;
                   2662:     
                   2663:     char template[1024];
                   2664:     if (test->tmp_template) {
                   2665:         snprintf(template, sizeof(template) / sizeof(char), "%s", test->tmp_template);
                   2666:     } else {
                   2667:         char buf[] = "/tmp/iperf3.XXXXXX";
                   2668:         snprintf(template, sizeof(template) / sizeof(char), "%s", buf);
                   2669:     }
                   2670: 
                   2671:     h_errno = 0;
                   2672: 
                   2673:     sp = (struct iperf_stream *) malloc(sizeof(struct iperf_stream));
                   2674:     if (!sp) {
                   2675:         i_errno = IECREATESTREAM;
                   2676:         return NULL;
                   2677:     }
                   2678: 
                   2679:     memset(sp, 0, sizeof(struct iperf_stream));
                   2680: 
                   2681:     sp->test = test;
                   2682:     sp->settings = test->settings;
                   2683:     sp->result = (struct iperf_stream_result *) malloc(sizeof(struct iperf_stream_result));
                   2684:     if (!sp->result) {
                   2685:         free(sp);
                   2686:         i_errno = IECREATESTREAM;
                   2687:         return NULL;
                   2688:     }
                   2689: 
                   2690:     memset(sp->result, 0, sizeof(struct iperf_stream_result));
                   2691:     TAILQ_INIT(&sp->result->interval_results);
                   2692:     
                   2693:     /* Create and randomize the buffer */
                   2694:     sp->buffer_fd = mkstemp(template);
                   2695:     if (sp->buffer_fd == -1) {
                   2696:         i_errno = IECREATESTREAM;
                   2697:         free(sp->result);
                   2698:         free(sp);
                   2699:         return NULL;
                   2700:     }
                   2701:     if (unlink(template) < 0) {
                   2702:         i_errno = IECREATESTREAM;
                   2703:         free(sp->result);
                   2704:         free(sp);
                   2705:         return NULL;
                   2706:     }
                   2707:     if (ftruncate(sp->buffer_fd, test->settings->blksize) < 0) {
                   2708:         i_errno = IECREATESTREAM;
                   2709:         free(sp->result);
                   2710:         free(sp);
                   2711:         return NULL;
                   2712:     }
                   2713:     sp->buffer = (char *) mmap(NULL, test->settings->blksize, PROT_READ|PROT_WRITE, MAP_PRIVATE, sp->buffer_fd, 0);
                   2714:     if (sp->buffer == MAP_FAILED) {
                   2715:         i_errno = IECREATESTREAM;
                   2716:         free(sp->result);
                   2717:         free(sp);
                   2718:         return NULL;
                   2719:     }
                   2720:     srandom(time(NULL));
                   2721:     for (i = 0; i < test->settings->blksize; ++i)
                   2722:         sp->buffer[i] = random();
                   2723: 
                   2724:     /* Set socket */
                   2725:     sp->socket = s;
                   2726: 
                   2727:     sp->snd = test->protocol->send;
                   2728:     sp->rcv = test->protocol->recv;
                   2729: 
                   2730:     if (test->diskfile_name != (char*) 0) {
                   2731:        sp->diskfile_fd = open(test->diskfile_name, test->sender ? O_RDONLY : (O_WRONLY|O_CREAT|O_TRUNC), S_IRUSR|S_IWUSR);
                   2732:        if (sp->diskfile_fd == -1) {
                   2733:            i_errno = IEFILE;
                   2734:             munmap(sp->buffer, sp->test->settings->blksize);
                   2735:             free(sp->result);
                   2736:             free(sp);
                   2737:            return NULL;
                   2738:        }
                   2739:         sp->snd2 = sp->snd;
                   2740:        sp->snd = diskfile_send;
                   2741:        sp->rcv2 = sp->rcv;
                   2742:        sp->rcv = diskfile_recv;
                   2743:     } else
                   2744:         sp->diskfile_fd = -1;
                   2745: 
                   2746:     /* Initialize stream */
                   2747:     if (iperf_init_stream(sp, test) < 0) {
                   2748:         close(sp->buffer_fd);
                   2749:         munmap(sp->buffer, sp->test->settings->blksize);
                   2750:         free(sp->result);
                   2751:         free(sp);
                   2752:         return NULL;
                   2753:     }
                   2754:     iperf_add_stream(test, sp);
                   2755: 
                   2756:     return sp;
                   2757: }
                   2758: 
                   2759: /**************************************************************************/
                   2760: int
                   2761: iperf_init_stream(struct iperf_stream *sp, struct iperf_test *test)
                   2762: {
                   2763:     socklen_t len;
                   2764:     int opt;
                   2765: 
                   2766:     len = sizeof(struct sockaddr_storage);
                   2767:     if (getsockname(sp->socket, (struct sockaddr *) &sp->local_addr, &len) < 0) {
                   2768:         i_errno = IEINITSTREAM;
                   2769:         return -1;
                   2770:     }
                   2771:     len = sizeof(struct sockaddr_storage);
                   2772:     if (getpeername(sp->socket, (struct sockaddr *) &sp->remote_addr, &len) < 0) {
                   2773:         i_errno = IEINITSTREAM;
                   2774:         return -1;
                   2775:     }
                   2776: 
                   2777:     /* Set IP TOS */
                   2778:     if ((opt = test->settings->tos)) {
                   2779:         if (getsockdomain(sp->socket) == AF_INET6) {
                   2780: #ifdef IPV6_TCLASS
                   2781:             if (setsockopt(sp->socket, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt)) < 0) {
                   2782:                 i_errno = IESETCOS;
                   2783:                 return -1;
                   2784:             }
                   2785: #else
                   2786:             i_errno = IESETCOS;
                   2787:             return -1;
                   2788: #endif
                   2789:         } else {
                   2790:             if (setsockopt(sp->socket, IPPROTO_IP, IP_TOS, &opt, sizeof(opt)) < 0) {
                   2791:                 i_errno = IESETTOS;
                   2792:                 return -1;
                   2793:             }
                   2794:         }
                   2795:     }
                   2796: 
                   2797:     return 0;
                   2798: }
                   2799: 
                   2800: /**************************************************************************/
                   2801: void
                   2802: iperf_add_stream(struct iperf_test *test, struct iperf_stream *sp)
                   2803: {
                   2804:     int i;
                   2805:     struct iperf_stream *n, *prev;
                   2806: 
                   2807:     if (SLIST_EMPTY(&test->streams)) {
                   2808:         SLIST_INSERT_HEAD(&test->streams, sp, streams);
                   2809:         sp->id = 1;
                   2810:     } else {
                   2811:         // for (n = test->streams, i = 2; n->next; n = n->next, ++i);
                   2812:         i = 2;
                   2813:         SLIST_FOREACH(n, &test->streams, streams) {
                   2814:             prev = n;
                   2815:             ++i;
                   2816:         }
                   2817:         SLIST_INSERT_AFTER(prev, sp, streams);
                   2818:         sp->id = i;
                   2819:     }
                   2820: }
                   2821: 
                   2822: /* This pair of routines gets inserted into the snd/rcv function pointers
                   2823: ** when there's a -F flag. They handle the file stuff and call the real
                   2824: ** snd/rcv functions, which have been saved in snd2/rcv2.
                   2825: **
                   2826: ** The advantage of doing it this way is that in the much more common
                   2827: ** case of no -F flag, there is zero extra overhead.
                   2828: */
                   2829: 
                   2830: static int
                   2831: diskfile_send(struct iperf_stream *sp)
                   2832: {
                   2833:     int r;
                   2834: 
                   2835:     r = read(sp->diskfile_fd, sp->buffer, sp->test->settings->blksize);
                   2836:     if (r == 0)
                   2837:         sp->test->done = 1;
                   2838:     else
                   2839:        r = sp->snd2(sp);
                   2840:     return r;
                   2841: }
                   2842: 
                   2843: static int
                   2844: diskfile_recv(struct iperf_stream *sp)
                   2845: {
                   2846:     int r;
                   2847: 
                   2848:     r = sp->rcv2(sp);
                   2849:     if (r > 0) {
                   2850:        (void) write(sp->diskfile_fd, sp->buffer, r);
                   2851:        (void) fsync(sp->diskfile_fd);
                   2852:     }
                   2853:     return r;
                   2854: }
                   2855: 
                   2856: 
                   2857: void
                   2858: iperf_catch_sigend(void (*handler)(int))
                   2859: {
                   2860:     signal(SIGINT, handler);
                   2861:     signal(SIGTERM, handler);
                   2862:     signal(SIGHUP, handler);
                   2863: }
                   2864: 
                   2865: /**
                   2866:  * Called as a result of getting a signal.
                   2867:  * Depending on the current state of the test (and the role of this
                   2868:  * process) compute and report one more set of ending statistics
                   2869:  * before cleaning up and exiting.
                   2870:  */
                   2871: void
                   2872: iperf_got_sigend(struct iperf_test *test)
                   2873: {
                   2874:     /*
                   2875:      * If we're the client, or if we're a server and running a test,
                   2876:      * then dump out the accumulated stats so far.
                   2877:      */
                   2878:     if (test->role == 'c' ||
                   2879:       (test->role == 's' && test->state == TEST_RUNNING)) {
                   2880: 
                   2881:        test->done = 1;
                   2882:        cpu_util(test->cpu_util);
                   2883:        test->stats_callback(test);
                   2884:        test->state = DISPLAY_RESULTS; /* change local state only */
                   2885:        if (test->on_test_finish)
                   2886:            test->on_test_finish(test);
                   2887:        test->reporter_callback(test);
                   2888:     }
                   2889: 
                   2890:     if (test->ctrl_sck >= 0) {
                   2891:        test->state = (test->role == 'c') ? CLIENT_TERMINATE : SERVER_TERMINATE;
                   2892:        (void) Nwrite(test->ctrl_sck, (char*) &test->state, sizeof(signed char), Ptcp);
                   2893:     }
                   2894:     i_errno = (test->role == 'c') ? IECLIENTTERM : IESERVERTERM;
                   2895:     iperf_errexit(test, "interrupt - %s", iperf_strerror(i_errno));
                   2896: }
                   2897: 
                   2898: /* Try to write a PID file if requested, return -1 on an error. */
                   2899: int
                   2900: iperf_create_pidfile(struct iperf_test *test)
                   2901: {
                   2902:     if (test->pidfile) {
                   2903:        int fd;
                   2904:        char buf[8];
                   2905:        fd = open(test->pidfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR|S_IWUSR);
                   2906:        if (fd < 0) {
                   2907:            return -1;
                   2908:        }
                   2909:        snprintf(buf, sizeof(buf), "%d", getpid()); /* no trailing newline */
                   2910:        if (write(fd, buf, strlen(buf) + 1) < 0) {
                   2911:            return -1;
                   2912:        }
                   2913:        if (close(fd) < 0) {
                   2914:            return -1;
                   2915:        };
                   2916:     }
                   2917:     return 0;
                   2918: }
                   2919: 
                   2920: /* Get rid of a PID file, return -1 on error. */
                   2921: int
                   2922: iperf_delete_pidfile(struct iperf_test *test)
                   2923: {
                   2924:     if (test->pidfile) {
                   2925:        if (unlink(test->pidfile) < 0) {
                   2926:            return -1;
                   2927:        }
                   2928:     }
                   2929:     return 0;
                   2930: }
                   2931: 
                   2932: int
                   2933: iperf_json_start(struct iperf_test *test)
                   2934: {
                   2935:     test->json_top = cJSON_CreateObject();
                   2936:     if (test->json_top == NULL)
                   2937:         return -1;
                   2938:     test->json_start = cJSON_CreateObject();
                   2939:     if (test->json_start == NULL)
                   2940:         return -1;
                   2941:     cJSON_AddItemToObject(test->json_top, "start", test->json_start);
                   2942:     test->json_connected = cJSON_CreateArray();
                   2943:     if (test->json_connected == NULL)
                   2944:         return -1;
                   2945:     cJSON_AddItemToObject(test->json_start, "connected", test->json_connected);
                   2946:     test->json_intervals = cJSON_CreateArray();
                   2947:     if (test->json_intervals == NULL)
                   2948:         return -1;
                   2949:     cJSON_AddItemToObject(test->json_top, "intervals", test->json_intervals);
                   2950:     test->json_end = cJSON_CreateObject();
                   2951:     if (test->json_end == NULL)
                   2952:         return -1;
                   2953:     cJSON_AddItemToObject(test->json_top, "end", test->json_end);
                   2954:     return 0;
                   2955: }
                   2956: 
                   2957: int
                   2958: iperf_json_finish(struct iperf_test *test)
                   2959: {
                   2960:     if (test->title)
                   2961:        cJSON_AddStringToObject(test->json_top, "title", test->title);
                   2962:     /* Include server output */
                   2963:     if (test->json_server_output) {
                   2964:        cJSON_AddItemToObject(test->json_top, "server_output_json", test->json_server_output);
                   2965:     }
                   2966:     if (test->server_output_text) {
                   2967:        cJSON_AddStringToObject(test->json_top, "server_output_text", test->server_output_text);
                   2968:     }
                   2969:     test->json_output_string = cJSON_Print(test->json_top);
                   2970:     if (test->json_output_string == NULL)
                   2971:         return -1;
                   2972:     fprintf(test->outfile, "%s\n", test->json_output_string);
                   2973:     iflush(test);
                   2974:     cJSON_Delete(test->json_top);
                   2975:     test->json_top = test->json_start = test->json_connected = test->json_intervals = test->json_server_output = test->json_end = NULL;
                   2976:     return 0;
                   2977: }
                   2978: 
                   2979: 
                   2980: /* CPU affinity stuff - Linux and FreeBSD only. */
                   2981: 
                   2982: int
                   2983: iperf_setaffinity(struct iperf_test *test, int affinity)
                   2984: {
                   2985: #if defined(HAVE_SCHED_SETAFFINITY)
                   2986:     cpu_set_t cpu_set;
                   2987: 
                   2988:     CPU_ZERO(&cpu_set);
                   2989:     CPU_SET(affinity, &cpu_set);
                   2990:     if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) != 0) {
                   2991:        i_errno = IEAFFINITY;
                   2992:         return -1;
                   2993:     }
                   2994:     return 0;
                   2995: #elif defined(HAVE_CPUSET_SETAFFINITY)
                   2996:     cpuset_t cpumask;
                   2997: 
                   2998:     if(cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1,
                   2999:                           sizeof(cpuset_t), &test->cpumask) != 0) {
                   3000:         i_errno = IEAFFINITY;
                   3001:         return -1;
                   3002:     }
                   3003: 
                   3004:     CPU_ZERO(&cpumask);
                   3005:     CPU_SET(affinity, &cpumask);
                   3006: 
                   3007:     if(cpuset_setaffinity(CPU_LEVEL_WHICH,CPU_WHICH_PID, -1,
                   3008:                           sizeof(cpuset_t), &cpumask) != 0) {
                   3009:         i_errno = IEAFFINITY;
                   3010:         return -1;
                   3011:     }
                   3012:     return 0;
                   3013: #else /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */
                   3014:     i_errno = IEAFFINITY;
                   3015:     return -1;
                   3016: #endif /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */
                   3017: }
                   3018: 
                   3019: int
                   3020: iperf_clearaffinity(struct iperf_test *test)
                   3021: {
                   3022: #if defined(HAVE_SCHED_SETAFFINITY)
                   3023:     cpu_set_t cpu_set;
                   3024:     int i;
                   3025: 
                   3026:     CPU_ZERO(&cpu_set);
                   3027:     for (i = 0; i < CPU_SETSIZE; ++i)
                   3028:        CPU_SET(i, &cpu_set);
                   3029:     if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) != 0) {
                   3030:        i_errno = IEAFFINITY;
                   3031:         return -1;
                   3032:     }
                   3033:     return 0;
                   3034: #elif defined(HAVE_CPUSET_SETAFFINITY)
                   3035:     if(cpuset_setaffinity(CPU_LEVEL_WHICH,CPU_WHICH_PID, -1,
                   3036:                           sizeof(cpuset_t), &test->cpumask) != 0) {
                   3037:         i_errno = IEAFFINITY;
                   3038:         return -1;
                   3039:     }
                   3040:     return 0;
                   3041: #else /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */
                   3042:     i_errno = IEAFFINITY;
                   3043:     return -1;
                   3044: #endif /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */
                   3045: }
                   3046: 
                   3047: int
                   3048: iprintf(struct iperf_test *test, const char* format, ...)
                   3049: {
                   3050:     va_list argp;
                   3051:     int r = -1;
                   3052: 
                   3053:     /*
                   3054:      * There are roughly two use cases here.  If we're the client,
                   3055:      * want to print stuff directly to the output stream.
                   3056:      * If we're the sender we might need to buffer up output to send
                   3057:      * to the client.
                   3058:      *
                   3059:      * This doesn't make a whole lot of difference except there are
                   3060:      * some chunks of output on the client (on particular the whole
                   3061:      * of the server output with --get-server-output) that could
                   3062:      * easily exceed the size of the line buffer, but which don't need
                   3063:      * to be buffered up anyway.
                   3064:      */
                   3065:     if (test->role == 'c') {
                   3066:        if (test->title)
                   3067:            fprintf(test->outfile, "%s:  ", test->title);
                   3068:        va_start(argp, format);
                   3069:        r = vfprintf(test->outfile, format, argp);
                   3070:        va_end(argp);
                   3071:     }
                   3072:     else if (test->role == 's') {
                   3073:        char linebuffer[1024];
                   3074:        va_start(argp, format);
                   3075:        r = vsnprintf(linebuffer, sizeof(linebuffer), format, argp);
                   3076:        va_end(argp);
                   3077:        fprintf(test->outfile, "%s", linebuffer);
                   3078: 
                   3079:        if (test->role == 's' && iperf_get_test_get_server_output(test)) {
                   3080:            struct iperf_textline *l = (struct iperf_textline *) malloc(sizeof(struct iperf_textline));
                   3081:            l->line = strdup(linebuffer);
                   3082:            TAILQ_INSERT_TAIL(&(test->server_output_list), l, textlineentries);
                   3083:        }
                   3084:     }
                   3085:     return r;
                   3086: }
                   3087: 
                   3088: int
                   3089: iflush(struct iperf_test *test)
                   3090: {
                   3091:     return fflush(test->outfile);
                   3092: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>