Skip to content

Commit 5f0e4e8

Browse files
Liam McBirnieLiam McBirnie
authored andcommitted
Add option to set the ToS of the control connection.
1 parent d348cd7 commit 5f0e4e8

7 files changed

Lines changed: 118 additions & 2 deletions

File tree

docs/invoking.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,16 @@ the executable.
226226
iperf3 versions. Use this option to preserve the less secure,
227227
but more compatible, behavior.
228228
229+
--control-tos n
230+
Set the IP type of service bits of the control connection. The
231+
usual prefixes for octal and hex can be used, i.e. 52, 064 and
232+
0x34 all specify the same value.
233+
234+
--control-dscp dscp
235+
Set the IP DSCP bits of the control connection. Both numeric and
236+
symbolic values are accepted. Numeric values can be specified in
237+
decimal, octal and hex (see --control-tos above).
238+
229239
-m, --mptcp
230240
Use the MPTCP variant for the current protocol. This only ap-
231241
plies to TCP and enables MPTCP usage.

src/iperf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ struct iperf_settings
170170
int mss; /* for TCP MSS */
171171
int ttl; /* IP TTL option */
172172
int tos; /* type of service bit */
173+
int ctrl_tos; /* type of service for control socket */
173174
int flowlabel; /* IPv6 flow label */
174175
iperf_size_t bytes; /* number of bytes to send */
175176
iperf_size_t blocks; /* number of blocks (packets) to send */

src/iperf_api.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,6 +1135,8 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
11351135
{"version6", no_argument, NULL, '6'},
11361136
{"tos", required_argument, NULL, 'S'},
11371137
{"dscp", required_argument, NULL, OPT_DSCP},
1138+
{"control-tos", required_argument, NULL, OPT_CONTROL_TOS},
1139+
{"control-dscp", required_argument, NULL, OPT_CONTROL_DSCP},
11381140
{"extra-data", required_argument, NULL, OPT_EXTRA_DATA},
11391141
#if defined(HAVE_FLOWLABEL)
11401142
{"flowlabel", required_argument, NULL, 'L'},
@@ -1505,6 +1507,22 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
15051507
}
15061508
client_flag = 1;
15071509
break;
1510+
case OPT_CONTROL_TOS:
1511+
test->settings->ctrl_tos = strtol(optarg, &endptr, 0);
1512+
if (endptr == optarg ||
1513+
test->settings->ctrl_tos < 0 ||
1514+
test->settings->ctrl_tos > 255) {
1515+
i_errno = IEBADTOS;
1516+
return -1;
1517+
}
1518+
break;
1519+
case OPT_CONTROL_DSCP:
1520+
test->settings->ctrl_tos = parse_qos(optarg);
1521+
if(test->settings->ctrl_tos < 0) {
1522+
i_errno = IEBADTOS;
1523+
return -1;
1524+
}
1525+
break;
15081526
case OPT_EXTRA_DATA:
15091527
test->extra_data = strdup(optarg);
15101528
client_flag = 1;
@@ -5487,6 +5505,34 @@ iflush(struct iperf_test *test)
54875505
return rc2;
54885506
}
54895507

5508+
int
5509+
iperf_set_tos(int s, int tos)
5510+
{
5511+
if (tos) {
5512+
if (getsockdomain(s) == AF_INET6) {
5513+
#ifdef IPV6_TCLASS
5514+
if (setsockopt(s, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos)) < 0) {
5515+
i_errno = IESETCOS;
5516+
return -1;
5517+
}
5518+
if (setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) {
5519+
/* ignore any failure of v4 TOS in IPv6 case */
5520+
}
5521+
#else
5522+
i_errno = IESETCOS;
5523+
return -1;
5524+
#endif
5525+
} else {
5526+
if (setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) {
5527+
i_errno = IESETTOS;
5528+
return -1;
5529+
}
5530+
}
5531+
}
5532+
5533+
return 0;
5534+
}
5535+
54905536
#if defined (HAVE_TCP_KEEPALIVE)
54915537
// Set Control Connection TCP Keepalive (especially useful for long UDP test sessions)
54925538
int

src/iperf_api.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ typedef atomic_uint_fast64_t atomic_iperf_size_t;
106106
#define OPT_SKIP_RX_COPY 32
107107
#define OPT_JSON_STREAM_FULL_OUTPUT 33
108108
#define OPT_SERVER_MAX_DURATION 34
109+
#define OPT_CONTROL_TOS 35
110+
#define OPT_CONTROL_DSCP 36
109111

110112
/* states */
111113
#define TEST_START 1
@@ -319,6 +321,12 @@ void iperf_free_stream(struct iperf_stream * sp);
319321
*/
320322
int iperf_common_sockopts(struct iperf_test *, int s);
321323

