Added the -F / --file flag, to use a specified file instead

of random data for sending, and to save the data in the file
on receiving.
This commit is contained in:
Jef Poskanzer 2013-10-19 07:43:38 -07:00
parent 36662029e5
commit e32a7bcd77
7 changed files with 75 additions and 1 deletions

View File

@ -88,6 +88,7 @@ struct iperf_stream
int green_light;
int buffer_fd; /* data to send, file descriptor */
char *buffer; /* data to send, mmapped */
int diskfile_fd; /* file to send, file descriptor */
/*
* for udp measurements - This can be a structure outside stream, and
@ -107,6 +108,10 @@ struct iperf_stream
int (*rcv) (struct iperf_stream * stream);
int (*snd) (struct iperf_stream * stream);
/* chained send/receive routines for -F mode */
int (*rcv2) (struct iperf_stream * stream);
int (*snd2) (struct iperf_stream * stream);
// struct iperf_stream *next;
SLIST_ENTRY(iperf_stream) streams;
@ -137,6 +142,7 @@ struct iperf_test
int server_port;
int omit; /* duration of omit period (-O flag) */
int duration; /* total duration of test (-t flag) */
char *diskfile_name; /* -F option */
int ctrl_sck;
int listener;

View File

@ -28,6 +28,12 @@ set server port to listen on/connect to to \fIn\fR (default 5201)
.BR -i ", " --interval " \fIn\fR"
pause \fIn\fR seconds between periodic bandwidth reports
.TP
.BR -F ", " --file " \fIname\fR"
client-side: read from the file and write to the network, instead
of using random data;
server-side: read from the network and write to the file, instead
of throwing the data away
.TP
.BR -V ", " --verbose " "
give more detailed output
.TP

View File

@ -51,6 +51,8 @@ static int send_parameters(struct iperf_test *test);
static int get_parameters(struct iperf_test *test);
static int send_results(struct iperf_test *test);
static int get_results(struct iperf_test *test);
static int diskfile_send(struct iperf_stream *sp);
static int diskfile_recv(struct iperf_stream *sp);
static int JSON_write(int fd, cJSON *json);
static void print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *json_interval_streams);
static cJSON *JSON_read(int fd);
@ -516,6 +518,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
{"flowlabel", required_argument, NULL, 'L'},
{"zerocopy", no_argument, NULL, 'Z'},
{"omit", required_argument, NULL, 'O'},
{"file", required_argument, NULL, 'F'},
{"help", no_argument, NULL, 'h'},
/* XXX: The following ifdef needs to be split up. linux-congestion is not
@ -532,7 +535,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
blksize = 0;
server_flag = client_flag = rate_flag = 0;
while ((flag = getopt_long(argc, argv, "p:f:i:DVJdvsc:ub:t:n:l:P:Rw:B:M:N46S:L:ZO:h", longopts, NULL)) != -1) {
while ((flag = getopt_long(argc, argv, "p:f:i:DVJdvsc:ub:t:n:l:P:Rw:B:M:N46S:L:ZO:F:h", longopts, NULL)) != -1) {
switch (flag) {
case 'p':
test->server_port = atoi(optarg);
@ -680,6 +683,9 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
}
client_flag = 1;
break;
case 'F':
test->diskfile_name = optarg;
break;
case 'h':
default:
usage_long();
@ -1344,6 +1350,7 @@ iperf_defaults(struct iperf_test *testp)
testp->omit = OMIT;
testp->duration = DURATION;
testp->diskfile_name = (char*) 0;
testp->server_port = PORT;
testp->ctrl_sck = -1;
testp->prot_listener = -1;
@ -1488,6 +1495,7 @@ iperf_reset_test(struct iperf_test *test)
set_protocol(test, Ptcp);
test->omit = OMIT;
test->duration = DURATION;
test->diskfile_name = (char*) 0;
test->state = 0;
test->server_hostname = NULL;
@ -1889,6 +1897,8 @@ iperf_free_stream(struct iperf_stream *sp)
/* XXX: need to free interval list too! */
munmap(sp->buffer, sp->test->settings->blksize);
close(sp->buffer_fd);
if (sp->diskfile_fd >= 0)
close(sp->diskfile_fd);
for (irp = TAILQ_FIRST(&sp->result->interval_results); irp != TAILQ_END(sp->result->interval_results); irp = nirp) {
nirp = TAILQ_NEXT(irp, irlistentries);
free(irp);
@ -1958,6 +1968,19 @@ iperf_new_stream(struct iperf_test *test, int s)
sp->snd = test->protocol->send;
sp->rcv = test->protocol->recv;
if (test->diskfile_name != (char*) 0) {
sp->diskfile_fd = open(test->diskfile_name, test->sender ? O_RDONLY : (O_WRONLY|O_CREAT|O_TRUNC));
if (sp->diskfile_fd == -1) {
i_errno = IEFILE;
return NULL;
}
sp->snd2 = sp->snd;
sp->snd = diskfile_send;
sp->rcv2 = sp->rcv;
sp->rcv = diskfile_recv;
} else
sp->diskfile_fd = -1;
/* Initialize stream */
if (iperf_init_stream(sp, test) < 0)
return NULL;
@ -2029,6 +2052,38 @@ iperf_add_stream(struct iperf_test *test, struct iperf_stream *sp)
}
}
/* This pair of routines gets inserted into the snd/rcv function pointers
** when there's a -F flag. They handle the file stuff and call the real
** snd/rcv functions, which have been saved in snd2/rcv2.
**
** The advantage of doing it this way is that in the much more common
** case of no -F flag, there is zero extra overhead.
*/
static int
diskfile_send(struct iperf_stream *sp)
{
int r;
r = read(sp->diskfile_fd, sp->buffer, sp->test->settings->blksize);
if (r == 0)
sp->test->done = 1;
else
r = sp->snd2(sp);
return r;
}
static int
diskfile_recv(struct iperf_stream *sp)
{
int r;
r = sp->rcv2(sp);
if (r > 0)
(void) write(sp->diskfile_fd, sp->buffer, r);
return r;
}
void
sig_handler(int sig)
{

View File

@ -230,6 +230,7 @@ enum {
IENOSENDFILE = 11, // This OS does not support sendfile
IEOMIT = 12, // Bogus value for --omit
IEUNIMP = 13, // Not implemented yet
IEFILE = 14, // -F file couldn't be opened
/* Test errors */
IENEWTEST = 100, // Unable to create a new test (check perror)
IEINITTEST = 101, // Test initialization failed (check perror)

View File

@ -105,6 +105,10 @@ iperf_strerror(int i_errno)
case IEUNIMP:
snprintf(errstr, len, "an option you are trying to set is not implemented yet");
break;
case IEFILE:
snprintf(errstr, len, "unable to open -F file");
perr = 1;
break;
case IENEWTEST:
snprintf(errstr, len, "unable to create a new test");
perr = 1;

View File

@ -254,6 +254,7 @@ iperf_test_reset(struct iperf_test *test)
set_protocol(test, Ptcp);
test->omit = OMIT;
test->duration = DURATION;
test->diskfile_name = (char*) 0;
test->state = 0;
test->server_hostname = NULL;

View File

@ -99,6 +99,7 @@ const char usage_longstr[] = "Usage: iperf [-s|-c host] [options]\n"
/* " -L, --flowlabel N set the IPv6 'flow label'\n" */
" -Z, --zerocopy use a 'zero copy' method of sending data\n"
" -O, --omit N omit the first n seconds\n"
" -F, --file name xmit/recv the specified file\n"
#ifdef NOT_YET_SUPPORTED /* still working on these */
" -D, --daemon run the server as a daemon\n"