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