Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/iperf.h
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,8 @@ struct iperf_test
void (*json_callback) (struct iperf_test *, char *); /* allow user apps to receive the
JSON strings,instead of writing them to the output file */
int zerocopy; /* -Z option - use sendfile */
int udp_gso; /* -G option - use UDP_GSO feature */
uint16_t udp_gso_size;
int debug; /* -d option - enable debug */
enum debug_level debug_level; /* -d option option - level of debug messages to show */
int get_server_output; /* --get-server-output */
Expand Down
15 changes: 12 additions & 3 deletions src/iperf_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -1115,6 +1115,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
{"flowlabel", required_argument, NULL, 'L'},
#endif /* HAVE_FLOWLABEL */
{"zerocopy", no_argument, NULL, 'Z'},
{"udp_gso", no_argument, NULL, 'G'},
{"omit", required_argument, NULL, 'O'},
{"file", required_argument, NULL, 'F'},
{"repeating-payload", no_argument, NULL, OPT_REPEATING_PAYLOAD},
Expand Down Expand Up @@ -1189,7 +1190,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
FILE *ptr_file;
#endif /* HAVE_SSL */

while ((flag = getopt_long(argc, argv, "p:f:i:D1VJvsc:ub:t:n:k:l:P:Rw:B:M:N46S:L:ZO:F:A:T:C:dI:mhX:", longopts, NULL)) != -1) {
while ((flag = getopt_long(argc, argv, "p:f:i:D1VJvsc:ub:t:n:k:l:P:Rw:B:M:N46S:L:ZG:O:F:A:T:C:dI:hX:", longopts, NULL)) != -1) {
switch (flag) {
case 'p':
portno = atoi(optarg);
Expand Down Expand Up @@ -1493,6 +1494,12 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
test->zerocopy = 1;
client_flag = 1;
break;
case 'G':
test->udp_gso = 1;
test->udp_gso_size = strtoul(optarg, NULL, 0);
printf("UDP_GSO enabled for this run\n");
client_flag = 1;
break;
case OPT_REPEATING_PAYLOAD:
test->repeating_payload = 1;
client_flag = 1;
Expand Down Expand Up @@ -4184,9 +4191,11 @@ iperf_print_results(struct iperf_test *test)
iperf_printf(test, report_receiver_not_available_format, sp->socket);
}
else {
if (sp->omitted_cnt_error > -1) {
if (test->udp_gso)
iperf_printf(test, report_bw_udp_hw_gso_format, sp->socket, mbuf, start_time, receiver_time, ubuf, nbuf, "--NA--", " --NA-- ", report_receiver);
else if (sp->omitted_cnt_error > -1) {
iperf_printf(test, report_bw_udp_format, sp->socket, mbuf, start_time, receiver_time, ubuf, nbuf, sp->jitter * 1000.0, (sp->cnt_error - sp->omitted_cnt_error), (receiver_packet_count - receiver_omitted_packet_count), lost_percent, report_receiver);
} else {
} else {
iperf_printf(test, report_bw_udp_format_no_omitted_error, sp->socket, mbuf, start_time, receiver_time, ubuf, nbuf, sp->jitter * 1000.0, (receiver_packet_count - receiver_omitted_packet_count), report_receiver);
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/iperf_locale.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n"
" -L, --flowlabel N set the IPv6 flow label (only supported on Linux)\n"
#endif /* HAVE_FLOWLABEL */
" -Z, --zerocopy use a 'zero copy' method of sending data\n"
" -G, --use udp_gso use 'udp_gso' feature for sending data\n"
" -O, --omit N perform pre-test for N seconds and omit the pre-test statistics\n"
" -T, --title str prefix every output line with this string\n"
" --extra-data str data string to include in client and server JSON\n"
Expand Down Expand Up @@ -399,6 +400,9 @@ const char report_bw_retrans_cwnd_format[] =
const char report_bw_udp_format[] =
"[%3d]%s %6.2f-%-6.2f sec %ss %ss/sec %5.3f ms %" PRId64 "/%" PRId64 " (%.2g%%) %s\n";

const char report_bw_udp_hw_gso_format[] =
"[%3d]%s %6.2f-%-6.2f sec %ss %ss/sec %s %s %s\n";

const char report_bw_udp_format_no_omitted_error[] =
"[%3d]%s %6.2f-%-6.2f sec %ss %ss/sec %5.3f ms Unknown/%" PRId64 " %s\n";

Expand Down
1 change: 1 addition & 0 deletions src/iperf_locale.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ extern const char report_bw_format[] ;
extern const char report_bw_retrans_format[] ;
extern const char report_bw_retrans_cwnd_format[] ;
extern const char report_bw_udp_format[] ;
extern const char report_bw_udp_hw_gso_format[] ;
extern const char report_bw_udp_format_no_omitted_error[] ;
extern const char report_bw_udp_sender_format[] ;
extern const char report_summary[] ;
Expand Down
56 changes: 55 additions & 1 deletion src/iperf_udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,57 @@
#include "net.h"
#include "cjson.h"

#ifndef UDP_SEGMENT
#define UDP_SEGMENT 103
#endif

#ifndef SOL_UDP
#define SOL_UDP 17
#endif

/* iperf_udp_send_segment
*
* sends the UDP data segment
*/
static int iperf_udp_send_segment(struct iperf_stream *sp, char *buf)
{
int ret = 0;
uint16_t *valp;
struct msghdr msg = {0};
struct iovec iov = {0};
struct cmsghdr *cmsg;
struct sockaddr_in addr4;
char control[CMSG_SPACE(sizeof(sp->test->udp_gso_size))] = {0};

iov.iov_base = buf;
iov.iov_len = sp->settings->blksize;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = control;
msg.msg_controllen = sizeof(control);

/* Construct CMSG for UDP_GSO */
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_UDP;
cmsg->cmsg_type = UDP_SEGMENT;
cmsg->cmsg_len = CMSG_LEN(sizeof(sp->test->udp_gso_size));
valp = (void *)CMSG_DATA(cmsg);
*valp = sp->test->udp_gso_size;
msg.msg_controllen = CMSG_SPACE(sizeof(sp->test->udp_gso_size));

/*set up sock address */
addr4.sin_family = AF_INET;
addr4.sin_port = htons(sp->test->server_port);
if (inet_pton(AF_INET, sp->test->server_hostname, &(addr4.sin_addr)) != 1)
printf("ipv4 parse error: %s", sp->test->server_hostname);
msg.msg_name = (void *)&addr4;
msg.msg_namelen = sizeof(struct sockaddr_in);

ret = sendmsg(sp->socket, &msg, 0);

return ret;
}

/* iperf_udp_recv
*
* receives the data for UDP
Expand Down Expand Up @@ -237,7 +288,10 @@ iperf_udp_send(struct iperf_stream *sp)

}

r = Nwrite(sp->socket, sp->buffer, size, Pudp);
if (!sp->test->udp_gso)
r = Nwrite(sp->socket, sp->buffer, size, Pudp);
else
r = iperf_udp_send_segment(sp, sp->buffer);

if (r <= 0) {
--sp->packet_count; /* Don't count messages that no data was sent from them.
Expand Down