Skip to content

Commit

Permalink
enh: Add support for SO_PRIORITY socket option.
Browse files Browse the repository at this point in the history
This functionality is needed to test multi queue support of Ethernet
drivers.

Co-developed-by: Oleksij Rempel <o.rempel@pengutronix.de>
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Co-developed-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
  • Loading branch information
olerem committed Oct 18, 2023
1 parent 7e05ef2 commit 5bb90e8
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 1 deletion.
12 changes: 12 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,18 @@ if test "x$iperf3_cv_header_so_bindtodevice" = "xyes"; then
AC_DEFINE([HAVE_SO_BINDTODEVICE], [1], [Have SO_BINDTODEVICE sockopt.])
fi

# Check for SO_PRIORITY sockopt (believed to be Linux only)
AC_CACHE_CHECK([SO_PRIORITY socket option],
[iperf3_cv_header_so_priority],
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[#include <sys/socket.h>]],
[[int foo = SO_PRIORITY;]])],
iperf3_cv_header_so_priority=yes,
iperf3_cv_header_so_priority=no))
if test "x$iperf3_cv_header_so_priority" = "xyes"; then
AC_DEFINE([HAVE_SO_PRIORITY], [1], [Have SO_PRIORITY sockopt.])
fi

# Check for IP_MTU_DISCOVER (mostly on Linux)
AC_CACHE_CHECK([IP_MTU_DISCOVER socket option],
[iperf3_cv_header_ip_mtu_discover],
Expand Down
8 changes: 8 additions & 0 deletions docs/invoking.rst
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,14 @@ the executable.
set the IP type of service. The usual prefixes for octal and hex
can be used, i.e. 52, 064 and 0x34 all specify the same value.
--sock-prio n
Set the protocol-defined priority for all packets to be sent
on this socket. Linux uses this value to order the networking
queues: packets with a higher priority may be processed first
depending on the selected device queueing discipline. Setting
a priority outside the range 0 to 6 requires the CAP_NET_ADMIN
capability
--dscp dscp
set the IP DSCP bits. Both numeric and symbolic values are
accepted. Numeric values can be specified in decimal, octal and
Expand Down
3 changes: 3 additions & 0 deletions src/iperf.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ struct iperf_settings
int mss; /* for TCP MSS */
int ttl; /* IP TTL option */
int tos; /* type of service bit */
#if defined(HAVE_SO_PRIORITY)
int sock_prio; /* protocol-defined priority */
#endif // HAVE_SO_PRIORITY
int flowlabel; /* IPv6 flow label */
iperf_size_t bytes; /* number of bytes to send */
iperf_size_t blocks; /* number of blocks (packets) to send */
Expand Down
47 changes: 46 additions & 1 deletion src/iperf_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -881,7 +881,13 @@ void
iperf_on_test_start(struct iperf_test *test)
{
if (test->json_output) {
cJSON_AddItemToObject(test->json_start, "test_start", iperf_json_printf("protocol: %s num_streams: %d blksize: %d omit: %d duration: %d bytes: %d blocks: %d reverse: %d tos: %d target_bitrate: %d bidir: %d fqrate: %d", test->protocol->name, (int64_t) test->num_streams, (int64_t) test->settings->blksize, (int64_t) test->omit, (int64_t) test->duration, (int64_t) test->settings->bytes, (int64_t) test->settings->blocks, test->reverse?(int64_t)1:(int64_t)0, (int64_t) test->settings->tos, (int64_t) test->settings->rate, (int64_t) test->bidirectional, (uint64_t) test->settings->fqrate));
cJSON_AddItemToObject(test->json_start, "test_start", iperf_json_printf("protocol: %s num_streams: %d blksize: %d omit: %d duration: %d bytes: %d blocks: %d reverse: %d tos: %d target_bitrate: %d bidir: %d fqrate: %d sock_prio: %d", test->protocol->name, (int64_t) test->num_streams, (int64_t) test->settings->blksize, (int64_t) test->omit, (int64_t) test->duration, (int64_t) test->settings->bytes, (int64_t) test->settings->blocks, test->reverse?(int64_t)1:(int64_t)0, (int64_t) test->settings->tos, (int64_t) test->settings->rate, (int64_t) test->bidirectional, (uint64_t) test->settings->fqrate,
#if defined(HAVE_SO_PRIORITY)
(int64_t) test->settings->sock_prio
#else /* HAVE_SO_PRIORITY */
0
#endif
));
} else {
if (test->verbose) {
if (test->settings->bytes)
Expand Down Expand Up @@ -1083,6 +1089,9 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
{"version4", no_argument, NULL, '4'},
{"version6", no_argument, NULL, '6'},
{"tos", required_argument, NULL, 'S'},
#if defined(HAVE_SO_PRIORITY)
{"sock-prio", required_argument, NULL, OPT_SOCK_PRIO},
#endif /* HAVE_SO_PRIORITY */
{"dscp", required_argument, NULL, OPT_DSCP},
{"extra-data", required_argument, NULL, OPT_EXTRA_DATA},
#if defined(HAVE_FLOWLABEL)
Expand Down Expand Up @@ -1404,6 +1413,21 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
}
client_flag = 1;
break;
case OPT_SOCK_PRIO:
#if defined(HAVE_SO_PRIORITY)
test->settings->sock_prio = strtol(optarg, &endptr, 0);
if (endptr == optarg ||
test->settings->sock_prio < 0 ||
test->settings->sock_prio > 15) {
i_errno = IEBADSOPRIO;
return -1;
}
client_flag = 1;
#else /* HAVE_SO_PRIORITY */
i_errno = IEUNIMP;
return -1;
#endif /* HAVE_SO_PRIORITY */
break;
case OPT_DSCP:
test->settings->tos = parse_qos(optarg);
if(test->settings->tos < 0) {
Expand Down Expand Up @@ -2210,6 +2234,10 @@ send_parameters(struct iperf_test *test)
cJSON_AddNumberToObject(j, "burst", test->settings->burst);
if (test->settings->tos)
cJSON_AddNumberToObject(j, "TOS", test->settings->tos);
#if defined(HAVE_SO_PRIORITY)
if (test->settings->sock_prio)
cJSON_AddNumberToObject(j, "SOCK_PRIO", test->settings->sock_prio);
#endif /* HAVE_SO_PRIORITY */
if (test->settings->flowlabel)
cJSON_AddNumberToObject(j, "flowlabel", test->settings->flowlabel);
if (test->title)
Expand Down Expand Up @@ -2326,6 +2354,10 @@ get_parameters(struct iperf_test *test)
test->settings->burst = j_p->valueint;
if ((j_p = cJSON_GetObjectItem(j, "TOS")) != NULL)
test->settings->tos = j_p->valueint;
#if defined(HAVE_SO_PRIORITY)
if ((j_p = cJSON_GetObjectItem(j, "SOCK_PRIO")) != NULL)
test->settings->sock_prio = j_p->valueint;
#endif /* HAVE_SO_PRIORITY */
if ((j_p = cJSON_GetObjectItem(j, "flowlabel")) != NULL)
test->settings->flowlabel = j_p->valueint;
if ((j_p = cJSON_GetObjectItem(j, "title")) != NULL)
Expand Down Expand Up @@ -3188,6 +3220,9 @@ iperf_reset_test(struct iperf_test *test)
test->settings->burst = 0;
test->settings->mss = 0;
test->settings->tos = 0;
#if defined(HAVE_SO_PRIORITY)
test->settings->sock_prio = 0;
#endif /* HAVE_SO_PRIORITY */
test->settings->dont_fragment = 0;
test->zerocopy = 0;

Expand Down Expand Up @@ -4438,6 +4473,16 @@ iperf_common_sockopts(struct iperf_test *test, int s)
}
}
}

#if defined(HAVE_SO_PRIORITY)
if ((opt = test->settings->sock_prio)) {
if (setsockopt(s, SOL_SOCKET, SO_PRIORITY, &opt, sizeof(opt)) < 0) {
i_errno = IESETSOPRIO;
return -1;
}
}
#endif /* HAVE_SO_PRIORITY */

return 0;
}

