Merge pull request #1210 from esnet/issue-1157-take-2
Closes #1157. Incorporates and closes #1180.
This commit is contained in:
commit
9149c64b9e
12
src/iperf3.1
12
src/iperf3.1
@ -140,9 +140,12 @@ Note that when using this feature, a process will only be bound
|
||||
to a single CPU (as opposed to a set containing potentially multiple
|
||||
CPUs).
|
||||
.TP
|
||||
.BR -B ", " --bind " \fIhost\fR"
|
||||
.BR -B ", " --bind " \fIhost\fR[\fB%\fIdev\fR]"
|
||||
bind to the specific interface associated with address \fIhost\fR.
|
||||
.BR --bind-dev " \fIdev\R"
|
||||
If an optional interface is specified, it is treated as a shortcut
|
||||
for \fB--bind-dev \fIdev\fR.
|
||||
Note that a percent sign and interface device name are required for IPv6 link-local address literals.
|
||||
.BR --bind-dev " \fIdev\fR"
|
||||
bind to the specified network interface.
|
||||
This option uses SO_BINDTODEVICE, and may require root permissions.
|
||||
(Available on Linux and possibly other systems.)
|
||||
@ -229,10 +232,13 @@ time skew threshold (in seconds) between the server and client
|
||||
during the authentication process.
|
||||
.SH "CLIENT SPECIFIC OPTIONS"
|
||||
.TP
|
||||
.BR -c ", " --client " \fIhost\fR"
|
||||
.BR -c ", " --client " \fIhost\fR[\fB%\fIdev\fR]"
|
||||
run in client mode, connecting to the specified server.
|
||||
By default, a test consists of sending data from the client to the
|
||||
server, unless the \-R flag is specified.
|
||||
If an optional interface is specified, it is treated as a shortcut
|
||||
for \fB--bind-dev \fIdev\fR.
|
||||
Note that a percent sign and interface device name are required for IPv6 link-local address literals.
|
||||
.TP
|
||||
.BR --sctp
|
||||
use SCTP rather than TCP (FreeBSD and Linux)
|
||||
|
@ -925,6 +925,54 @@ iperf_on_test_finish(struct iperf_test *test)
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/*
|
||||
* iperf_parse_hostname tries to split apart a string into hostname %
|
||||
* interface parts, which are returned in **p and **p1, if they
|
||||
* exist. If the %interface part is detected, and it's not an IPv6
|
||||
* link local address, then returns 1, else returns 0.
|
||||
*
|
||||
* Modifies the string pointed to by spec in-place due to the use of
|
||||
* strtok(3). The caller should strdup(3) or otherwise copy the string
|
||||
* if an unmodified copy is needed.
|
||||
*/
|
||||
int
|
||||
iperf_parse_hostname(struct iperf_test *test, char *spec, char **p, char **p1) {
|
||||
struct in6_addr ipv6_addr;
|
||||
|
||||
// Format is <addr>[%<device>]
|
||||
if ((*p = strtok(spec, "%")) != NULL &&
|
||||
(*p1 = strtok(NULL, "%")) != NULL) {
|
||||
|
||||
/*
|
||||
* If an IPv6 literal for a link-local address, then
|
||||
* tell the caller to leave the "%" in the hostname.
|
||||
*/
|
||||
if (inet_pton(AF_INET6, *p, &ipv6_addr) == 1 &&
|
||||
IN6_IS_ADDR_LINKLOCAL(&ipv6_addr)) {
|
||||
if (test->debug) {
|
||||
iperf_printf(test, "IPv6 link-local address literal detected\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Other kind of address or FQDN. The interface name after
|
||||
* "%" is a shorthand for --bind-dev.
|
||||
*/
|
||||
else {
|
||||
if (test->debug) {
|
||||
iperf_printf(test, "p %s p1 %s\n", *p, *p1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (test->debug) {
|
||||
iperf_printf(test, "noparse\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
|
||||
{
|
||||
@ -1019,6 +1067,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
|
||||
char* comma;
|
||||
#endif /* HAVE_CPU_AFFINITY */
|
||||
char* slash;
|
||||
char *p, *p1;
|
||||
struct xbind_entry *xbe;
|
||||
double farg;
|
||||
int rcv_timeout_in = 0;
|
||||
@ -1101,6 +1150,18 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
|
||||
}
|
||||
iperf_set_test_role(test, 'c');
|
||||
iperf_set_test_server_hostname(test, optarg);
|
||||
|
||||
if (iperf_parse_hostname(test, optarg, &p, &p1)) {
|
||||
#if defined(HAVE_SO_BINDTODEVICE)
|
||||
/* Get rid of the hostname we saved earlier. */
|
||||
free(iperf_get_test_server_hostname(test));
|
||||
iperf_set_test_server_hostname(test, p);
|
||||
iperf_set_test_bind_dev(test, p1);
|
||||
#else /* HAVE_SO_BINDTODEVICE */
|
||||
i_errno = IEBINDDEVNOSUPPORT;
|
||||
return -1;
|
||||
#endif /* HAVE_SO_BINDTODEVICE */
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
set_protocol(test, Pudp);
|
||||
@ -1212,12 +1273,25 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
|
||||
test->settings->socket_bufsize = (int) farg;
|
||||
client_flag = 1;
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
test->bind_address = strdup(optarg);
|
||||
iperf_set_test_bind_address(test, optarg);
|
||||
|
||||
if (iperf_parse_hostname(test, optarg, &p, &p1)) {
|
||||
#if defined(HAVE_SO_BINDTODEVICE)
|
||||
/* Get rid of the hostname we saved earlier. */
|
||||
free(iperf_get_test_server_hostname(test));
|
||||
iperf_set_test_server_hostname(test, p);
|
||||
iperf_set_test_bind_dev(test, p1);
|
||||
#else /* HAVE_SO_BINDTODEVICE */
|
||||
i_errno = IEBINDDEVNOSUPPORT;
|
||||
return -1;
|
||||
#endif /* HAVE_SO_BINDTODEVICE */
|
||||
}
|
||||
break;
|
||||
#if defined (HAVE_SO_BINDTODEVICE)
|
||||
case OPT_BIND_DEV:
|
||||
test->bind_dev = strdup(optarg);
|
||||
iperf_set_test_bind_dev(test, optarg);
|
||||
break;
|
||||
#endif /* HAVE_SO_BINDTODEVICE */
|
||||
case OPT_CLIENT_PORT:
|
||||
|
@ -427,7 +427,9 @@ enum {
|
||||
IEAUTHTEST = 142, // Test authorization failed
|
||||
IEBINDDEV = 143, // Unable to bind-to-device (check perror, maybe permissions?)
|
||||
IENOMSG = 144, // No message was received for NO_MSG_RCVD_TIMEOUT time period
|
||||
IESETDONTFRAGMENT = 145, // Unable to set IP Do-Not-Fragment
|
||||
IESETDONTFRAGMENT = 145, // Unable to set IP Do-Not-Fragment
|
||||
IEBINDDEVNOSUPPORT = 146, // `ip%%dev` is not supported as system does not support bind to device
|
||||
IEHOSTDEV = 147, // host device name (ip%%<dev>) is supported (and required) only for IPv6 link-local address
|
||||
/* Stream errors */
|
||||
IECREATESTREAM = 200, // Unable to create a new stream (check herror/perror)
|
||||
IEINITSTREAM = 201, // Unable to initialize stream (check herror/perror)
|
||||
|
@ -438,6 +438,15 @@ iperf_strerror(int int_errno)
|
||||
case IEIDLETIMEOUT:
|
||||
snprintf(errstr, len, "idle timeout parameter is not positive or larger than allowed limit");
|
||||
break;
|
||||
case IEBINDDEV:
|
||||
snprintf(errstr, len, "Unable to bind-to-device (check perror, maybe permissions?)");
|
||||
break;
|
||||
case IEBINDDEVNOSUPPORT:
|
||||
snprintf(errstr, len, "`<ip>%%<dev>` is not supported as system does not support bind to device");
|
||||
break;
|
||||
case IEHOSTDEV:
|
||||
snprintf(errstr, len, "host device name (ip%%<dev>) is supported (and required) only for IPv6 link-local address");
|
||||
break;
|
||||
case IENOMSG:
|
||||
snprintf(errstr, len, "idle timeout for receiving data");
|
||||
break;
|
||||
|
@ -105,9 +105,12 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n"
|
||||
#if defined(HAVE_CPU_AFFINITY)
|
||||
" -A, --affinity n/n,m set CPU affinity\n"
|
||||
#endif /* HAVE_CPU_AFFINITY */
|
||||
" -B, --bind <host> bind to the interface associated with the address <host>\n"
|
||||
#if defined(HAVE_SO_BINDTODEVICE)
|
||||
" --bind-dev <dev> bind to the network interface with SO_BINDTODEVICE\n"
|
||||
" -B, --bind <host>[%<dev>] bind to the interface associated with the address <host>\n"
|
||||
" (optional <dev> equivalent to `--bind-dev <dev>`)\n"
|
||||
" --bind-dev <dev> bind to the network interface with SO_BINDTODEVICE\n"
|
||||
#else /* HAVE_SO_BINDTODEVICE */
|
||||
" -B, --bind <host> bind to the interface associated with the address <host>\n"
|
||||
#endif /* HAVE_SO_BINDTODEVICE */
|
||||
" -V, --verbose more detailed output\n"
|
||||
" -J, --json output in JSON format\n"
|
||||
@ -139,7 +142,8 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n"
|
||||
" and client during the authentication process\n"
|
||||
#endif //HAVE_SSL
|
||||
"Client specific:\n"
|
||||
" -c, --client <host> run in client mode, connecting to <host>\n"
|
||||
" -c, --client <host>[%<dev>] run in client mode, connecting to <host>\n"
|
||||
" (option <dev> equivalent to `--bind-dev <dev>`)\n"
|
||||
#if defined(HAVE_SCTP_H)
|
||||
" --sctp use SCTP rather than TCP\n"
|
||||
" -X, --xbind <name> bind SCTP association to links\n"
|
||||
|
Loading…
x
Reference in New Issue
Block a user