traffic_start_iperf: Add support for additional CAPI parameters
Add support for the following parameters:
- clientport: Specify the client-side port
- reverse: Run in reverse mode (server sends, client receives)
- DSCP: The type-of-service for outgoing packets
- iptype=version6: Alias for IPv6
Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
diff --git a/traffic.c b/traffic.c
index 87972dc..a037a0d 100644
--- a/traffic.c
+++ b/traffic.c
@@ -13,6 +13,7 @@
#include <fcntl.h>
#include <signal.h>
#include <ctype.h>
+#include <ifaddrs.h>
#include "wpa_helpers.h"
@@ -244,6 +245,41 @@
}
+static int get_ip_addr(const char *ifname, int ipv6, char *buf, size_t len)
+{
+ struct ifaddrs *ifa, *ifa_tmp;
+
+ if (getifaddrs(&ifa) == -1)
+ return -1;
+
+ for (ifa_tmp = ifa; ifa_tmp; ifa_tmp = ifa_tmp->ifa_next) {
+ if (!ifa_tmp->ifa_addr ||
+ strcasecmp(ifname, ifa_tmp->ifa_name) != 0)
+ continue;
+
+ if (!ipv6 && ifa_tmp->ifa_addr->sa_family == AF_INET) {
+ struct sockaddr_in *in;
+
+ in = (struct sockaddr_in *) ifa_tmp->ifa_addr;
+ if (!inet_ntop(AF_INET, &in->sin_addr, buf, len))
+ return -1;
+ return 0;
+ }
+
+ if (ipv6 && ifa_tmp->ifa_addr->sa_family == AF_INET6) {
+ struct sockaddr_in6 *in6;
+
+ in6 = (struct sockaddr_in6 *) ifa_tmp->ifa_addr;
+ if (!inet_ntop(AF_INET6, &in6->sin6_addr, buf, len))
+ return -1;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+
static enum sigma_cmd_result cmd_traffic_start_iperf(struct sigma_dut *dut,
struct sigma_conn *conn,
struct sigma_cmd *cmd)
@@ -257,6 +293,9 @@
char port_str[20], iperf[100];
FILE *f;
int server, ipv6 = 0;
+ char *pos;
+ int dscp, reverse = 0;
+ char tos[20], client_port_str[100];
val = get_param(cmd, "mode");
if (!val) {
@@ -269,7 +308,8 @@
iptype = "";
val = get_param(cmd, "iptype");
if (val) {
- if (strcasecmp(val, "ipv6") == 0) {
+ if (strcasecmp(val, "ipv6") == 0 ||
+ strcasecmp(val, "version6") == 0) {
iptype = "-6";
ipv6 = 1;
} else {
@@ -291,23 +331,68 @@
proto = "-u";
dst = get_param(cmd, "destination");
+ pos = dst ? strchr(dst, '%') : NULL;
+ if (pos) {
+ *pos++ = '\0';
+ ifname = pos;
+ } else if (dut->ndpe) {
+ ifname = "nan0";
+ } else {
+ ifname = get_station_ifname(dut);
+ }
+
if (!server && (!dst || (!is_ip_addr(dst) && !is_ipv6_addr(dst)))) {
send_resp(dut, conn, SIGMA_ERROR,
"errorCode,Invalid destination address");
return STATUS_SENT;
}
- if (dut->ndpe)
- ifname = "nan0";
- else
- ifname = get_station_ifname(dut);
-
val = get_param(cmd, "duration");
if (val)
duration = atoi(val);
else
duration = 0;
+ client_port_str[0] = '\0';
+ val = get_param(cmd, "clientport");
+ if (val) {
+ char ipaddr[100];
+ int res;
+
+ port = atoi(val);
+ if (get_ip_addr(ifname, ipv6, ipaddr, sizeof(ipaddr))) {
+ send_resp(dut, conn, SIGMA_ERROR,
+ "errorCode,Cannot get own IP address");
+ return STATUS_SENT;
+ }
+
+ if (ipv6)
+ snprintf(buf, sizeof(buf), "%s%%%s", ipaddr, ifname);
+ else
+ snprintf(buf, sizeof(buf), "%s", ipaddr);
+
+ res = snprintf(client_port_str, sizeof(client_port_str),
+ " -B %s --cport %d", buf, port);
+ if (res < 0 || res >= sizeof(client_port_str))
+ return ERROR_SEND_STATUS;
+ }
+
+ val = get_param(cmd, "reverse");
+ if (val)
+ reverse = atoi(val);
+
+ tos[0] = '\0';
+ val = get_param(cmd, "DSCP");
+ if (val) {
+ dscp = atoi(val);
+ if (dscp < 0 || dscp > 63) {
+ send_resp(dut, conn, SIGMA_ERROR,
+ "ErrorCode,Invalid DSCP value");
+ return STATUS_SENT_ERROR;
+ }
+ snprintf(tos, sizeof(tos), " -S 0x%02x", dscp << 2);
+ }
+
unlink(concat_sigma_tmpdir(dut, "/sigma_dut-iperf", iperf,
sizeof(iperf)));
unlink(concat_sigma_tmpdir(dut, "/sigma_dut-iperf-pid", iperf,
@@ -337,10 +422,11 @@
else
snprintf(buf, sizeof(buf), "%s", dst);
fprintf(f, "#!" SHELL "\n"
- "iperf3 -c %s -t %d %s %s %s > %s"
+ "iperf3 -c %s -t %d %s %s %s%s%s%s > %s"
"/sigma_dut-iperf &\n"
"echo $! > %s/sigma_dut-iperf-pid\n",
buf, duration, iptype, proto, port_str,
+ client_port_str, tos, reverse ? " -R" : "",
dut->sigma_tmpdir, dut->sigma_tmpdir);
}