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 */
|
||||
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
|
||||
|
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
|
||||
.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;
|
||||
}
|
||||
|
||||
|
Загрузка…
Ссылка в новой задаче
Block a user