diff options
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..b179f5b --- /dev/null +++ b/src/main.c @@ -0,0 +1,214 @@ +/* + * iperf, Copyright (c) 2014-2023, The Regents of the University of + * California, through Lawrence Berkeley National Laboratory (subject + * to receipt of any required approvals from the U.S. Dept. of + * Energy). All rights reserved. + * + * If you have questions about your rights to use or distribute this + * software, please contact Berkeley Lab's Technology Transfer + * Department at TTD@lbl.gov. + * + * NOTICE. This software is owned by the U.S. Department of Energy. + * As such, the U.S. Government has been granted for itself and others + * acting on its behalf a paid-up, nonexclusive, irrevocable, + * worldwide license in the Software to reproduce, prepare derivative + * works, and perform publicly and display publicly. Beginning five + * (5) years after the date permission to assert copyright is obtained + * from the U.S. Department of Energy, and subject to any subsequent + * five (5) year renewals, the U.S. Government is granted for itself + * and others acting on its behalf a paid-up, nonexclusive, + * irrevocable, worldwide license in the Software to reproduce, + * prepare derivative works, distribute copies to the public, perform + * publicly and display publicly, and to permit others to do so. + * + * This code is distributed under a BSD style license, see the LICENSE + * file for complete information. + */ +#include "iperf_config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <getopt.h> +#include <errno.h> +#include <signal.h> +#include <unistd.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#include <sys/socket.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> + +#include "iperf.h" +#include "iperf_api.h" +#include "iperf_util.h" +#include "iperf_locale.h" +#include "net.h" +#include "units.h" + + +static int run(struct iperf_test *test); + + +/**************************************************************************/ +int +main(int argc, char **argv) +{ + struct iperf_test *test; + + /* + * Atomics check. We prefer to have atomic types (which is + * basically on any compiler supporting C11 or better). If we + * don't have them, we try to approximate the type we need with a + * regular integer, but complain if they're not lock-free. We only + * know how to check this on GCC. GCC on CentOS 7 / RHEL 7 is the + * targeted use case for these check. + */ +#ifndef HAVE_STDATOMIC_H +#ifdef __GNUC__ + if (! __atomic_always_lock_free (sizeof (u_int64_t), 0)) { +#endif // __GNUC__ + fprintf(stderr, "Warning: Cannot guarantee lock-free operation with 64-bit data types\n"); +#ifdef __GNUC__ + } +#endif // __GNUC__ +#endif // HAVE_STDATOMIC_H + + // XXX: Setting the process affinity requires root on most systems. + // Is this a feature we really need? +#ifdef TEST_PROC_AFFINITY + /* didn't seem to work.... */ + /* + * increasing the priority of the process to minimise packet generation + * delay + */ + int rc = setpriority(PRIO_PROCESS, 0, -15); + + if (rc < 0) { + perror("setpriority:"); + fprintf(stderr, "setting priority to valid level\n"); + rc = setpriority(PRIO_PROCESS, 0, 0); + } + + /* setting the affinity of the process */ + cpu_set_t cpu_set; + int affinity = -1; + int ncores = 1; + + sched_getaffinity(0, sizeof(cpu_set_t), &cpu_set); + if (errno) + perror("couldn't get affinity:"); + + if ((ncores = sysconf(_SC_NPROCESSORS_CONF)) <= 0) + err("sysconf: couldn't get _SC_NPROCESSORS_CONF"); + + CPU_ZERO(&cpu_set); + CPU_SET(affinity, &cpu_set); + if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) != 0) + err("couldn't change CPU affinity"); +#endif + + test = iperf_new_test(); + if (!test) + iperf_errexit(NULL, "create new test error - %s", iperf_strerror(i_errno)); + iperf_defaults(test); /* sets defaults */ + + if (iperf_parse_arguments(test, argc, argv) < 0) { + iperf_err(test, "parameter error - %s", iperf_strerror(i_errno)); + fprintf(stderr, "\n"); + usage(); + exit(1); + } + + if (run(test) < 0) + iperf_errexit(test, "error - %s", iperf_strerror(i_errno)); + + iperf_free_test(test); + + return 0; +} + + +static jmp_buf sigend_jmp_buf; + +static void __attribute__ ((noreturn)) +sigend_handler(int sig) +{ + longjmp(sigend_jmp_buf, 1); +} + +/**************************************************************************/ +static int +run(struct iperf_test *test) +{ + /* Termination signals. */ + iperf_catch_sigend(sigend_handler); + if (setjmp(sigend_jmp_buf)) + iperf_got_sigend(test); + + /* Ignore SIGPIPE to simplify error handling */ + signal(SIGPIPE, SIG_IGN); + + switch (test->role) { + case 's': + if (test->daemon) { + int rc; + rc = daemon(0, 0); + if (rc < 0) { + i_errno = IEDAEMON; + iperf_errexit(test, "error - %s", iperf_strerror(i_errno)); + } + } + if (iperf_create_pidfile(test) < 0) { + i_errno = IEPIDFILE; + iperf_errexit(test, "error - %s", iperf_strerror(i_errno)); + } + for (;;) { + int rc; + rc = iperf_run_server(test); + test->server_last_run_rc = rc; + if (rc < 0) { + iperf_err(test, "error - %s", iperf_strerror(i_errno)); + if (test->json_output) { + if (iperf_json_finish(test) < 0) + return -1; + } + iflush(test); + + if (rc < -1) { + iperf_errexit(test, "exiting"); + } + } + iperf_reset_test(test); + if (iperf_get_test_one_off(test) && rc != 2) { + /* Authentication failure doesn't count for 1-off test */ + if (rc < 0 && i_errno == IEAUTHTEST) { + continue; + } + break; + } + } + iperf_delete_pidfile(test); + break; + case 'c': + if (iperf_create_pidfile(test) < 0) { + i_errno = IEPIDFILE; + iperf_errexit(test, "error - %s", iperf_strerror(i_errno)); + } + if (iperf_run_client(test) < 0) + iperf_errexit(test, "error - %s", iperf_strerror(i_errno)); + iperf_delete_pidfile(test); + break; + default: + usage(); + break; + } + + iperf_catch_sigend(SIG_DFL); + signal(SIGPIPE, SIG_DFL); + + return 0; +} |