From 8430ad49e64446668b1305341129e173dc3c2eb0 Mon Sep 17 00:00:00 2001 From: sethdelliott Date: Mon, 19 Jul 2010 19:45:08 +0000 Subject: [PATCH] Added iperf error code (iperf_error.*). Also added iperf_parse_parameters(). --- src/Makefile.old | 2 +- src/iperf.h | 6 +- src/iperf_api.c | 204 ++++++++++++++++++++++++++++++++++++++++++++++ src/iperf_api.h | 1 + src/iperf_error.c | 41 ++++++++++ src/iperf_error.h | 25 ++++++ src/main.c | 162 ++---------------------------------- 7 files changed, 285 insertions(+), 156 deletions(-) create mode 100644 src/iperf_error.c create mode 100644 src/iperf_error.h diff --git a/src/Makefile.old b/src/Makefile.old index 6d8b4ac48..38e3b15ee 100644 --- a/src/Makefile.old +++ b/src/Makefile.old @@ -1,5 +1,5 @@ CFLAGS=-g -Wall -OBJS=main.o iperf_api.o iperf_server_api.o iperf_tcp.o iperf_udp.o timer.o net.o tcp_window_size.o units.o iperf_util.o tcp_info.o locale.o +OBJS=main.o iperf_api.o iperf_server_api.o iperf_tcp.o iperf_udp.o timer.o net.o tcp_window_size.o units.o iperf_util.o tcp_info.o locale.o iperf_error.o LDFLAGS= UNAME=$(shell uname) diff --git a/src/iperf.h b/src/iperf.h index dbb06797b..5f9b3a953 100644 --- a/src/iperf.h +++ b/src/iperf.h @@ -4,10 +4,12 @@ approvals from the U.S. Dept. of Energy). All rights reserved. */ -#ifndef __IPERF_H -#define __IPERF_H +#ifndef __IPERF_H +#define __IPERF_H #include +#include +#include #include #include diff --git a/src/iperf_api.c b/src/iperf_api.c index 719a4a569..43a385630 100644 --- a/src/iperf_api.c +++ b/src/iperf_api.c @@ -32,6 +32,7 @@ #include "iperf_api.h" #include "iperf_udp.h" #include "iperf_tcp.h" +#include "iperf_error.h" #include "timer.h" #include "net.h" #include "units.h" @@ -56,6 +57,209 @@ usage_long() fprintf(stderr, usage_long2); } +int +iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) +{ + static struct option longopts[] = + { + {"client", required_argument, NULL, 'c'}, + {"server", no_argument, NULL, 's'}, + {"time", required_argument, NULL, 't'}, + {"port", required_argument, NULL, 'p'}, + {"parallel", required_argument, NULL, 'P'}, + {"udp", no_argument, NULL, 'u'}, + {"tcpInfo", no_argument, NULL, 'T'}, + {"bandwidth", required_argument, NULL, 'b'}, + {"length", required_argument, NULL, 'l'}, + {"window", required_argument, NULL, 'w'}, + {"interval", required_argument, NULL, 'i'}, + {"bytes", required_argument, NULL, 'n'}, + {"NoDelay", no_argument, NULL, 'N'}, + {"Print-mss", no_argument, NULL, 'm'}, + {"Set-mss", required_argument, NULL, 'M'}, + {"version", no_argument, NULL, 'v'}, + {"verbose", no_argument, NULL, 'V'}, + {"debug", no_argument, NULL, 'd'}, + {"help", no_argument, NULL, 'h'}, + {"daemon", no_argument, NULL, 'D'}, + {"format", required_argument, NULL, 'f'}, + {"reverse", no_argument, NULL, 'R'}, + + /* XXX: The following ifdef needs to be split up. linux-congestion is not necessarily supported + * by systems that support tos. + */ +#ifdef ADD_WHEN_SUPPORTED + {"tos", required_argument, NULL, 'S'}, + {"linux-congestion", required_argument, NULL, 'Z'}, +#endif + {NULL, 0, NULL, 0} + }; + char ch; + + while ((ch = getopt_long(argc, argv, "c:p:st:uP:b:l:w:i:n:mRNTvhVdM:f:", longopts, NULL)) != -1) { + switch (ch) { + case 'c': + if (test->role == 's') { + ierrno = IESERVCLIENT; + return (-1); + } else { + test->role = 'c'; + test->server_hostname = (char *) malloc(strlen(optarg)+1); + strncpy(test->server_hostname, optarg, strlen(optarg)); + } + break; + case 'p': + test->server_port = atoi(optarg); + break; + case 's': + if (test->role == 'c') { + ierrno = IESERVCLIENT; + return (-1); + } else { + test->role = 's'; + } + break; + case 't': + if (test->role == 's') { + ierrno = IECLIENTONLY; + return (-1); + } + test->duration = atoi(optarg); + if (test->duration > MAX_TIME) { + ierrno = IEDURATION; + return (-1); + } + break; + case 'u': + if (test->role == 's') { + ierrno = IECLIENTONLY; + return (-1); + } + test->protocol = Pudp; + test->default_settings->blksize = DEFAULT_UDP_BLKSIZE; + test->new_stream = iperf_new_udp_stream; + break; + case 'P': + if (test->role == 's') { + ierrno = IECLIENTONLY; + return (-1); + } + test->num_streams = atoi(optarg); + if (test->num_streams > MAX_STREAMS) { + ierrno = IENUMSTREAMS; + return (-1); + } + break; + case 'b': + if (test->role == 's') { + ierrno = IECLIENTONLY; + return (-1); + } + test->default_settings->rate = unit_atof(optarg); + break; + case 'l': + if (test->role == 's') { + ierrno = IECLIENTONLY; + return (-1); + } + test->default_settings->blksize = unit_atoi(optarg); + if (test->default_settings->blksize > MAX_BLOCKSIZE) { + ierrno = IEBLOCKSIZE; + return (-1); + } + break; + case 'w': + // XXX: This is a socket buffer, not specific to TCP + if (test->role == 's') { + ierrno = IECLIENTONLY; + return (-1); + } + test->default_settings->socket_bufsize = unit_atof(optarg); + if (test->default_settings->socket_bufsize > MAX_TCP_BUFFER) { + ierrno = IEBUFSIZE; + return (-1); + } + break; + case 'i': + /* XXX: could potentially want separate stat collection and reporting intervals, + but just set them to be the same for now */ + test->stats_interval = atoi(optarg); + test->reporter_interval = atoi(optarg); + if (test->stats_interval > MAX_INTERVAL) { + ierrno = IEINTERVAL; + return (-1); + } + break; + case 'n': + if (test->role == 's') { + ierrno = IECLIENTONLY; + return (-1); + } + test->default_settings->bytes = unit_atoi(optarg); + break; + case 'm': + test->print_mss = 1; + break; + case 'N': + if (test->role == 's') { + ierrno = IECLIENTONLY; + return (-1); + } + test->no_delay = 1; + break; + case 'M': + if (test->role == 's') { + ierrno = IECLIENTONLY; + return (-1); + } + test->default_settings->mss = atoi(optarg); + if (test->default_settings->mss > MAX_MSS) { + ierrno = IEMSS; + return (-1); + } + break; + case 'f': + test->default_settings->unit_format = *optarg; + break; + case 'T': + test->tcp_info = 1; + break; + case 'V': + test->verbose = 1; + break; + case 'd': + test->debug = 1; + break; + case 'R': + if (test->role == 's') { + ierrno = IECLIENTONLY; + return (-1); + } + test->reverse = 1; + break; + case 'v': + printf(version); + exit(0); + case 'h': + default: + usage_long(); + exit(1); + } + } + /* For subsequent calls to getopt */ +#ifdef __APPLE__ + optreset = 1; +#endif + optind = 0; + + if ((test->role != 'c') && (test->role != 's')) { + ierrno = IENOROLE; + return (-1); + } + + return (0); +} + int all_data_sent(struct iperf_test * test) { diff --git a/src/iperf_api.h b/src/iperf_api.h index 609fd3567..0d8aca95d 100644 --- a/src/iperf_api.h +++ b/src/iperf_api.h @@ -133,6 +133,7 @@ int iperf_handle_message_client(struct iperf_test *); int iperf_exchange_results(struct iperf_test *); int parse_results(struct iperf_test *, char *); void iperf_init_test(struct iperf_test *); +int iperf_parse_arguments(struct iperf_test *, int, char **); #endif diff --git a/src/iperf_error.c b/src/iperf_error.c new file mode 100644 index 000000000..a755b942e --- /dev/null +++ b/src/iperf_error.c @@ -0,0 +1,41 @@ +#include +#include "iperf.h" +#include "iperf_error.h" + +int ierrno; + +void +ierror(char *estr) +{ + fprintf(stderr, "%s: ", estr); + + switch (ierrno) { + case IESERVCLIENT: + fprintf(stderr, "iperf cannot be both server and client\n"); + break; + case IENOROLE: + fprintf(stderr, "iperf instance must either be a client (-c) or server (-s)\n"); + break; + case IECLIENTONLY: + fprintf(stderr, "some option you are trying to set is client only\n"); + break; + case IEDURATION: + fprintf(stderr, "test duration too long (maximum = %d seconds)\n", MAX_TIME); + break; + case IENUMSTREAMS: + fprintf(stderr, "number of parallel streams too large (maximum = %d)\n", MAX_STREAMS); + break; + case IEBLOCKSIZE: + fprintf(stderr, "block size too large (maximum = %d bytes)\n", MAX_BLOCKSIZE); + break; + case IEBUFSIZE: + fprintf(stderr, "socket buffer size too large (maximum = %d bytes)\n", MAX_TCP_BUFFER); + break; + case IEINTERVAL: + fprintf(stderr, "report interval too large (maximum = %d seconds)\n", MAX_INTERVAL); + break; + case IEMSS: + fprintf(stderr, "TCP MSS too large (maximum = %d bytes)\n", MAX_MSS); + break; + } +} diff --git a/src/iperf_error.h b/src/iperf_error.h new file mode 100644 index 000000000..50e99e6d9 --- /dev/null +++ b/src/iperf_error.h @@ -0,0 +1,25 @@ +/* iperf_error.h + * + * Iperf error handling + */ + +#ifndef __IPERF_ERROR_H +#define __IPERF_ERROR_H + +void ierror(char *); + +extern int ierrno; + +enum { + IESERVCLIENT = 1, // Iperf cannot be both server and client + IENOROLE = 2, // Iperf must either be a client (-c) or server (-s) + IECLIENTONLY = 3, // This option is client only + IEDURATION = 4, // test duration too long. Maximum value = %dMAX_TIME + IENUMSTREAMS = 5, // Number of parallel streams too large. Maximum value = %dMAX_STREAMS + IEBLOCKSIZE = 6, // Block size too large. Maximum value = %dMAX_BLOCKSIZE + IEBUFSIZE = 7, // Socket buffer size too large. Maximum value = %dMAX_TCP_BUFFER + IEINTERVAL = 8, // Report interval too large. Maxumum value = %dMAX_INTERVAL + IEMSS = 9, // MSS too large. Maximum value = %dMAX_MSS +}; + +#endif diff --git a/src/main.c b/src/main.c index 887a757e2..71e2c0c5a 100644 --- a/src/main.c +++ b/src/main.c @@ -27,49 +27,13 @@ #include "iperf_server_api.h" #include "units.h" #include "locale.h" +#include "iperf_error.h" int iperf_run(struct iperf_test *); /**************************************************************************/ -static struct option longopts[] = -{ - {"client", required_argument, NULL, 'c'}, - {"server", no_argument, NULL, 's'}, - {"time", required_argument, NULL, 't'}, - {"port", required_argument, NULL, 'p'}, - {"parallel", required_argument, NULL, 'P'}, - {"udp", no_argument, NULL, 'u'}, - {"tcpInfo", no_argument, NULL, 'T'}, - {"bandwidth", required_argument, NULL, 'b'}, - {"length", required_argument, NULL, 'l'}, - {"window", required_argument, NULL, 'w'}, - {"interval", required_argument, NULL, 'i'}, - {"bytes", required_argument, NULL, 'n'}, - {"NoDelay", no_argument, NULL, 'N'}, - {"Print-mss", no_argument, NULL, 'm'}, - {"Set-mss", required_argument, NULL, 'M'}, - {"version", no_argument, NULL, 'v'}, - {"verbose", no_argument, NULL, 'V'}, - {"debug", no_argument, NULL, 'd'}, - {"help", no_argument, NULL, 'h'}, - {"daemon", no_argument, NULL, 'D'}, - {"format", required_argument, NULL, 'f'}, - {"reverse", no_argument, NULL, 'R'}, - -/* The following ifdef needs to be split up. linux-congestion is not necessarily supported - * by systems that support tos. - */ -#ifdef ADD_WHEN_SUPPORTED - {"tos", required_argument, NULL, 'S'}, - {"linux-congestion", required_argument, NULL, 'Z'}, -#endif - {NULL, 0, NULL, 0} -}; - -/**************************************************************************/ - int main(int argc, char **argv) { @@ -77,6 +41,8 @@ main(int argc, char **argv) struct iperf_test *test; int port = PORT; + // XXX: Setting the process affinity requires root on most systems. + // Is this a feature we really need? #ifdef TEST_PROC_AFFINITY /* didnt seem to work.... */ /* @@ -112,126 +78,16 @@ main(int argc, char **argv) test = iperf_new_test(); iperf_defaults(test); /* sets defaults */ - while ((ch = getopt_long(argc, argv, "c:p:st:uP:b:l:w:i:n:mRNTvhVdM:f:", longopts, NULL)) != -1) { - switch (ch) { - case 'c': - test->role = 'c'; - role = test->role; - test->server_hostname = (char *) malloc(strlen(optarg)+1); - strncpy(test->server_hostname, optarg, strlen(optarg)); - break; - case 'p': - test->server_port = atoi(optarg); - port = test->server_port; - break; - case 's': - test->role = 's'; - role = test->role; - break; - case 't': - test->duration = atoi(optarg); - if (test->duration > MAX_TIME) { - fprintf(stderr, "\n Error: test duration too long. Maximum value = %d \n\n", (int)MAX_TIME); - usage_long(); - exit(1); - } - break; - case 'u': - test->protocol = Pudp; - test->default_settings->blksize = DEFAULT_UDP_BLKSIZE; - test->new_stream = iperf_new_udp_stream; - break; - case 'P': - test->num_streams = atoi(optarg); - if (test->num_streams > MAX_STREAMS) { - fprintf(stderr, "\n Error: Number of parallel streams too large. Maximum value = %d \n\n", MAX_STREAMS); - usage_long(); - exit(1); - } - break; - case 'b': - test->default_settings->rate = unit_atof(optarg); - break; - case 'l': - test->default_settings->blksize = unit_atoi(optarg); - if (test->default_settings->blksize > MAX_BLOCKSIZE) { - fprintf(stderr, "\n Error: Block size too large. Maximum value = %d \n\n", MAX_BLOCKSIZE); - usage_long(); - exit(1); - } - break; - case 'w': - test->default_settings->socket_bufsize = unit_atof(optarg); - if (test->default_settings->socket_bufsize > MAX_TCP_BUFFER) { - fprintf(stderr, "\n Error: TCP buffer too large. Maximum value = %d \n\n", MAX_TCP_BUFFER); - usage_long(); - exit(1); - } - break; - case 'i': - /* could potentially want separate stat collection and reporting intervals, - but just set them to be the same for now */ - test->stats_interval = atoi(optarg); - test->reporter_interval = atoi(optarg); - if (test->stats_interval > MAX_INTERVAL) { - fprintf(stderr, "\n Error: Report interval too large. Maximum value = %d \n\n", MAX_INTERVAL); - usage_long(); - exit(1); - } - break; - case 'n': - test->default_settings->bytes = unit_atoi(optarg); - printf("total bytes to be transferred = %llu\n", test->default_settings->bytes); - break; - case 'm': - test->print_mss = 1; - break; - case 'N': - test->no_delay = 1; - break; - case 'M': - test->default_settings->mss = atoi(optarg); - if (test->default_settings->mss > MAX_MSS) { - fprintf(stderr, "\n Error: MSS too large. Maximum value = %d \n\n", MAX_MSS); - usage_long(); - exit(1); - } - break; - case 'f': - test->default_settings->unit_format = *optarg; - break; - case 'T': - test->tcp_info = 1; - break; - case 'V': - test->verbose = 1; - break; - case 'd': - test->debug = 1; - break; - case 'R': - test->reverse = 1; - break; - case 'v': - printf(version); - exit(0); - case 'h': - default: - usage_long(); - exit(1); - } + if (iperf_parse_arguments(test, argc, argv) < 0) { + ierror("parameter error"); + fprintf(stderr, "\n"); + usage_long(); + exit(1); } - /* For subsequent calls to getopt */ -#ifdef __APPLE__ - optreset = 1; -#endif - optind = 0; - - if (iperf_run(test) < 0) { fprintf(stderr, "An error occurred. Exiting...\n"); - return -1; + exit(1); } iperf_free_test(test);