1 /* 2 * Copyright (c) 2009-2014, The Regents of the University of California, 3 * through Lawrence Berkeley National Laboratory (subject to receipt of any 4 * required approvals from the U.S. Dept. of Energy). All rights reserved. 5 * 6 * This code is distributed under a BSD style license, see the LICENSE file 7 * for complete information. 8 */ 9 #include "iperf_config.h" 10 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <getopt.h> 15 #include <errno.h> 16 #include <signal.h> 17 #include <unistd.h> 18 #include <stdint.h> 19 #include <sys/socket.h> 20 #include <sys/types.h> 21 #include <netinet/in.h> 22 #include <arpa/inet.h> 23 #include <netdb.h> 24 #include <stdint.h> 25 #include <netinet/tcp.h> 26 27 #include "iperf.h" 28 #include "iperf_api.h" 29 #include "units.h" 30 #include "locale.h" 31 #include "net.h" 32 33 34 static int run(struct iperf_test *test); 35 36 37 /**************************************************************************/ 38 int 39 main(int argc, char **argv) 40 { 41 struct iperf_test *test; 42 43 // XXX: Setting the process affinity requires root on most systems. 44 // Is this a feature we really need? 45 #ifdef TEST_PROC_AFFINITY 46 /* didnt seem to work.... */ 47 /* 48 * increasing the priority of the process to minimise packet generation 49 * delay 50 */ 51 int rc = setpriority(PRIO_PROCESS, 0, -15); 52 53 if (rc < 0) { 54 perror("setpriority:"); 55 fprintf(stderr, "setting priority to valid level\n"); 56 rc = setpriority(PRIO_PROCESS, 0, 0); 57 } 58 59 /* setting the affinity of the process */ 60 cpu_set_t cpu_set; 61 int affinity = -1; 62 int ncores = 1; 63 64 sched_getaffinity(0, sizeof(cpu_set_t), &cpu_set); 65 if (errno) 66 perror("couldn't get affinity:"); 67 68 if ((ncores = sysconf(_SC_NPROCESSORS_CONF)) <= 0) 69 err("sysconf: couldn't get _SC_NPROCESSORS_CONF"); 70 71 CPU_ZERO(&cpu_set); 72 CPU_SET(affinity, &cpu_set); 73 if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) != 0) 74 err("couldn't change CPU affinity"); 75 #endif 76 77 test = iperf_new_test(); 78 if (!test) 79 iperf_errexit(NULL, "create new test error - %s", iperf_strerror(i_errno)); 80 iperf_defaults(test); /* sets defaults */ 81 82 /* This main program doesn't use SIGALRM, so the iperf API may use it. */ 83 iperf_set_test_may_use_sigalrm(test, 1); 84 85 if (iperf_parse_arguments(test, argc, argv) < 0) { 86 iperf_err(test, "parameter error - %s", iperf_strerror(i_errno)); 87 fprintf(stderr, "\n"); 88 usage_long(); 89 exit(1); 90 } 91 92 if (run(test) < 0) 93 iperf_errexit(test, "error - %s", iperf_strerror(i_errno)); 94 95 iperf_free_test(test); 96 97 return 0; 98 } 99 100 /**************************************************************************/ 101 static int 102 run(struct iperf_test *test) 103 { 104 int consecutive_errors; 105 106 switch (test->role) { 107 case 's': 108 if (test->daemon) { 109 int rc = daemon(0, 0); 110 if (rc < 0) { 111 i_errno = IEDAEMON; 112 iperf_errexit(test, "error - %s", iperf_strerror(i_errno)); 113 } 114 } 115 consecutive_errors = 0; 116 if (iperf_create_pidfile(test) < 0) { 117 i_errno = IEPIDFILE; 118 iperf_errexit(test, "error - %s", iperf_strerror(i_errno)); 119 } 120 for (;;) { 121 if (iperf_run_server(test) < 0) { 122 iperf_err(test, "error - %s", iperf_strerror(i_errno)); 123 fprintf(stderr, "\n"); 124 ++consecutive_errors; 125 if (consecutive_errors >= 5) { 126 fprintf(stderr, "too many errors, exiting\n"); 127 break; 128 } 129 } else 130 consecutive_errors = 0; 131 iperf_reset_test(test); 132 } 133 iperf_delete_pidfile(test); 134 break; 135 case 'c': 136 if (iperf_run_client(test) < 0) 137 iperf_errexit(test, "error - %s", iperf_strerror(i_errno)); 138 break; 139 default: 140 usage(); 141 break; 142 } 143 144 return 0; 145 } 146