diff --git a/src/iperf.h b/src/iperf.h index 55ad513..ffbd6d3 100644 --- a/src/iperf.h +++ b/src/iperf.h @@ -62,6 +62,7 @@ struct iperf_settings int mss; /* for TCP MSS */ int ttl; /* IP TTL option */ int tos; /* type of service bit */ + int flowlabel; /* IPv6 flow label */ iperf_size_t bytes; /* number of bytes to send */ char unit_format; /* -f */ }; diff --git a/src/iperf3.1 b/src/iperf3.1 index ab20419..d32874b 100644 --- a/src/iperf3.1 +++ b/src/iperf3.1 @@ -94,6 +94,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 -Z ", " --zerocopy " " Use a "zero copy" method of sending data, such as sendfile(2), diff --git a/src/iperf_api.c b/src/iperf_api.c index 7615c2d..e37fb85 100644 --- a/src/iperf_api.c +++ b/src/iperf_api.c @@ -430,14 +430,14 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) {"no-delay", no_argument, NULL, 'N'}, {"version6", no_argument, NULL, '6'}, {"tos", required_argument, NULL, 'S'}, + {"flowlabel", required_argument, NULL, 'L'}, {"zerocopy", no_argument, NULL, 'Z'}, {"help", no_argument, NULL, 'h'}, - /* XXX: The following ifdef needs to be split up. linux-congestion is not necessarily supported - * by systems that support tos. + /* XXX: The following ifdef needs to be split up. linux-congestion is not + * necessarily supported by systems that support tos. */ #ifdef ADD_WHEN_SUPPORTED - {"tos", required_argument, NULL, 'S'}, {"linux-congestion", required_argument, NULL, 'L'}, #endif {NULL, 0, NULL, 0} @@ -448,7 +448,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) blksize = 0; server_flag = client_flag = 0; - while ((flag = getopt_long(argc, argv, "p:f:i:DVJdvsc:ub:t:n:l:P:Rw:B:M:N46S:Zh", longopts, NULL)) != -1) { + while ((flag = getopt_long(argc, argv, "p:f:i:DVJdvsc:ub:t:n:l:P:Rw:B:M:N46S:L:Zh", longopts, NULL)) != -1) { switch (flag) { case 'p': test->server_port = atoi(optarg); @@ -569,10 +569,22 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) test->settings->domain = AF_INET6; break; case 'S': - // XXX: Checking for errors in strtol is not portable. Leave as is? test->settings->tos = strtol(optarg, NULL, 0); client_flag = 1; break; + case 'L': +#ifdef notdef + 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 */ + break; case 'Z': if (!has_sendfile()) { i_errno = IENOSENDFILE; @@ -889,6 +901,8 @@ send_parameters(struct iperf_test *test) cJSON_AddIntToObject(j, "bandwidth", test->settings->rate); if (test->settings->tos) cJSON_AddIntToObject(j, "TOS", test->settings->tos); + if (test->settings->flowlabel) + cJSON_AddIntToObject(j, "flowlabel", test->settings->flowlabel); if (JSON_write(test->ctrl_sck, j) < 0) { i_errno = IESENDPARAMS; r = -1; @@ -938,6 +952,8 @@ get_parameters(struct iperf_test *test) test->settings->rate = j_p->valueint; if ((j_p = cJSON_GetObjectItem(j, "TOS")) != NULL) test->settings->tos = j_p->valueint; + if ((j_p = cJSON_GetObjectItem(j, "flowlabel")) != NULL) + test->settings->flowlabel = j_p->valueint; if (test->sender && test->protocol->id == Ptcp && has_tcpinfo_retransmits()) test->sender_has_retransmits = 1; cJSON_Delete(j); @@ -1832,6 +1848,7 @@ iperf_init_stream(struct iperf_stream *sp, struct iperf_test *test) i_errno = IEINITSTREAM; return -1; } + /* Set IP TOS */ if ((opt = test->settings->tos)) { if (getsockdomain(sp->socket) == AF_INET6) { diff --git a/src/iperf_api.h b/src/iperf_api.h index 8936d8c..418eebc 100644 --- a/src/iperf_api.h +++ b/src/iperf_api.h @@ -222,6 +222,7 @@ enum { IEINTERVAL = 9, // Report interval too large. Maxumum value = %dMAX_INTERVAL IEMSS = 10, // MSS too large. Maximum value = %dMAX_MSS IENOSENDFILE = 11, // This OS does not support sendfile + IEUNIMP = 12, // Not implemented yet /* Test errors */ IENEWTEST = 100, // Unable to create a new test (check perror) IEINITTEST = 101, // Test initialization failed (check perror) @@ -250,10 +251,11 @@ enum { IESETBUF = 124, // Unable to set socket buffer size (check perror) IESETTOS = 125, // Unable to set IP TOS (check perror) IESETCOS = 126, // Unable to set IPv6 traffic class (check perror) - IEREUSEADDR = 127, // Unable to set reuse address on socket (check perror) - IENONBLOCKING = 128, // Unable to set socket to non-blocking (check perror) - IESETWINDOWSIZE = 129, // Unable to set socket window size (check perror) - IEPROTOCOL = 130, // Protocol does not exist + IESETFLOW = 127, // Unable to set IPv6 flow label + IEREUSEADDR = 128, // Unable to set reuse address on socket (check perror) + IENONBLOCKING = 129, // Unable to set socket to non-blocking (check perror) + IESETWINDOWSIZE = 130, // Unable to set socket window size (check perror) + IEPROTOCOL = 131, // Protocol does not exist /* Stream errors */ IECREATESTREAM = 200, // Unable to create a new stream (check herror/perror) IEINITSTREAM = 201, // Unable to initialize stream (check herror/perror) diff --git a/src/iperf_error.c b/src/iperf_error.c index d8c8010..c5d9910 100644 --- a/src/iperf_error.c +++ b/src/iperf_error.c @@ -99,6 +99,9 @@ iperf_strerror(int i_errno) case IENOSENDFILE: snprintf(errstr, len, "this OS does not support sendfile"); break; + case IEUNIMP: + snprintf(errstr, len, "an option you are trying to set is not implemented yet"); + break; case IENEWTEST: snprintf(errstr, len, "unable to create a new test"); perr = 1; @@ -203,6 +206,9 @@ iperf_strerror(int i_errno) snprintf(errstr, len, "unable to set IPv6 traffic class"); perr = 1; break; + case IESETFLOW: + snprintf(errstr, len, "unable to set IPv6 flow label"); + break; case IEREUSEADDR: snprintf(errstr, len, "unable to reuse address on socket"); perr = 1; diff --git a/src/iperf_tcp.c b/src/iperf_tcp.c index 3165842..b47ebda 100644 --- a/src/iperf_tcp.c +++ b/src/iperf_tcp.c @@ -263,6 +263,15 @@ iperf_tcp_connect(struct iperf_test *test) return -1; } } + if (test->settings->flowlabel) { + if (server_res->ai_addr->sa_family != AF_INET6) { + i_errno = IESETFLOW; + return -1; + } else { + struct sockaddr_in6* sa6P = (struct sockaddr_in6*) server_res->ai_addr; + sa6P->sin6_flowinfo = htonl(test->settings->flowlabel); + } + } if (connect(s, (struct sockaddr *) server_res->ai_addr, server_res->ai_addrlen) < 0 && errno != EINPROGRESS) { i_errno = IESTREAMCONNECT; diff --git a/src/locale.c b/src/locale.c index 40e4fc0..a827625 100644 --- a/src/locale.c +++ b/src/locale.c @@ -97,6 +97,7 @@ 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" */ " -Z, --zerocopy use a 'zero copy' method of sending data\n" #ifdef NOT_YET_SUPPORTED /* still working on these */