Support setting the IPv6 flow label on Linux systems (only).
This functionality uses some setsockopt(2) calls that unfortunately don't seem to have an analog on other platforms. Slightly tweaked version of a patch that was... Submitted by: ssahani@redhat.com Issue: 40 (Option for setting Flow Label field in IPv6 header)
Этот коммит содержится в:
родитель
c8a0a2229d
Коммит
d04c7bd0a4
@ -109,9 +109,9 @@ only use IPv6
|
||||
.TP
|
||||
.BR -S ", " --tos " \fIn\fR"
|
||||
set the IP 'type of service'
|
||||
.\" .TP
|
||||
.\" .BR -L ", " --flowlabel " \fIn\fR"
|
||||
.\" set the IPv6 'flow label'
|
||||
.TP
|
||||
.BR -L ", " --flowlabel " \fIn\fR"
|
||||
set the IPv6 flow label (currently only supported on Linux)
|
||||
.TP
|
||||
.BR -Z ", " --zerocopy " "
|
||||
Use a "zero copy" method of sending data, such as sendfile(2),
|
||||
|
@ -655,17 +655,17 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
|
||||
client_flag = 1;
|
||||
break;
|
||||
case 'L':
|
||||
#ifdef notdef
|
||||
#if defined(linux)
|
||||
test->settings->flowlabel = strtol(optarg, NULL, 0);
|
||||
if (test->settings->flowlabel < 1 || test->settings->flowlabel > 0xfffff) {
|
||||
i_errno = IESETFLOW;
|
||||
return -1;
|
||||
}
|
||||
client_flag = 1;
|
||||
#else /* notdef */
|
||||
i_errno = IEUNIMP;
|
||||
return -1;
|
||||
#endif /* notdef */
|
||||
#else /* linux */
|
||||
i_errno = IEUNIMP;
|
||||
return -1;
|
||||
#endif /* linux */
|
||||
break;
|
||||
case 'Z':
|
||||
if (!has_sendfile()) {
|
||||
|
@ -25,6 +25,9 @@
|
||||
#include "iperf_tcp.h"
|
||||
#include "net.h"
|
||||
|
||||
#if defined(linux)
|
||||
#include "flowlabel.h"
|
||||
#endif
|
||||
|
||||
/* iperf_tcp_recv
|
||||
*
|
||||
@ -291,6 +294,7 @@ iperf_tcp_connect(struct iperf_test *test)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#if defined(linux)
|
||||
if (test->settings->flowlabel) {
|
||||
if (server_res->ai_addr->sa_family != AF_INET6) {
|
||||
close(s);
|
||||
@ -299,9 +303,35 @@ iperf_tcp_connect(struct iperf_test *test)
|
||||
return -1;
|
||||
} else {
|
||||
struct sockaddr_in6* sa6P = (struct sockaddr_in6*) server_res->ai_addr;
|
||||
sa6P->sin6_flowinfo = htonl(test->settings->flowlabel);
|
||||
char freq_buf[sizeof(struct in6_flowlabel_req)];
|
||||
struct in6_flowlabel_req *freq = (struct in6_flowlabel_req *)freq_buf;
|
||||
int freq_len = sizeof(*freq);
|
||||
|
||||
memset(freq, 0, sizeof(*freq));
|
||||
freq->flr_label = htonl(test->settings->flowlabel & IPV6_FLOWINFO_FLOWLABEL);
|
||||
freq->flr_action = IPV6_FL_A_GET;
|
||||
freq->flr_flags = IPV6_FL_F_CREATE;
|
||||
freq->flr_share = IPV6_FL_F_CREATE | IPV6_FL_S_EXCL;
|
||||
memcpy(&freq->flr_dst, &sa6P->sin6_addr, 16);
|
||||
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_FLOWLABEL_MGR, freq, freq_len) < 0) {
|
||||
close(s);
|
||||
freeaddrinfo(server_res);
|
||||
i_errno = IESETFLOW;
|
||||
return -1;
|
||||
}
|
||||
sa6P->sin6_flowinfo = freq->flr_label;
|
||||
|
||||
opt = 1;
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_FLOWINFO_SEND, &opt, sizeof(opt)) < 0) {
|
||||
close(s);
|
||||
freeaddrinfo(server_res);
|
||||
i_errno = IESETFLOW;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (connect(s, (struct sockaddr *) server_res->ai_addr, server_res->ai_addrlen) < 0 && errno != EINPROGRESS) {
|
||||
close(s);
|
||||
|
@ -99,7 +99,9 @@ const char usage_longstr[] = "Usage: iperf [-s|-c host] [options]\n"
|
||||
" -4, --version4 only use IPv4\n"
|
||||
" -6, --version6 only use IPv6\n"
|
||||
" -S, --tos N set the IP 'type of service'\n"
|
||||
/* " -L, --flowlabel N set the IPv6 'flow label'\n" */
|
||||
#if defined(linux)
|
||||
" -L, --flowlabel N set the IPv6 flow label (only supported on Linux)\n"
|
||||
#endif
|
||||
" -Z, --zerocopy use a 'zero copy' method of sending data\n"
|
||||
" -O, --omit N omit the first n seconds\n"
|
||||
" -T, --title str prefix every output line with this string\n"
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user