blob: c0cf21fb431ba26145aa946665db83df2d64fa6d [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.
4 * Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
5 * All Rights Reserved.
6 * Licensed under the Clear BSD license. See README for more details.
7 */
8
9#include "sigma_dut.h"
10#include <sys/types.h>
11#include <sys/stat.h>
12#include <fcntl.h>
13#include <signal.h>
14#include <ctype.h>
15
16#ifdef ANDROID
17#define SHELL "/system/bin/sh"
18#else /* ANDROID */
19#define SHELL "/bin/sh"
20#endif /* ANDROID */
21
22
23static int is_ipv6_addr(const char *str)
24{
25 const char *pos = str;
26
27 while (*pos) {
28 if (*pos != ':' && (*pos < '0' || *pos > '9') &&
29 (*pos < 'a' || *pos > 'f') &&
30 (*pos < 'A' || *pos > 'F'))
31 return 0;
32 pos++;
33 }
34
35 return 1;
36}
37
38
39static int cmd_traffic_send_ping(struct sigma_dut *dut,
40 struct sigma_conn *conn,
41 struct sigma_cmd *cmd)
42{
43 const char *dst, *val;
44 int size, dur, pkts;
45 int id;
46 char resp[100];
47 float interval;
48 double rate;
49 FILE *f;
50 char buf[100];
51 int type = 1;
52 int dscp = 0, use_dscp = 0;
53 char extra[100], int_arg[100];
54
55 val = get_param(cmd, "Type");
56 if (!val)
57 val = get_param(cmd, "IPType");
58 if (val)
59 type = atoi(val);
60 if (type != 1 && type != 2) {
61 send_resp(dut, conn, SIGMA_ERROR,
62 "ErrorCode,Unsupported address type");
63 return 0;
64 }
65
66 dst = get_param(cmd, "destination");
67 if (dst == NULL || (type == 1 && !is_ip_addr(dst)) ||
68 (type == 2 && !is_ipv6_addr(dst)))
69 return -1;
70
71 val = get_param(cmd, "frameSize");
72 if (val == NULL)
73 return -1;
74 size = atoi(val);
75
76 val = get_param(cmd, "frameRate");
77 if (val == NULL)
78 return -1;
79 rate = atof(val);
80 if (rate <= 0)
81 return -1;
82
83 val = get_param(cmd, "duration");
84 if (val == NULL)
85 return -1;
86 dur = atoi(val);
87 if (dur <= 0)
88 dur = 3600;
89
90 pkts = dur * rate;
91 interval = (float) 1 / rate;
92 if (interval > 100000)
93 return -1;
94
95 val = get_param(cmd, "DSCP");
96 if (val) {
97 dscp = atoi(val);
98 if (dscp < 0 || dscp > 63) {
99 send_resp(dut, conn, SIGMA_ERROR,
100 "ErrorCode,Invalid DSCP value");
101 return 0;
102 }
103 use_dscp = 1;
104 }
105
106 id = dut->next_streamid++;
107 snprintf(buf, sizeof(buf), SIGMA_TMPDIR "/sigma_dut-ping.%d", id);
108 unlink(buf);
109 snprintf(buf, sizeof(buf), SIGMA_TMPDIR "/sigma_dut-ping-pid.%d", id);
110 unlink(buf);
111
112 sigma_dut_print(dut, DUT_MSG_DEBUG, "Send ping: pkts=%d interval=%f "
113 "streamid=%d",
114 pkts, interval, id);
115
116 f = fopen(SIGMA_TMPDIR "/sigma_dut-ping.sh", "w");
117 if (f == NULL)
118 return -2;
119
120 extra[0] = '\0';
121 if (use_dscp) {
122 snprintf(extra, sizeof(extra), " -Q 0x%02x",
123 dscp << 2);
124 }
125
126 int_arg[0] = '\0';
127 if (rate != 1)
128 snprintf(int_arg, sizeof(int_arg), " -i %f", interval);
129 fprintf(f, "#!" SHELL "\n"
130 "ping%s -c %d%s -s %d%s -q %s > " SIGMA_TMPDIR
131 "/sigma_dut-ping.%d &\n"
132 "echo $! > " SIGMA_TMPDIR "/sigma_dut-ping-pid.%d\n",
133 type == 2 ? "6" : "", pkts, int_arg, size, extra, dst, id, id);
134
135 fclose(f);
136 if (chmod(SIGMA_TMPDIR "/sigma_dut-ping.sh",
137 S_IRUSR | S_IWUSR | S_IXUSR) < 0)
138 return -2;
139
140 if (system(SIGMA_TMPDIR "/sigma_dut-ping.sh") != 0) {
141 sigma_dut_print(dut, DUT_MSG_ERROR, "Failed to start ping");
142 return -2;
143 }
144
145 unlink(SIGMA_TMPDIR "/sigma_dut-ping.sh");
146
147 snprintf(resp, sizeof(resp), "streamID,%d", id);
148 send_resp(dut, conn, SIGMA_COMPLETE, resp);
149 return 0;
150}
151
152
153static int cmd_traffic_stop_ping(struct sigma_dut *dut,
154 struct sigma_conn *conn,
155 struct sigma_cmd *cmd)
156{
157 const char *val;
158 int id, pid;
159 FILE *f;
160 char buf[100];
161 int res_found = 0, sent = 0, received = 0;
162
163 val = get_param(cmd, "streamID");
164 if (val == NULL)
165 return -1;
166 id = atoi(val);
167
168 snprintf(buf, sizeof(buf), SIGMA_TMPDIR "/sigma_dut-ping-pid.%d", id);
169 f = fopen(buf, "r");
170 if (f == NULL) {
171 send_resp(dut, conn, SIGMA_ERROR,
172 "ErrorCode,Unknown streamID");
173 return 0;
174 }
175 if (fscanf(f, "%d", &pid) != 1 || pid <= 0) {
176 sigma_dut_print(dut, DUT_MSG_ERROR, "No PID for ping process");
177 fclose(f);
178 unlink(buf);
179 return -2;
180 }
181
182 fclose(f);
183 unlink(buf);
184
185 sigma_dut_print(dut, DUT_MSG_DEBUG, "Ping process pid %d", pid);
186 if (kill(pid, SIGINT) < 0 && errno != ESRCH) {
187 sigma_dut_print(dut, DUT_MSG_DEBUG, "kill failed: %s",
188 strerror(errno));
189 }
190 usleep(250000);
191
192 snprintf(buf, sizeof(buf), SIGMA_TMPDIR "/sigma_dut-ping.%d", id);
193 f = fopen(buf, "r");
194 if (f == NULL) {
195 sigma_dut_print(dut, DUT_MSG_DEBUG,
196 "No ping result file found");
197 send_resp(dut, conn, SIGMA_COMPLETE, "sent,0,replies,0");
198 return 0;
199 }
200
201 while (fgets(buf, sizeof(buf), f)) {
202 char *pos;
203
204 pos = strstr(buf, " packets transmitted");
205 if (pos) {
206 pos--;
207 while (pos > buf && isdigit(pos[-1]))
208 pos--;
209 sent = atoi(pos);
210 res_found = 1;
211 }
212
213 pos = strstr(buf, " packets received");
214 if (pos == NULL)
215 pos = strstr(buf, " received");
216 if (pos) {
217 pos--;
218 while (pos > buf && isdigit(pos[-1]))
219 pos--;
220 received = atoi(pos);
221 res_found = 1;
222 }
223 }
224 fclose(f);
225 snprintf(buf, sizeof(buf), SIGMA_TMPDIR "/sigma_dut-ping.%d", id);
226 unlink(buf);
227
228 if (!res_found) {
229 sigma_dut_print(dut, DUT_MSG_DEBUG,
230 "No ping results found");
231 send_resp(dut, conn, SIGMA_COMPLETE, "sent,0,replies,0");
232 return 0;
233 }
234
235 snprintf(buf, sizeof(buf), "sent,%d,replies,%d", sent, received);
236 send_resp(dut, conn, SIGMA_COMPLETE, buf);
237 return 0;
238}
239
240
241void traffic_register_cmds(void)
242{
243 sigma_dut_reg_cmd("traffic_send_ping", NULL, cmd_traffic_send_ping);
244 sigma_dut_reg_cmd("traffic_stop_ping", NULL, cmd_traffic_stop_ping);
245}