blob: 0749f097dae18c877433a15980e05f150e3c8e7a [file] [log] [blame]
Jouni Malinencd4e3c32015-10-29 12:39:56 +02001/*
2 * Sigma Control API DUT (station/AP)
3 * Copyright (c) 2010, Atheros Communications, Inc.
Jouni Malinen9d7e31d2017-12-22 18:55:04 +02004 * Copyright (c) 2011-2013, 2016-2017 Qualcomm Atheros, Inc.
Peng Xu57784e02018-06-26 17:20:43 -07005 * Copyright (c) 2018, The Linux Foundation
Jouni Malinencd4e3c32015-10-29 12:39:56 +02006 * All Rights Reserved.
7 * Licensed under the Clear BSD license. See README for more details.
8 */
9
10#include "sigma_dut.h"
11#include <sys/types.h>
12#include <sys/stat.h>
13#include <fcntl.h>
14#include <signal.h>
15#include <ctype.h>
16
Pradeep Reddy POTTETIeeb2ccb2016-08-30 12:41:03 +053017#include "wpa_helpers.h"
18
Jouni Malinencd4e3c32015-10-29 12:39:56 +020019#ifdef ANDROID
20#define SHELL "/system/bin/sh"
21#else /* ANDROID */
22#define SHELL "/bin/sh"
23#endif /* ANDROID */
24
25
Jouni Malinencd4e3c32015-10-29 12:39:56 +020026static int cmd_traffic_send_ping(struct sigma_dut *dut,
27 struct sigma_conn *conn,
28 struct sigma_cmd *cmd)
29{
30 const char *dst, *val;
31 int size, dur, pkts;
32 int id;
33 char resp[100];
34 float interval;
35 double rate;
36 FILE *f;
37 char buf[100];
38 int type = 1;
39 int dscp = 0, use_dscp = 0;
Peng Xu1165f172018-10-05 17:44:22 -070040 char extra[100], int_arg[100], intf_arg[100], ip_dst[100];
Jouni Malinencd4e3c32015-10-29 12:39:56 +020041
42 val = get_param(cmd, "Type");
43 if (!val)
44 val = get_param(cmd, "IPType");
45 if (val)
46 type = atoi(val);
47 if (type != 1 && type != 2) {
48 send_resp(dut, conn, SIGMA_ERROR,
49 "ErrorCode,Unsupported address type");
50 return 0;
51 }
52
53 dst = get_param(cmd, "destination");
54 if (dst == NULL || (type == 1 && !is_ip_addr(dst)) ||
55 (type == 2 && !is_ipv6_addr(dst)))
56 return -1;
Peng Xu1165f172018-10-05 17:44:22 -070057 if (dut->ndp_enable && type == 2) {
58 snprintf(ip_dst, sizeof(ip_dst), "%s%%nan0", dst);
59 dst = ip_dst;
60 }
Jouni Malinencd4e3c32015-10-29 12:39:56 +020061
62 val = get_param(cmd, "frameSize");
63 if (val == NULL)
64 return -1;
65 size = atoi(val);
66
67 val = get_param(cmd, "frameRate");
68 if (val == NULL)
69 return -1;
70 rate = atof(val);
71 if (rate <= 0)
72 return -1;
73
74 val = get_param(cmd, "duration");
75 if (val == NULL)
76 return -1;
77 dur = atoi(val);
Pradeep Reddy POTTETI95093ac2016-10-13 17:22:03 +053078 if (dur <= 0 || dur > 3600)
Jouni Malinencd4e3c32015-10-29 12:39:56 +020079 dur = 3600;
80
81 pkts = dur * rate;
82 interval = (float) 1 / rate;
83 if (interval > 100000)
84 return -1;
85
86 val = get_param(cmd, "DSCP");
87 if (val) {
88 dscp = atoi(val);
89 if (dscp < 0 || dscp > 63) {
90 send_resp(dut, conn, SIGMA_ERROR,
91 "ErrorCode,Invalid DSCP value");
92 return 0;
93 }
94 use_dscp = 1;
95 }
96
97 id = dut->next_streamid++;
98 snprintf(buf, sizeof(buf), SIGMA_TMPDIR "/sigma_dut-ping.%d", id);
99 unlink(buf);
100 snprintf(buf, sizeof(buf), SIGMA_TMPDIR "/sigma_dut-ping-pid.%d", id);
101 unlink(buf);
102
103 sigma_dut_print(dut, DUT_MSG_DEBUG, "Send ping: pkts=%d interval=%f "
104 "streamid=%d",
105 pkts, interval, id);
106
107 f = fopen(SIGMA_TMPDIR "/sigma_dut-ping.sh", "w");
108 if (f == NULL)
109 return -2;
110
111 extra[0] = '\0';
112 if (use_dscp) {
113 snprintf(extra, sizeof(extra), " -Q 0x%02x",
114 dscp << 2);
115 }
116
117 int_arg[0] = '\0';
118 if (rate != 1)
119 snprintf(int_arg, sizeof(int_arg), " -i %f", interval);
Peng Xu1165f172018-10-05 17:44:22 -0700120 if (!dut->ndp_enable && type == 2)
Purushottam Kushwahaa11683a2017-12-11 12:36:43 +0530121 snprintf(intf_arg, sizeof(intf_arg), " -I %s",
122 get_station_ifname());
Peng Xu1165f172018-10-05 17:44:22 -0700123 else
124 intf_arg[0] = '\0';
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200125 fprintf(f, "#!" SHELL "\n"
Purushottam Kushwahaa11683a2017-12-11 12:36:43 +0530126 "ping%s -c %d%s -s %d%s -q%s %s > " SIGMA_TMPDIR
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200127 "/sigma_dut-ping.%d &\n"
128 "echo $! > " SIGMA_TMPDIR "/sigma_dut-ping-pid.%d\n",
Pradeep Reddy POTTETIeeb2ccb2016-08-30 12:41:03 +0530129 type == 2 ? "6" : "", pkts, int_arg, size, extra,
Purushottam Kushwahaa11683a2017-12-11 12:36:43 +0530130 intf_arg, dst, id, id);
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200131
132 fclose(f);
133 if (chmod(SIGMA_TMPDIR "/sigma_dut-ping.sh",
134 S_IRUSR | S_IWUSR | S_IXUSR) < 0)
135 return -2;
136
137 if (system(SIGMA_TMPDIR "/sigma_dut-ping.sh") != 0) {
138 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to start ping");
139 return -2;
140 }
141
142 unlink(SIGMA_TMPDIR "/sigma_dut-ping.sh");
143
144 snprintf(resp, sizeof(resp), "streamID,%d", id);
145 send_resp(dut, conn, SIGMA_COMPLETE, resp);
146 return 0;
147}
148
149
150static int cmd_traffic_stop_ping(struct sigma_dut *dut,
151 struct sigma_conn *conn,
152 struct sigma_cmd *cmd)
153{
154 const char *val;
155 int id, pid;
156 FILE *f;
157 char buf[100];
158 int res_found = 0, sent = 0, received = 0;
159
160 val = get_param(cmd, "streamID");
161 if (val == NULL)
162 return -1;
163 id = atoi(val);
164
165 snprintf(buf, sizeof(buf), SIGMA_TMPDIR "/sigma_dut-ping-pid.%d", id);
166 f = fopen(buf, "r");
167 if (f == NULL) {
168 send_resp(dut, conn, SIGMA_ERROR,
169 "ErrorCode,Unknown streamID");
170 return 0;
171 }
172 if (fscanf(f, "%d", &pid) != 1 || pid <= 0) {
173 sigma_dut_print(dut, DUT_MSG_ERROR, "No PID for ping process");
174 fclose(f);
175 unlink(buf);
176 return -2;
177 }
178
179 fclose(f);
180 unlink(buf);
181
182 sigma_dut_print(dut, DUT_MSG_DEBUG, "Ping process pid %d", pid);
183 if (kill(pid, SIGINT) < 0 && errno != ESRCH) {
184 sigma_dut_print(dut, DUT_MSG_DEBUG, "kill failed: %s",
185 strerror(errno));
186 }
187 usleep(250000);
188
189 snprintf(buf, sizeof(buf), SIGMA_TMPDIR "/sigma_dut-ping.%d", id);
190 f = fopen(buf, "r");
191 if (f == NULL) {
192 sigma_dut_print(dut, DUT_MSG_DEBUG,
193 "No ping result file found");
194 send_resp(dut, conn, SIGMA_COMPLETE, "sent,0,replies,0");
195 return 0;
196 }
197
198 while (fgets(buf, sizeof(buf), f)) {
199 char *pos;
200
201 pos = strstr(buf, " packets transmitted");
202 if (pos) {
203 pos--;
204 while (pos > buf && isdigit(pos[-1]))
205 pos--;
206 sent = atoi(pos);
207 res_found = 1;
208 }
209
210 pos = strstr(buf, " packets received");
211 if (pos == NULL)
212 pos = strstr(buf, " received");
213 if (pos) {
214 pos--;
215 while (pos > buf && isdigit(pos[-1]))
216 pos--;
217 received = atoi(pos);
218 res_found = 1;
219 }
220 }
221 fclose(f);
222 snprintf(buf, sizeof(buf), SIGMA_TMPDIR "/sigma_dut-ping.%d", id);
223 unlink(buf);
224
225 if (!res_found) {
226 sigma_dut_print(dut, DUT_MSG_DEBUG,
227 "No ping results found");
228 send_resp(dut, conn, SIGMA_COMPLETE, "sent,0,replies,0");
229 return 0;
230 }
231
232 snprintf(buf, sizeof(buf), "sent,%d,replies,%d", sent, received);
233 send_resp(dut, conn, SIGMA_COMPLETE, buf);
234 return 0;
235}
236
237
Peng Xu57784e02018-06-26 17:20:43 -0700238static int cmd_traffic_start_iperf(struct sigma_dut *dut,
239 struct sigma_conn *conn,
240 struct sigma_cmd *cmd)
241{
242 const char *val, *dst;
243 const char *iptype;
244 int port, duration;
245 const char *proto;
246 char buf[256];
247 const char *ifname;
248 char port_str[20];
249 FILE *f;
250 int server, ipv6 = 0;
251
252 val = get_param(cmd, "mode");
253 if (!val) {
254 send_resp(dut, conn, SIGMA_ERROR,
255 "errorCode,Missing mode parameter");
256 return 0;
257 }
258 server = strcasecmp(val, "server") == 0;
259
260 iptype = "";
261 val = get_param(cmd, "iptype");
262 if (val) {
263 if (strcasecmp(val, "ipv6") == 0) {
264 iptype = "-6";
265 ipv6 = 1;
266 } else {
267 iptype = "-4";
268 ipv6 = 0;
269 }
270 }
271
272 port_str[0] = '\0';
273 val = get_param(cmd, "port");
274 if (val) {
275 port = atoi(val);
276 snprintf(port_str, sizeof(port_str), "-p %d", port);
277 }
278
279 proto = "";
280 val = get_param(cmd, "transproto");
281 if (val && strcasecmp(val, "udp") == 0)
282 proto = "-u";
283
284 dst = get_param(cmd, "destination");
285 if (!server && (!dst || (!is_ip_addr(dst) && !is_ipv6_addr(dst)))) {
286 send_resp(dut, conn, SIGMA_ERROR,
287 "errorCode,Invalid destination address");
288 return 0;
289 }
290
291 if (dut->ndpe)
292 ifname = "nan0";
293 else
294 ifname = get_station_ifname();
295
296 val = get_param(cmd, "duration");
297 if (val)
298 duration = atoi(val);
299 else
300 duration = 0;
301
302 unlink(SIGMA_TMPDIR "/sigma_dut-iperf");
303 unlink(SIGMA_TMPDIR "/sigma_dut-iperf-pid");
304
305 f = fopen(SIGMA_TMPDIR "/sigma_dut-iperf.sh", "w");
306 if (!f) {
307 send_resp(dut, conn, SIGMA_ERROR,
308 "errorCode,Can not write sigma_dut-iperf.sh");
309 return 0;
310 }
311
312 if (server) {
313 /* write server side command to shell file */
314 fprintf(f, "#!" SHELL "\n"
315 "iperf3 -s %s %s > " SIGMA_TMPDIR
316 "/sigma_dut-iperf &\n"
317 "echo $! > " SIGMA_TMPDIR "/sigma_dut-iperf-pid\n",
318 port_str, iptype);
319 } else {
320 /* write client side command to shell file */
321 if (!dst)
322 return -1;
323 if (ipv6)
324 snprintf(buf, sizeof(buf), "%s%%%s", dst, ifname);
325 else
326 snprintf(buf, sizeof(buf), "%s", dst);
327 fprintf(f, "#!" SHELL "\n"
328 "iperf3 -c %s -t %d %s %s %s > " SIGMA_TMPDIR
329 "/sigma_dut-iperf &\n"
330 "echo $! > " SIGMA_TMPDIR "/sigma_dut-iperf-pid\n",
331 buf, duration, iptype, proto, port_str);
332 }
333
334 fclose(f);
335
336 if (chmod(SIGMA_TMPDIR "/sigma_dut-iperf.sh",
337 S_IRUSR | S_IWUSR | S_IXUSR) < 0) {
338 send_resp(dut, conn, SIGMA_ERROR,
339 "errorCode,Can not chmod sigma_dut-iperf.sh");
340 return 0;
341 }
342
343 sigma_dut_print(dut, DUT_MSG_DEBUG, "Starting iperf");
344 if (system(SIGMA_TMPDIR "/sigma_dut-iperf.sh") != 0) {
345 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to start iperf");
346 send_resp(dut, conn, SIGMA_ERROR,
347 "errorCode,Failed to run sigma_dut-iperf.sh");
348 return 0;
349 }
350
351 unlink(SIGMA_TMPDIR "/sigma_dut-iperf.sh");
352 return 1;
353}
354
355
356static int cmd_traffic_stop_iperf(struct sigma_dut *dut,
357 struct sigma_conn *conn,
358 struct sigma_cmd *cmd)
359{
360 int pid;
361 FILE *f;
362 char buf[100], summary_buf[100];
363 float bandwidth, totalbytes, factor;
364 char *pos;
365 long l_bandwidth, l_totalbytes;
366
367 f = fopen(SIGMA_TMPDIR "/sigma_dut-iperf-pid", "r");
368 if (!f) {
369 send_resp(dut, conn, SIGMA_ERROR,
370 "errorCode,PID file does not exist");
371 return 0;
372 }
373 if (fscanf(f, "%d", &pid) != 1 || pid <= 0) {
374 sigma_dut_print(dut, DUT_MSG_ERROR, "No PID for iperf process");
375 fclose(f);
376 unlink(SIGMA_TMPDIR "/sigma_dut-iperf-pid");
377 return -2;
378 }
379
380 fclose(f);
381 unlink(SIGMA_TMPDIR "/sigma_dut-iperf-pid");
382
383 if (kill(pid, SIGINT) < 0 && errno != ESRCH) {
384 sigma_dut_print(dut, DUT_MSG_DEBUG, "kill failed: %s",
385 strerror(errno));
386 }
387 usleep(250000);
388
389 /* parse iperf output which is stored in sigma_dut-iperf */
Peng Xu3886d5e2018-10-25 17:10:26 -0700390 summary_buf[0] = '\0';
Peng Xu57784e02018-06-26 17:20:43 -0700391 f = fopen(SIGMA_TMPDIR "/sigma_dut-iperf", "r");
392 if (!f) {
393 sigma_dut_print(dut, DUT_MSG_DEBUG,
394 "No iperf result file found");
395 send_resp(dut, conn, SIGMA_COMPLETE,
396 "bandwidth,0,totalbytes,0");
397 return 0;
398 }
399
400 /* find the last line which has the received bytes summary */
401 while (fgets(buf, sizeof(buf), f)) {
402 char *pos;
403
404 pos = strchr(buf, '\n');
405 if (pos)
406 *pos = '\0';
407 sigma_dut_print(dut, DUT_MSG_DEBUG, "iperf: %s", buf);
408 pos = strstr(buf, " sec ");
409 if (pos)
410 strlcpy(summary_buf, buf, sizeof(summary_buf));
411 }
412
413 fclose(f);
414 unlink(SIGMA_TMPDIR "/sigma_dut-iperf");
415
416 pos = strstr(summary_buf, "Bytes");
417 if (!pos || pos == summary_buf) {
418 sigma_dut_print(dut, DUT_MSG_DEBUG,
419 "Can not parse iperf results");
420 send_resp(dut, conn, SIGMA_COMPLETE,
421 "bandwidth,0,totalbytes,0");
422 return 0;
423 }
424
425 if (pos[-1] == 'G')
426 factor = 1024 * 1024 * 1024;
427 else if (pos[-1] == 'M')
428 factor = 1024 * 1024;
429 else if (pos[-1] == 'K')
430 factor = 1024;
431 else
432 factor = 1;
433
434 if (pos) {
435 pos -= 2;
436 while (pos > summary_buf && (pos[-1] != ' '))
437 pos--;
438 totalbytes = atof(pos);
439 } else
440 totalbytes = 0;
441 l_totalbytes = totalbytes * factor;
442
443 pos = strstr(summary_buf, "bits/sec");
444 if (!pos || pos == summary_buf) {
445 sigma_dut_print(dut, DUT_MSG_DEBUG,
446 "Can not parse iperf results");
447 send_resp(dut, conn, SIGMA_COMPLETE,
448 "bandwidth,0,totalbytes,0");
449 return 0;
450 }
451
452 if (pos[-1] == 'G')
453 factor = 1024 * 1024 * 1024 / 8;
454 else if (pos[-1] == 'M')
455 factor = 1024 * 1024 / 8;
456 else if (pos[-1] == 'K')
457 factor = 1024 / 8;
458 else
459 factor = 1 / 8;
460
461 if (pos && pos - summary_buf > 2) {
462 pos -= 2;
463 while (pos > summary_buf && (pos[-1] != ' '))
464 pos--;
465 bandwidth = atof(pos);
466 } else
467 bandwidth = 0;
468 l_bandwidth = bandwidth * factor;
469
470 snprintf(buf, sizeof(buf), "bandwidth,%lu,totalbytes,%lu",
471 l_bandwidth, l_totalbytes);
472 send_resp(dut, conn, SIGMA_COMPLETE, buf);
473 return 0;
474}
475
476
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200477void traffic_register_cmds(void)
478{
479 sigma_dut_reg_cmd("traffic_send_ping", NULL, cmd_traffic_send_ping);
480 sigma_dut_reg_cmd("traffic_stop_ping", NULL, cmd_traffic_stop_ping);
Peng Xu57784e02018-06-26 17:20:43 -0700481 sigma_dut_reg_cmd("traffic_start_iperf", NULL, cmd_traffic_start_iperf);
482 sigma_dut_reg_cmd("traffic_stop_iperf", NULL, cmd_traffic_stop_iperf);
Jouni Malinencd4e3c32015-10-29 12:39:56 +0200483}