blob: 0cd1a655d7dae6b92144deb6fbf1e54d07d2a0fe [file] [log] [blame]
Amir Patel8f758182019-03-14 15:07:17 +05301/*
Debasis Dasfc04e122019-11-15 14:56:16 +05302 * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
Amir Patel8f758182019-03-14 15:07:17 +05303 *
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
Amir Patel42c63e42019-03-27 13:08:12 +053034#define PRINT(fmt, ...) \
Amir Patel8f758182019-03-14 15:07:17 +053035 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;
Amir Patel936900d2019-05-17 15:40:53 +053049 uint8_t is_lithium;
50 uint8_t chain, max_chain, bw, max_bw;
51 struct wlan_rx_rate_stats *tmp_rx_stats;;
Amir Patel8f758182019-03-14 15:07:17 +053052
Amir Patel936900d2019-05-17 15:40:53 +053053 rx_stats = tmp_rx_stats = (struct wlan_rx_rate_stats *)buffer;
Amir Patel42c63e42019-03-27 13:08:12 +053054 PRINT("\n......................................");
55 PRINT("......................................");
56 PRINT("PEER %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
57 peer_mac[0],
58 peer_mac[1],
59 peer_mac[2],
60 peer_mac[3],
61 peer_mac[4],
62 peer_mac[5]);
Debasis Dasfc04e122019-11-15 14:56:16 +053063 PRINT("\tpeer cookie: %016"PRIx64"\n",
64 (peer_cookie & 0xFFFFFFFF00000000) >>
65 WLANSTATS_PEER_COOKIE_LSB);
Amir Patel936900d2019-05-17 15:40:53 +053066 is_lithium = (peer_cookie & WLANSTATS_COOKIE_PLATFORM_OFFSET)
67 >> WLANSTATS_PEER_COOKIE_LSB;
68 if (is_lithium) {
69 max_chain = 8;
70 max_bw = 8;
71 } else {
72 max_chain = 4;
73 max_bw = 4;
74 }
Amir Patel42c63e42019-03-27 13:08:12 +053075 PRINT("\n..............................................");
76 PRINT("................................");
77 PRINT("................................................");
78 PRINT(".................................\n");
79 PRINT("\tRx statistics:");
Amir Patel936900d2019-05-17 15:40:53 +053080 PRINT(" %10s | %10s | %10s | %10s | %10s | %10s|",
Amir Patel42c63e42019-03-27 13:08:12 +053081 "rate",
82 "rix",
83 "bytes",
84 "msdus",
85 "mpdus",
86 "ppdus");
Amir Patel936900d2019-05-17 15:40:53 +053087 PRINT(" %10s | %10s | %10s |",
Amir Patel42c63e42019-03-27 13:08:12 +053088 "retries",
Amir Patel936900d2019-05-17 15:40:53 +053089 "sgi",
90 "rssi\n");
Amir Patel8f758182019-03-14 15:07:17 +053091
Pranita Solanke67a1dde2019-03-16 18:10:32 +053092 for (i = 0; i < WLANSTATS_CACHE_SIZE; i++) {
Amir Patel42c63e42019-03-27 13:08:12 +053093 if (rx_stats->rix != INVALID_CACHE_IDX) {
Amir Patel936900d2019-05-17 15:40:53 +053094 PRINT(" %10u | %10u | %10u | %10u | %10u | %10u |",
Amir Patel42c63e42019-03-27 13:08:12 +053095 rx_stats->rate,
Amir Patel737f4262019-08-14 09:54:38 +053096 GET_DP_PEER_STATS_RIX(rx_stats->rix),
Amir Patel42c63e42019-03-27 13:08:12 +053097 rx_stats->num_bytes,
98 rx_stats->num_msdus,
Amir Patel936900d2019-05-17 15:40:53 +053099 rx_stats->num_mpdus,
100 rx_stats->num_ppdus);
Aakanksha Dodadeba7142019-07-01 14:45:10 +0530101 PRINT(" %10u | %10u | %10lu |\n",
Amir Patel42c63e42019-03-27 13:08:12 +0530102 rx_stats->num_retries,
103 rx_stats->num_sgi,
Amir Patel936900d2019-05-17 15:40:53 +0530104 rx_stats->avg_rssi);
Amir Patel42c63e42019-03-27 13:08:12 +0530105 }
Amir Patel8f758182019-03-14 15:07:17 +0530106 rx_stats = rx_stats + 1;
107 }
Amir Patel936900d2019-05-17 15:40:53 +0530108 if (is_lithium) {
109 PRINT("\n %10s | %10s | %10s | %10s | %10s |",
110 "rate",
111 "rssi 1 p20",
112 "rssi 1 e20",
113 "rssi 1 e40 low20",
114 "rssi 1 e40 high20");
115 PRINT("\n | %10s | %10s | %10s | %10s |",
116 "rssi 1 ext80 low20",
117 "rssi 1 ext80 low_high20",
118 "rssi 1 ext80 high_low20",
119 "rssi 1 ext80 high20");
120 PRINT("\n | %10s | %10s | %10s | %10s |",
121 "rssi 2 p20",
122 "rssi 2 e20",
123 "rssi 2 e40 low20",
124 "rssi 2 e40 high20");
125 PRINT("\n | %10s | %10s | %10s | %10s |",
126 "rssi 2 ext80 low20",
127 "rssi 2 ext80 low_high20",
128 "rssi 2 ext80 high_low20",
129 "rssi 2 ext80 high20");
130 PRINT("\n | %10s | %10s | %10s | %10s |",
131 "rssi 3 p20",
132 "rssi 3 e20",
133 "rssi 3 e40 low20",
134 "rssi 3 e40 high20");
135 PRINT("\n | %10s | %10s | %10s | %10s |",
136 "rssi 3 ext80 low20",
137 "rssi 3 ext80 low_high20",
138 "rssi 3 ext80 high_low20",
139 "rssi 3 ext80 high20");
140 PRINT("\n | %10s | %10s | %10s | %10s |",
141 "rssi 4 p20",
142 "rssi 4 e20",
143 "rssi 4 e40 low20",
144 "rssi 4 e40 high20");
145 PRINT("\n | %10s | %10s | %10s | %10s |",
146 "rssi 4 ext80 low20",
147 "rssi 4 ext80 low_high20",
148 "rssi 4 ext80 high_low20",
149 "rssi 4 ext80 high20");
150 PRINT("\n | %10s | %10s | %10s | %10s |",
151 "rssi 5 p20",
152 "rssi 5 e20",
153 "rssi 5 e40 low20",
154 "rssi 5 e40 high20");
155 PRINT("\n | %10s | %10s | %10s | %10s |",
156 "rssi 5 ext80 low20",
157 "rssi 5 ext80 low_high20",
158 "rssi 5 ext80 high_low20",
159 "rssi 5 ext80 high20");
160 PRINT("\n | %10s | %10s | %10s | %10s |",
161 "rssi 6 p20",
162 "rssi 6 e20",
163 "rssi 6 e40 low20",
164 "rssi 6 e40 high20");
165 PRINT("\n | %10s | %10s | %10s | %10s |",
166 "rssi 6 ext80 low20",
167 "rssi 6 ext80 low_high20",
168 "rssi 6 ext80 high_low20",
169 "rssi 6 ext80 high20");
170 PRINT("\n | %10s | %10s | %10s | %10s |",
171 "rssi 7 p20",
172 "rssi 7 e20",
173 "rssi 7 e40 low20",
174 "rssi 7 e40 high20");
175 PRINT("\n | %10s | %10s | %10s | %10s |",
176 "rssi 7 ext80 low20",
177 "rssi 7 ext80 low_high20",
178 "rssi 7 ext80 high_low20",
179 "rssi 7 ext80 high20");
180 PRINT("\n | %10s | %10s | %10s | %10s |",
181 "rssi 8 p20",
182 "rssi 8 e20",
183 "rssi 8 e40 low20",
184 "rssi 8 e40 high20");
185 PRINT("\n | %10s | %10s | %10s | %10s |\n\n\n",
186 "rssi 8 ext80 low20",
187 "rssi 8 ext80 low_high20",
188 "rssi 8 ext80 high_low20",
189 "rssi 8 ext80 high20");
190 } else {
191 PRINT("\n %10s | %10s | %10s | %10s | %10s |",
192 "rate",
193 "rssi 1 p20",
194 "rssi 1 e20",
195 "rssi 1 e40",
196 "rssi 1 e80");
197 PRINT(" | %10s | %10s | %10s | %10s |",
198 "rssi 2 p20",
199 "rssi 2 e20",
200 "rssi 2 e40",
201 "rssi 2 e80");
202 PRINT(" | %10s | %10s | %10s | %10s |",
203 "rssi 3 p20",
204 "rssi 3 e20",
205 "rssi 3 e40",
206 "rssi 3 e80");
207 PRINT(" | %10s | %10s | %10s | %10s |\n\n\n",
208 "rssi 4 p20",
209 "rssi 4 e20",
210 "rssi 4 e40",
211 "rssi 4 e80");
212 }
213 for (i = 0; i < WLANSTATS_CACHE_SIZE; i++) {
214 if (tmp_rx_stats->rix != INVALID_CACHE_IDX) {
215 printf(" %10u |", tmp_rx_stats->rate);
216 for (chain = 0; chain < max_chain; chain++) {
217 for (bw = 0; bw < max_bw; bw++) {
velagapudi sureshead022e2019-07-08 14:46:38 +0530218 printf(" %10lu |",
Amir Patel936900d2019-05-17 15:40:53 +0530219 tmp_rx_stats->avg_rssi_ant[chain][bw]);
220 }
221 printf(" \n\t ");
222 }
Aakanksha Dodadeba7142019-07-01 14:45:10 +0530223 PRINT(" ");
Amir Patel936900d2019-05-17 15:40:53 +0530224 }
225 tmp_rx_stats = tmp_rx_stats + 1;
226 }
Amir Patel8f758182019-03-14 15:07:17 +0530227}
228
229static void
230dp_peer_tx_sojourn_stats_print(uint8_t *peer_mac,
231 uint64_t peer_cookie,
232 struct wlan_tx_sojourn_stats *sojourn_stats)
233{
234 uint8_t tid;
235
Amir Patel42c63e42019-03-27 13:08:12 +0530236 PRINT("\n..........................................");
237 PRINT("....................................");
238 PRINT("....................................");
239 PRINT(".........................................\n");
240 PRINT("PEER %02hhx:%02hhx:%02hhx:%02hhx%02hhx:%02hhx\n",
241 peer_mac[0],
242 peer_mac[1],
243 peer_mac[2],
244 peer_mac[3],
245 peer_mac[4],
246 peer_mac[5]);
Debasis Dasfc04e122019-11-15 14:56:16 +0530247 PRINT("\tPEER Cookie: %016"PRIx64"\n", peer_cookie);
Amir Patel42c63e42019-03-27 13:08:12 +0530248 PRINT("\n...........................................");
249 PRINT("...................................");
250 PRINT("..................................");
251 PRINT("............................................");
252 PRINT("\n\tSojourn statistics:\n");
253 PRINT("\t\t%10s %10s %20s %20s\n", "tid", "ave", "sum", "num");
Amir Patel8f758182019-03-14 15:07:17 +0530254
255 for (tid = 0; tid < WLAN_DATA_TID_MAX; tid++) {
256 /* change sum_sojourn_msdu data type to u64 */
Amir Patel42c63e42019-03-27 13:08:12 +0530257 PRINT("\t\t%10d %10lu %20u %20u\n",
258 tid,
259 sojourn_stats->avg_sojourn_msdu[tid],
260 sojourn_stats->sum_sojourn_msdu[tid],
261 sojourn_stats->num_msdus[tid]);
Amir Patel8f758182019-03-14 15:07:17 +0530262 }
Debasis Das107c3582020-03-08 21:11:39 +0530263#ifdef __LP64__
264 PRINT("sizeof(avg) : %"PRIu64,
265#else
266 PRINT("sizeof(avg) : %"PRIu32,
267#endif
Debasis Dasfc04e122019-11-15 14:56:16 +0530268 sizeof(sojourn_stats->avg_sojourn_msdu[tid]));
Amir Patel42c63e42019-03-27 13:08:12 +0530269 PRINT("\n...........................................");
270 PRINT("...................................");
271 PRINT("...................................");
272 PRINT("...........................................\n");
Amir Patel8f758182019-03-14 15:07:17 +0530273}
274
275static void dp_peer_tx_rate_stats_print(uint8_t *peer_mac,
276 uint64_t peer_cookie,
277 void *buffer,
278 uint32_t buffer_len)
279{
280 int i = 0;
281 struct wlan_tx_rate_stats *tx_stats;
282 struct wlan_tx_sojourn_stats *sojourn_stats;
283
Pranita Solanke67a1dde2019-03-16 18:10:32 +0530284 if (buffer_len < (WLANSTATS_CACHE_SIZE *
Amir Patel8f758182019-03-14 15:07:17 +0530285 sizeof(struct wlan_tx_rate_stats))
286 + sizeof(struct wlan_tx_sojourn_stats)) {
Amir Patel42c63e42019-03-27 13:08:12 +0530287 PRINT("invalid buffer len, return");
Amir Patel8f758182019-03-14 15:07:17 +0530288 return;
289 }
290 tx_stats = (struct wlan_tx_rate_stats *)buffer;
Amir Patel42c63e42019-03-27 13:08:12 +0530291 PRINT("\n...........................................");
292 PRINT("...................................");
293 PRINT("...................................");
294 PRINT("...........................................\n");
295 PRINT("PEER %02hhx:%02hhx:%02hhx:%02hhx%02hhx:%02hhx\n\n",
296 peer_mac[0],
297 peer_mac[1],
298 peer_mac[2],
299 peer_mac[3],
300 peer_mac[4],
301 peer_mac[5]);
Debasis Dasfc04e122019-11-15 14:56:16 +0530302 PRINT("\tPEER Cookie: %016"PRIx64, peer_cookie);
Amir Patel42c63e42019-03-27 13:08:12 +0530303 PRINT("\n...........................................");
304 PRINT("...................................");
305 PRINT("...................................");
306 PRINT("...........................................\n");
307 PRINT("\tTx statistics:\n");
308 PRINT("\t\t%10s | %10s | %10s | %10s | %10s",
309 "rate",
310 "rix",
311 "attempts",
312 "success",
313 "ppdus");
Amir Patela74d4df2019-08-14 14:45:35 +0530314 PRINT(" %10s | %10s | %10s |",
315 "msdus",
316 "bytes",
317 "retries\n");
Amir Patel42c63e42019-03-27 13:08:12 +0530318
Pranita Solanke67a1dde2019-03-16 18:10:32 +0530319 for (i = 0; i < WLANSTATS_CACHE_SIZE; i++) {
Amir Patel42c63e42019-03-27 13:08:12 +0530320 if (tx_stats->rix != INVALID_CACHE_IDX) {
321 PRINT("\t\t%10u | %10u | %10u | %10u | %10u\n",
322 tx_stats->rate,
Amir Patel737f4262019-08-14 09:54:38 +0530323 GET_DP_PEER_STATS_RIX(tx_stats->rix),
Amir Patel42c63e42019-03-27 13:08:12 +0530324 tx_stats->mpdu_attempts,
325 tx_stats->mpdu_success,
326 tx_stats->num_ppdus);
Debasis Dasfc04e122019-11-15 14:56:16 +0530327 PRINT(" %10u | %10u | %10u |\n",
Amir Patela74d4df2019-08-14 14:45:35 +0530328 tx_stats->num_msdus,
329 tx_stats->num_bytes,
330 tx_stats->num_retries);
Amir Patel42c63e42019-03-27 13:08:12 +0530331 }
Amir Patel8f758182019-03-14 15:07:17 +0530332 tx_stats = tx_stats + 1;
333 }
334
Amir Patel42c63e42019-03-27 13:08:12 +0530335 sojourn_stats = (struct wlan_tx_sojourn_stats *)((uint8_t *)buffer
336 + (WLANSTATS_CACHE_SIZE *
337 sizeof(struct wlan_tx_rate_stats)));
Amir Patel8f758182019-03-14 15:07:17 +0530338 dp_peer_tx_sojourn_stats_print(peer_mac, peer_cookie, sojourn_stats);
339
Viyom Mittal9184b992019-03-19 16:00:08 +0530340 return;
Amir Patel8f758182019-03-14 15:07:17 +0530341}
342
Viyom Mittal9184b992019-03-19 16:00:08 +0530343static void dp_peer_stats_handler(uint32_t cache_type,
Amir Patel8f758182019-03-14 15:07:17 +0530344 uint8_t *peer_mac,
345 uint64_t peer_cookie,
346 void *buffer,
347 uint32_t buffer_len)
348{
349 switch (cache_type) {
350 case DP_PEER_RX_RATE_STATS:
351 dp_peer_rx_rate_stats_print(peer_mac, peer_cookie,
352 buffer, buffer_len);
353 break;
354 case DP_PEER_TX_RATE_STATS:
355 dp_peer_tx_rate_stats_print(peer_mac, peer_cookie,
356 buffer, buffer_len);
357 break;
358 }
359}
360
361static void
362dp_peer_stats_event_callback(char *ifname,
363 uint32_t cmdid,
364 uint8_t *data,
365 size_t len)
366{
Amir Patel8f758182019-03-14 15:07:17 +0530367 struct nlattr *tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_MAX + 1];
368 struct nlattr *tb;
369 void *buffer = NULL;
370 uint32_t buffer_len = 0;
371 uint8_t *peer_mac;
372 uint32_t cache_type;
373 uint64_t peer_cookie;
374
375 if (cmdid != QCA_NL80211_VENDOR_SUBCMD_PEER_STATS_CACHE_FLUSH) {
376 /* ignore anyother events*/
377 return;
378 }
379
380 if (strncmp(interface, ifname, sizeof(interface)) != 0) {
381 /* ignore events for other interfaces*/
382 return;
383 }
384
385 if (nla_parse(tb_array, QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_MAX,
386 (struct nlattr *)data, len, NULL)) {
Amir Patel42c63e42019-03-27 13:08:12 +0530387 PRINT("Invalid event\n");
Amir Patel8f758182019-03-14 15:07:17 +0530388 return;
389 }
390
391 tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_TYPE];
392 if (!tb) {
Amir Patel42c63e42019-03-27 13:08:12 +0530393 PRINT("Cache type in NULL, return");
Amir Patel8f758182019-03-14 15:07:17 +0530394 return;
395 }
396 cache_type = nla_get_u32(tb);
397
398 tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_MAC];
399 if (!tb) {
Amir Patel42c63e42019-03-27 13:08:12 +0530400 PRINT("Peer mac addr is null, return");
Amir Patel8f758182019-03-14 15:07:17 +0530401 return;
402 }
403 peer_mac = (uint8_t *)nla_data(tb);
404
405 tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_DATA];
406 if (tb) {
407 buffer = (void *)nla_data(tb);
408 buffer_len = nla_len(tb);
409 }
410
411 tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_COOKIE];
412 if (!tb) {
Amir Patel42c63e42019-03-27 13:08:12 +0530413 PRINT("peer cookie attribute is null, return");
Amir Patel8f758182019-03-14 15:07:17 +0530414 return;
415 }
416 peer_cookie = nla_get_u64(tb);
417 if (!buffer) {
Amir Patel42c63e42019-03-27 13:08:12 +0530418 PRINT(" stats buffer is null, return");
Amir Patel8f758182019-03-14 15:07:17 +0530419 return;
420 }
421
422 dp_peer_stats_handler(cache_type, peer_mac, peer_cookie,
423 buffer, buffer_len);
424}
425
426int main(int argc, char *argv[])
427{
Amir Patel8f758182019-03-14 15:07:17 +0530428 int err = 0;
429 wifi_cfg80211_context cfg80211_ctxt;
430 char *ifname;
431 int num_msecs = 0;
Amir Patel8f758182019-03-14 15:07:17 +0530432 int status = 0;
433
434 if (argc < 2) {
435 fprintf(stderr, "Invalid commands args\n");
436 return -EIO;
437 }
438
439 /* Reset the cfg80211 context to 0 if the application does not pass
440 * custom private event and command sockets. In this case, the default
441 * port is used for netlink communication.
442 */
443 memset(&cfg80211_ctxt, 0, sizeof(wifi_cfg80211_context));
444
445 ifname = argv[1];
446 memcpy(interface, ifname, sizeof(interface));
447 cfg80211_ctxt.event_callback = dp_peer_stats_event_callback;
448
449 err = wifi_init_nl80211(&cfg80211_ctxt);
450 if (err) {
451 fprintf(stderr, "unable to create NL socket\n");
452 return -EIO;
453 }
454
455 /* Starting event thread to listen for responses*/
456 if (wifi_nl80211_start_event_thread(&cfg80211_ctxt)) {
457 fprintf(stderr, "Unable to setup nl80211 event thread\n");
458 status = -EIO;
459 goto cleanup;
460 }
461
462 while (true) {
463 /*sleep for 1 ms*/
464 usleep(1000);
465 num_msecs++;
466 }
467
468 wifi_destroy_nl80211(&cfg80211_ctxt);
469 return 0;
470
471cleanup:
472 wifi_destroy_nl80211(&cfg80211_ctxt);
473 return status;
474}