1
1
Attempt to fix some brokenness in -F from #301.

In some work related to #125, we introduced a bug in which
chunks of a file being read for the -F option were not
completely sent, particularly with TCP sockets.  We attempt
to fix this by detecting cases in which not all data passed
to a socket could be actually sent (for example due to full
socket buffers) and preserving that data for future send
iterations.

The ending statistics in the "diskfile" JSON structure were
wrong, and did not properly distinguish between sender-side
and receiver-side statistics.  This has been fixed (at least
for the client side).

Specifically mention in the manpage that "iperf -F" is not
a file transfer tool.
Этот коммит содержится в:
Bruce A. Mah 2017-05-30 14:15:28 -07:00 коммит произвёл GitHub
родитель acb4c4c9d5
Коммит c458a115b7
5 изменённых файлов: 62 добавлений и 13 удалений

Просмотреть файл

@ -153,6 +153,7 @@ struct iperf_stream
int buffer_fd; /* data to send, file descriptor */
char *buffer; /* data to send, mmapped */
int diskfile_fd; /* file to send, file descriptor */
int diskfile_left; /* remaining file data on disk */
/*
* for udp measurements - This can be a structure outside stream, and

Просмотреть файл

@ -30,10 +30,13 @@ pause \fIn\fR seconds between periodic throughput reports;
default is 1, use 0 to disable
.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
Use a file as the source (on the sender) or sink (on the receiver) of
data, rather than just generating random data or throwing it away.
This feature is used for finding whether or not the storage subsystem
is the bottleneck for file transfers.
It does not turn iperf3 into a file transfer tool.
The length, attributes, and in some cases contents of the received
file may not match those of the original file.
.TP
.BR -A ", " --affinity " \fIn/n,m\fR"
Set the CPU affinity, if possible (Linux and FreeBSD only).

Просмотреть файл

@ -2743,15 +2743,22 @@ iperf_print_results(struct iperf_test *test)
if (sp->diskfile_fd >= 0) {
if (fstat(sp->diskfile_fd, &sb) == 0) {
/* In the odd case that it's a zero-sized file, say it was all transferred. */
int percent = 100;
int percent_sent = 100, percent_received = 100;
if (sb.st_size > 0) {
percent = (int) ( ( (double) bytes_sent / (double) sb.st_size ) * 100.0 );
percent_sent = (int) ( ( (double) bytes_sent / (double) sb.st_size ) * 100.0 );
percent_received = (int) ( ( (double) bytes_received / (double) sb.st_size ) * 100.0 );
}
unit_snprintf(sbuf, UNIT_LEN, (double) sb.st_size, 'A');
if (test->json_output)
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));
cJSON_AddItemToObject(json_summary_stream, "diskfile", iperf_json_printf("sent: %d received: %d size: %d percent_sent: %d percent_received: %d filename: %s", (int64_t) bytes_sent, (int64_t) bytes_received, (int64_t) sb.st_size, (int64_t) percent_sent, (int64_t) percent_received, test->diskfile_name));
else
iperf_printf(test, report_diskfile, ubuf, sbuf, percent, test->diskfile_name);
if (test->sender) {
iperf_printf(test, report_diskfile, ubuf, sbuf, percent_sent, test->diskfile_name);
}
else {
unit_snprintf(ubuf, UNIT_LEN, (double) bytes_received, 'A');
iperf_printf(test, report_diskfile, ubuf, sbuf, percent_received, test->diskfile_name);
}
}
}
@ -3281,12 +3288,44 @@ static int
diskfile_send(struct iperf_stream *sp)
{
int r;
static int rtot;
r = read(sp->diskfile_fd, sp->buffer, sp->test->settings->blksize);
if (r == 0)
sp->test->done = 1;
else
r = sp->snd2(sp);
/* if needed, read enough data from the disk to fill up the buffer */
if (sp->diskfile_left < sp->test->settings->blksize && !sp->test->done) {
r = read(sp->diskfile_fd, sp->buffer, sp->test->settings->blksize -
sp->diskfile_left);
rtot += r;
if (sp->test->debug) {
printf("read %d bytes from file, %d total\n", r, rtot);
if (r != sp->test->settings->blksize - sp->diskfile_left)
printf("possible eof\n");
}
/* If there's no data left in the file or in the buffer, we're done */
if (r == 0 && sp->diskfile_left == 0) {
sp->test->done = 1;
if (sp->test->debug)
printf("done\n");
}
}
r = sp->snd2(sp);
if (r < 0) {
return r;
}
/*
* Compute how much data is in the buffer but didn't get sent.
* If there are bytes that got left behind, slide them to the
* front of the buffer so they can hopefully go out on the next
* pass.
*/
sp->diskfile_left = sp->test->settings->blksize - r;
if (sp->diskfile_left && sp->diskfile_left < sp->test->settings->blksize) {
memcpy(sp->buffer,
sp->buffer + (sp->test->settings->blksize - sp->diskfile_left),
sp->diskfile_left);
if (sp->test->debug)
printf("Shifting %d bytes by %d\n", sp->diskfile_left, (sp->test->settings->blksize - sp->diskfile_left));
}
return r;
}

Просмотреть файл

@ -89,6 +89,9 @@ iperf_tcp_send(struct iperf_stream *sp)
sp->result->bytes_sent += r;
sp->result->bytes_sent_this_interval += r;
if (sp->test->debug)
printf("sent %d bytes of %d, total %lu\n", r, sp->settings->blksize, sp->result->bytes_sent);
return r;
}

Просмотреть файл

@ -187,6 +187,9 @@ iperf_udp_send(struct iperf_stream *sp)
sp->result->bytes_sent += r;
sp->result->bytes_sent_this_interval += r;
if (sp->test->debug)
printf("sent %d bytes of %d, total %lu\n", r, sp->settings->blksize, sp->result->bytes_sent);
return r;
}