324+
/**
325+
* iperf_set_tos -- set socket TOS
326+
*
327+
*/
328+
int iperf_set_tos(int s, int tos);
329+
322330
#if defined (HAVE_TCP_KEEPALIVE)
323331
/**
324332
* iperf_set_control_keepalive -- set control connection TCP keepalive

src/iperf_client_api.c

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <signal.h>
3434
#include <sys/types.h>
3535
#include <netinet/in.h>
36+
#include <netdb.h>
3637
#include <sys/select.h>
3738
#include <sys/uio.h>
3839
#include <arpa/inet.h>
@@ -409,6 +410,37 @@ iperf_handle_message_client(struct iperf_test *test)
409410
return 0;
410411
}
411412

413+
/*
414+
* Make connection to server
415+
* This is derived from netdial() but also sets the tos before connection.
416+
*/
417+
static int
418+
netdial_with_tos(int domain, int proto, const char *local, const char *bind_dev, int local_port, const char *server, int port, int timeout, int tos)
419+
{
420+
struct addrinfo *server_res = NULL;
421+
int s, saved_errno;
422+
423+
s = create_socket(domain, proto, 0, local, bind_dev, local_port, server, port, &server_res);
424+
if (s < 0) {
425+
return -1;
426+
}
427+
428+
// Set IP TOS
429+
if (iperf_set_tos(s, tos) < 0) {
430+
return -1;
431+
}
432+
433+
if (timeout_connect(s, (struct sockaddr *) server_res->ai_addr, server_res->ai_addrlen, timeout) < 0 && errno != EINPROGRESS) {
434+
saved_errno = errno;
435+
close(s);
436+
freeaddrinfo(server_res);
437+
errno = saved_errno;
438+
return -1;
439+
}
440+
441+
freeaddrinfo(server_res);
442+
return s;
443+
}
412444

413445

414446
/* iperf_connect -- client to server connection function */
@@ -430,8 +462,9 @@ iperf_connect(struct iperf_test *test)
430462

431463
/* Create and connect the control channel */
432464
if (test->ctrl_sck < 0)
433-
// Create the control channel using an ephemeral port
434-
test->ctrl_sck = netdial(test->settings->domain, Ptcp, test->bind_address, test->bind_dev, 0, test->server_hostname, test->server_port, test->settings->connect_timeout);
465+
// Create the control channel using an ephemeral port
466+
test->ctrl_sck = netdial_with_tos(test->settings->domain, Ptcp, test->bind_address, test->bind_dev, 0, test->server_hostname,
467+
test->server_port, test->settings->connect_timeout, test->settings->ctrl_tos);
435468
if (test->ctrl_sck < 0) {
436469
i_errno = IECONNECT;
437470
return -1;

src/iperf_locale.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,13 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n"
159159
" and client during the authentication process\n"
160160
" --use-pkcs1-padding use pkcs1 padding at your own risk\n"
161161
#endif //HAVE_SSL
162+
" --control-tos N set the IP type of service of the control connection, 0-255.\n"
163+
" The usual prefixes for octal and hex can be used,\n"
164+
" i.e. 52, 064 and 0x34 all specify the same value.\n"
165+
166+
" --control-dscp val set the IP dscp value of the control connection, either 0-63 or symbolic.\n"
167+
" Numeric values can be specified in decimal,\n"
168+
" octal and hex (see --control-tos above).\n"
162169
"Client specific:\n"
163170
" -c, --client <host>[%%<dev>] run in client mode, connecting to <host>\n"
164171
" (option <dev> equivalent to `--bind-dev <dev>`)\n"

src/iperf_server_api.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,12 @@ iperf_server_listen(struct iperf_test *test)
129129
}
130130
}
131131

132+
// Set IP TOS
133+
if (iperf_set_tos(test->listener, test->settings->ctrl_tos) < 0) {
134+
close(test->listener);
135+
return -1;
136+
}
137+
132138
if (!test->json_output) {
133139
if (test->server_last_run_rc != 2)
134140
test->server_test_number +=1;
@@ -174,6 +180,11 @@ iperf_accept(struct iperf_test *test)
174180
goto error_handling;
175181
}
176182

183+
// Set IP TOS
184+
if (iperf_set_tos(test->ctrl_sck, test->settings->ctrl_tos) < 0) {
185+
goto error_handling;
186+
}
187+
177188
#if defined(HAVE_TCP_USER_TIMEOUT)
178189
int opt;
179190
if ((opt = test->settings->snd_timeout)) {

0 commit comments

Comments
 (0)