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)
This commit is contained in:
Bruce A. Mah 2013-12-12 09:21:36 -08:00
parent c8a0a2229d
commit d04c7bd0a4
4 changed files with 42 additions and 10 deletions

View File

@ -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),

View File

@ -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()) {

View File

@ -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);

View File

@ -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"