Expand Down
3 changes: 3 additions & 0 deletions src/iperf_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ typedef uint64_t iperf_size_t;
#define OPT_DONT_FRAGMENT 26
#define OPT_RCV_TIMEOUT 27
#define OPT_SND_TIMEOUT 28
#define OPT_SOCK_PRIO 29

/* states */
#define TEST_START 1
Expand Down Expand Up @@ -406,6 +407,7 @@ enum {
IERVRSONLYRCVTIMEOUT = 32, // Client receive timeout is valid only in reverse mode
IESNDTIMEOUT = 33, // Illegal message send timeout
IEUDPFILETRANSFER = 34, // Cannot transfer file using UDP
IEBADSOPRIO = 35, // Bad socket priority value
/* Test errors */
IENEWTEST = 100, // Unable to create a new test (check perror)
IEINITTEST = 101, // Test initialization failed (check perror)
Expand Down Expand Up @@ -456,6 +458,7 @@ enum {
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
IESETUSERTIMEOUT = 148, // Unable to set TCP USER_TIMEOUT (check perror)
IESETSOPRIO = 149, // Unable to set socket priority (check perror)
/* Stream errors */
IECREATESTREAM = 200, // Unable to create a new stream (check herror/perror)
IEINITSTREAM = 201, // Unable to initialize stream (check herror/perror)
Expand Down
3 changes: 3 additions & 0 deletions src/iperf_locale.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,9 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n"
" --dscp N or --dscp val set the IP dscp value, either 0-63 or symbolic.\n"
" Numeric values can be specified in decimal,\n"
" octal and hex (see --tos above).\n"
#if defined(HAVE_SO_PRIORITY)
" --sock-prio N set the socket priority (only supported on Linux)\n"
#endif /* HAVE_SO_PRIORITY */
#if defined(HAVE_FLOWLABEL)
" -L, --flowlabel N set the IPv6 flow label (only supported on Linux)\n"
#endif /* HAVE_FLOWLABEL */
Expand Down

0 comments on commit 5bb90e8

Please sign in to comment.