blob: 87e33198499f0d1f3f64e34669289dbc754a24e7 [file] [log] [blame]
Amir Patel8f758182019-03-14 15:07:17 +05301/*
2 * Copyright (c) 2019 The Linux Foundation. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/**
20 * file: peer rate statitistics application
21 * This file provides framework to display peer rate statistics
22 */
23#include <netinet/in.h>
24#include <arpa/inet.h>
25#include <qcatools_lib.h>
26#include <dp_rate_stats_pub.h>
27
28#ifndef min
29#define min(x, y) ((x) < (y) ? (x) : (y))
30#else
31#error confilicting defs of min
32#endif
33
34#define DP_PEER_STATS_PRINT(fmt, ...) \
35 do { \
36 printf(fmt, ##__VA_ARGS__); \
37 printf("\n"); \
38 } while (0)
39
40char interface[IFNAMSIZ];
41
42static void dp_peer_rx_rate_stats_print(uint8_t *peer_mac,
43 uint64_t peer_cookie,
44 void *buffer,
45 uint32_t buffer_len)
46{
47 int i = 0;
48 struct wlan_rx_rate_stats *rx_stats;
49
50 rx_stats = (struct wlan_rx_rate_stats *)buffer;
51 DP_PEER_STATS_PRINT("\n......................................");
52 DP_PEER_STATS_PRINT("......................................");
53 DP_PEER_STATS_PRINT("PEER %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
54 peer_mac[0],
55 peer_mac[1],
56 peer_mac[2],
57 peer_mac[3],
58 peer_mac[4],
59 peer_mac[5]);
60 DP_PEER_STATS_PRINT("\tpeer cookie: %016llx\n",
61 peer_cookie);
62 DP_PEER_STATS_PRINT("\n..............................................");
63 DP_PEER_STATS_PRINT("................................");
64 DP_PEER_STATS_PRINT("................................................");
65 DP_PEER_STATS_PRINT(".................................\n");
66 DP_PEER_STATS_PRINT("\tRx statistics:");
67 DP_PEER_STATS_PRINT(" %10s | %10s | %10s | %10s | %10s | %10s",
68 "rate",
69 "rix",
70 "bytes",
71 "msdus",
72 "mpdus",
73 "ppdus");
74 DP_PEER_STATS_PRINT("\t\t%10s | %10s | %10s | %10s | %10s | %10s |",
75 "retries",
76 "rssi",
77 "rssi 1 p20",
78 "rssi 1 e20",
79 "rssi 1 e40",
80 "rssi 1 e80");
81 DP_PEER_STATS_PRINT(" | %10s | | %10s | %10s | %10s | %10s | %10s",
82 "rssi 2 p20",
83 "rssi 2 e20",
84 "rssi 2 e40",
85 "rssi 2 e80",
86 "rssi 3 p20",
87 "rssi 3 e20");
88 DP_PEER_STATS_PRINT(" | %10s | %10s | %10s | %10s | %10s\n\n\n",
89 "rssi 3 e40",
90 "rssi 3 e80",
91 "rssi 4 p20",
92 "rssi 4 e20",
93 "rssi 4 e40",
94 "rssi 4 e80");
95
96 for (i = 0; i < WLANSTATS_MAX_NODE; i++) {
97 DP_PEER_STATS_PRINT("\t\t%10u | %10u | %10u | %10u | %10u |",
98 rx_stats->rate,
99 rx_stats->rix,
100 rx_stats->num_bytes,
101 rx_stats->num_msdus,
102 rx_stats->num_mpdus,
103 );
104 DP_PEER_STATS_PRINT(" %10u | %10u | %10u | %10u | %10u |",
105 rx_stats->num_ppdus,
106 rx_stats->num_retries,
107 rx_stats->num_sgi,
108 rx_stats->avg_rssi,
109 rx_stats->avg_rssi_ant[0][0]);
110 DP_PEER_STATS_PRINT(" %10u | %10u | %10u | %10u | %10u |",
111 rx_stats->avg_rssi_ant[0][1],
112 rx_stats->avg_rssi_ant[0][2],
113 rx_stats->avg_rssi_ant[0][3],
114 rx_stats->avg_rssi_ant[1][0],
115 rx_stats->avg_rssi_ant[1][1]);
116 DP_PEER_STATS_PRINT(" %10u | %10u | %10u | %10u | %10u |",
117 rx_stats->avg_rssi_ant[1][2],
118 rx_stats->avg_rssi_ant[1][3],
119 rx_stats->avg_rssi_ant[2][0],
120 rx_stats->avg_rssi_ant[2][1],
121 rx_stats->avg_rssi_ant[2][2]);
122 DP_PEER_STATS_PRINT(" %10u | %10u | %10u\n\n\n",
123 rx_stats->avg_rssi_ant[2][3],
124 rx_stats->avg_rssi_ant[3][0],
125 rx_stats->avg_rssi_ant[3][1],
126 rx_stats->avg_rssi_ant[3][2],
127 rx_stats->avg_rssi_ant[3][3]);
128 rx_stats = rx_stats + 1;
129 }
130}
131
132static void
133dp_peer_tx_sojourn_stats_print(uint8_t *peer_mac,
134 uint64_t peer_cookie,
135 struct wlan_tx_sojourn_stats *sojourn_stats)
136{
137 uint8_t tid;
138
139 DP_PEER_STATS_PRINT("\n..........................................");
140 DP_PEER_STATS_PRINT("....................................");
141 DP_PEER_STATS_PRINT("....................................");
142 DP_PEER_STATS_PRINT(".........................................\n");
143 DP_PEER_STATS_PRINT("PEER%02hhx:%02hhx:%02hhx:%02hhx%02hhx:%02hhx\n",
144 peer_mac[0],
145 peer_mac[1],
146 peer_mac[2],
147 peer_mac[3],
148 peer_mac[4],
149 peer_mac[5]);
150 DP_PEER_STATS_PRINT("\tPEER Cookie: %016llx\n",
151 peer_cookie);
152 DP_PEER_STATS_PRINT("\n...........................................");
153 DP_PEER_STATS_PRINT("...................................");
154 DP_PEER_STATS_PRINT("..................................");
155 DP_PEER_STATS_PRINT("............................................");
156 DP_PEER_STATS_PRINT("\n\tSojourn statistics:\n");
157 DP_PEER_STATS_PRINT("\t\t%10s %10s %20s %20s\n",
158 "tid",
159 "ave",
160 "sum",
161 "num");
162
163 for (tid = 0; tid < WLAN_DATA_TID_MAX; tid++) {
164 /* change sum_sojourn_msdu data type to u64 */
165 DP_PEER_STATS_PRINT("\t\t%10d %10u %20u %20u\n",
166 tid,
167 sojourn_stats->avg_sojourn_msdu[tid],
168 sojourn_stats->sum_sojourn_msdu[tid],
169 sojourn_stats->num_msdus[tid]);
170 }
171 DP_PEER_STATS_PRINT("\n...........................................");
172 DP_PEER_STATS_PRINT("...................................");
173 DP_PEER_STATS_PRINT("...................................");
174 DP_PEER_STATS_PRINT("...........................................\n");
175}
176
177static void dp_peer_tx_rate_stats_print(uint8_t *peer_mac,
178 uint64_t peer_cookie,
179 void *buffer,
180 uint32_t buffer_len)
181{
182 int i = 0;
183 struct wlan_tx_rate_stats *tx_stats;
184 struct wlan_tx_sojourn_stats *sojourn_stats;
185
186 if (buffer_len < (WLANSTATS_MAX_NODE *
187 sizeof(struct wlan_tx_rate_stats))
188 + sizeof(struct wlan_tx_sojourn_stats)) {
189 DP_PEER_STATS_PRINT("invalid buffer len, return");
190 return;
191 }
192 tx_stats = (struct wlan_tx_rate_stats *)buffer;
193 DP_PEER_STATS_PRINT("\n...........................................");
194 DP_PEER_STATS_PRINT("...................................");
195 DP_PEER_STATS_PRINT("...................................");
196 DP_PEER_STATS_PRINT("...........................................\n");
197 DP_PEER_STATS_PRINT("PEER%02hhx:%02hhx:%02hhx:%02hhx%02hhx:%02hhx\n\n",
198 peer_mac[0],
199 peer_mac[1],
200 peer_mac[2],
201 peer_mac[3],
202 peer_mac[4],
203 peer_mac[5]);
204 DP_PEER_STATS_PRINT("\tPEER Cookie: %016llx",
205 peer_cookie);
206 DP_PEER_STATS_PRINT("\n...........................................");
207 DP_PEER_STATS_PRINT("...................................");
208 DP_PEER_STATS_PRINT("...................................");
209 DP_PEER_STATS_PRINT("...........................................\n");
210 DP_PEER_STATS_PRINT("\tTx statistics:\n");
211 DP_PEER_STATS_PRINT("\t\t%10s | %10s | %10s | %10s | %10s",
212 "rate",
213 "rix",
214 "attempts",
215 "success",
216 "ppdus");
217 for (i = 0; i < WLANSTATS_MAX_NODE; i++) {
218 DP_PEER_STATS_PRINT("\t\t%10u | %10u | %10u | %10u | %10u\n",
219 tx_stats->rate,
220 tx_stats->rix,
221 tx_stats->mpdu_attempts,
222 tx_stats->mpdu_success,
223 tx_stats->num_ppdus);
224 tx_stats = tx_stats + 1;
225 }
226
227 sojourn_stats = buffer + (WLANSTATS_MAX_NODE *
228 sizeof(struct wlan_tx_rate_stats));
229 dp_peer_tx_sojourn_stats_print(peer_mac, peer_cookie, sojourn_stats);
230
231 return 0;
232}
233
234static int dp_peer_stats_handler(uint32_t cache_type,
235 uint8_t *peer_mac,
236 uint64_t peer_cookie,
237 void *buffer,
238 uint32_t buffer_len)
239{
240 switch (cache_type) {
241 case DP_PEER_RX_RATE_STATS:
242 dp_peer_rx_rate_stats_print(peer_mac, peer_cookie,
243 buffer, buffer_len);
244 break;
245 case DP_PEER_TX_RATE_STATS:
246 dp_peer_tx_rate_stats_print(peer_mac, peer_cookie,
247 buffer, buffer_len);
248 break;
249 }
250}
251
252static void
253dp_peer_stats_event_callback(char *ifname,
254 uint32_t cmdid,
255 uint8_t *data,
256 size_t len)
257{
258 uint8_t cmd;
259 struct dbg_event_q_entry *q_entry;
260 int response_cookie = 0;
261 struct nlattr *tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_MAX + 1];
262 struct nlattr *tb;
263 void *buffer = NULL;
264 uint32_t buffer_len = 0;
265 uint8_t *peer_mac;
266 uint32_t cache_type;
267 uint64_t peer_cookie;
268
269 if (cmdid != QCA_NL80211_VENDOR_SUBCMD_PEER_STATS_CACHE_FLUSH) {
270 /* ignore anyother events*/
271 return;
272 }
273
274 if (strncmp(interface, ifname, sizeof(interface)) != 0) {
275 /* ignore events for other interfaces*/
276 return;
277 }
278
279 if (nla_parse(tb_array, QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_MAX,
280 (struct nlattr *)data, len, NULL)) {
281 printf("INVALID EVENT\n");
282 return;
283 }
284
285 tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_TYPE];
286 if (!tb) {
287 printf("#############%s:%d\n", __func__, __LINE__);
288 return;
289 }
290 cache_type = nla_get_u32(tb);
291
292 tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_MAC];
293 if (!tb) {
294 printf("#############%s:%d\n", __func__, __LINE__);
295 return;
296 }
297 peer_mac = (uint8_t *)nla_data(tb);
298
299 tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_DATA];
300 if (tb) {
301 buffer = (void *)nla_data(tb);
302 buffer_len = nla_len(tb);
303 }
304
305 tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_COOKIE];
306 if (!tb) {
307 printf("#############%s:%d\n", __func__, __LINE__);
308 return;
309 }
310 peer_cookie = nla_get_u64(tb);
311 if (!buffer) {
312 printf("#############%s:%d\n", __func__, __LINE__);
313 return;
314 }
315
316 dp_peer_stats_handler(cache_type, peer_mac, peer_cookie,
317 buffer, buffer_len);
318}
319
320int main(int argc, char *argv[])
321{
322 struct cfg80211_data buffer;
323 int err = 0;
324 wifi_cfg80211_context cfg80211_ctxt;
325 char *ifname;
326 int num_msecs = 0;
327 void *req_buff = NULL;
328 int req_buff_sz = 0;
329 int status = 0;
330
331 if (argc < 2) {
332 fprintf(stderr, "Invalid commands args\n");
333 return -EIO;
334 }
335
336 /* Reset the cfg80211 context to 0 if the application does not pass
337 * custom private event and command sockets. In this case, the default
338 * port is used for netlink communication.
339 */
340 memset(&cfg80211_ctxt, 0, sizeof(wifi_cfg80211_context));
341
342 ifname = argv[1];
343 memcpy(interface, ifname, sizeof(interface));
344 cfg80211_ctxt.event_callback = dp_peer_stats_event_callback;
345
346 err = wifi_init_nl80211(&cfg80211_ctxt);
347 if (err) {
348 fprintf(stderr, "unable to create NL socket\n");
349 return -EIO;
350 }
351
352 /* Starting event thread to listen for responses*/
353 if (wifi_nl80211_start_event_thread(&cfg80211_ctxt)) {
354 fprintf(stderr, "Unable to setup nl80211 event thread\n");
355 status = -EIO;
356 goto cleanup;
357 }
358
359 while (true) {
360 /*sleep for 1 ms*/
361 usleep(1000);
362 num_msecs++;
363 }
364
365 wifi_destroy_nl80211(&cfg80211_ctxt);
366 return 0;
367
368cleanup:
369 wifi_destroy_nl80211(&cfg80211_ctxt);
370 return status;
371}