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