Fix -F problems (#588)
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.
Этот коммит содержится в:
родитель
acb4c4c9d5
Коммит
c458a115b7
@ -153,6 +153,7 @@ struct iperf_stream
|
|||||||
int buffer_fd; /* data to send, file descriptor */
|
int buffer_fd; /* data to send, file descriptor */
|
||||||
char *buffer; /* data to send, mmapped */
|
char *buffer; /* data to send, mmapped */
|
||||||
int diskfile_fd; /* file to send, file descriptor */
|
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
|
* for udp measurements - This can be a structure outside stream, and
|
||||||
|
11
src/iperf3.1
11
src/iperf3.1
@ -30,10 +30,13 @@ pause \fIn\fR seconds between periodic throughput reports;
|
|||||||
default is 1, use 0 to disable
|
default is 1, use 0 to disable
|
||||||
.TP
|
.TP
|
||||||
.BR -F ", " --file " \fIname\fR"
|
.BR -F ", " --file " \fIname\fR"
|
||||||
client-side: read from the file and write to the network, instead
|
Use a file as the source (on the sender) or sink (on the receiver) of
|
||||||
of using random data;
|
data, rather than just generating random data or throwing it away.
|
||||||
server-side: read from the network and write to the file, instead
|
This feature is used for finding whether or not the storage subsystem
|
||||||
of throwing the data away
|
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
|
.TP
|
||||||
.BR -A ", " --affinity " \fIn/n,m\fR"
|
.BR -A ", " --affinity " \fIn/n,m\fR"
|
||||||
Set the CPU affinity, if possible (Linux and FreeBSD only).
|
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 (sp->diskfile_fd >= 0) {
|
||||||
if (fstat(sp->diskfile_fd, &sb) == 0) {
|
if (fstat(sp->diskfile_fd, &sb) == 0) {
|
||||||
/* In the odd case that it's a zero-sized file, say it was all transferred. */
|
/* 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) {
|
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');
|
unit_snprintf(sbuf, UNIT_LEN, (double) sb.st_size, 'A');
|
||||||
if (test->json_output)
|
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
|
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)
|
diskfile_send(struct iperf_stream *sp)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
static int rtot;
|
||||||
|
|
||||||
r = read(sp->diskfile_fd, sp->buffer, sp->test->settings->blksize);
|
/* if needed, read enough data from the disk to fill up the buffer */
|
||||||
if (r == 0)
|
if (sp->diskfile_left < sp->test->settings->blksize && !sp->test->done) {
|
||||||
sp->test->done = 1;
|
r = read(sp->diskfile_fd, sp->buffer, sp->test->settings->blksize -
|
||||||
else
|
sp->diskfile_left);
|
||||||
r = sp->snd2(sp);
|
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;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,6 +89,9 @@ iperf_tcp_send(struct iperf_stream *sp)
|
|||||||
sp->result->bytes_sent += r;
|
sp->result->bytes_sent += r;
|
||||||
sp->result->bytes_sent_this_interval += 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;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,6 +187,9 @@ iperf_udp_send(struct iperf_stream *sp)
|
|||||||
sp->result->bytes_sent += r;
|
sp->result->bytes_sent += r;
|
||||||
sp->result->bytes_sent_this_interval += 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;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Загрузка…
Ссылка в новой задаче
Block a user