blob: 18bd100d067c941497dac100460d0b1a0fc7a0bf [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
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;
49
50 rx_stats = (struct wlan_rx_rate_stats *)buffer;
Amir Patel42c63e42019-03-27 13:08:12 +053051 PRINT("\n......................................");
52 PRINT("......................................");
53 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 PRINT("\tpeer cookie: %016llx\n", peer_cookie);
61 PRINT("\n..............................................");
62 PRINT("................................");
63 PRINT("................................................");
64 PRINT(".................................\n");
65 PRINT("\tRx statistics:");
66 PRINT(" %10s | %10s | %10s | %10s | %10s | %10s",
67 "rate",
68 "rix",
69 "bytes",
70 "msdus",
71 "mpdus",
72 "ppdus");
73 PRINT("\t\t%10s | %10s | %10s | %10s | %10s | %10s |",
74 "retries",
75 "rssi",
76 "rssi 1 p20",
77 "rssi 1 e20",
78 "rssi 1 e40",
79 "rssi 1 e80");
80 PRINT(" | %10s | | %10s | %10s | %10s | %10s | %10s",
81 "rssi 2 p20",
82 "rssi 2 e20",
83 "rssi 2 e40",
84 "rssi 2 e80",
85 "rssi 3 p20",
86 "rssi 3 e20");
87 PRINT(" | %10s | %10s | %10s | %10s | %10s | %10s\n\n\n",
88 "rssi 3 e40",
89 "rssi 3 e80",
90 "rssi 4 p20",
91 "rssi 4 e20",
92 "rssi 4 e40",
93 "rssi 4 e80");
Amir Patel8f758182019-03-14 15:07:17 +053094
Pranita Solanke67a1dde2019-03-16 18:10:32 +053095 for (i = 0; i < WLANSTATS_CACHE_SIZE; i++) {
Amir Patel42c63e42019-03-27 13:08:12 +053096 if (rx_stats->rix != INVALID_CACHE_IDX) {
97 PRINT(" %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 PRINT(" %10u | %10u | %10u | %10lu | %10lu |",
104 rx_stats->num_ppdus,
105 rx_stats->num_retries,
106 rx_stats->num_sgi,
107 rx_stats->avg_rssi,
108 rx_stats->avg_rssi_ant[0][0]);
109 PRINT(" %10lu | %10lu | %10lu | %10lu | %10lu |",
110 rx_stats->avg_rssi_ant[0][1],
111 rx_stats->avg_rssi_ant[0][2],
112 rx_stats->avg_rssi_ant[0][3],
113 rx_stats->avg_rssi_ant[1][0],
114 rx_stats->avg_rssi_ant[1][1]);
115 PRINT(" %10lu | %10lu | %10lu | %10lu | %10lu |",
116 rx_stats->avg_rssi_ant[1][2],
117 rx_stats->avg_rssi_ant[1][3],
118 rx_stats->avg_rssi_ant[2][0],
119 rx_stats->avg_rssi_ant[2][1],
120 rx_stats->avg_rssi_ant[2][2]);
121 PRINT(" %10lu | %10lu | %10lu | %10lu | %10lu\n\n\n",
122 rx_stats->avg_rssi_ant[2][3],
123 rx_stats->avg_rssi_ant[3][0],
124 rx_stats->avg_rssi_ant[3][1],
125 rx_stats->avg_rssi_ant[3][2],
126 rx_stats->avg_rssi_ant[3][3]);
127 }
Amir Patel8f758182019-03-14 15:07:17 +0530128 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
Amir Patel42c63e42019-03-27 13:08:12 +0530139 PRINT("\n..........................................");
140 PRINT("....................................");
141 PRINT("....................................");
142 PRINT(".........................................\n");
143 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 PRINT("\tPEER Cookie: %016llx\n", peer_cookie);
151 PRINT("\n...........................................");
152 PRINT("...................................");
153 PRINT("..................................");
154 PRINT("............................................");
155 PRINT("\n\tSojourn statistics:\n");
156 PRINT("\t\t%10s %10s %20s %20s\n", "tid", "ave", "sum", "num");
Amir Patel8f758182019-03-14 15:07:17 +0530157
158 for (tid = 0; tid < WLAN_DATA_TID_MAX; tid++) {
159 /* change sum_sojourn_msdu data type to u64 */
Amir Patel42c63e42019-03-27 13:08:12 +0530160 PRINT("\t\t%10d %10lu %20u %20u\n",
161 tid,
162 sojourn_stats->avg_sojourn_msdu[tid],
163 sojourn_stats->sum_sojourn_msdu[tid],
164 sojourn_stats->num_msdus[tid]);
Amir Patel8f758182019-03-14 15:07:17 +0530165 }
Amir Patel42c63e42019-03-27 13:08:12 +0530166 PRINT("sizeof(avg): %d", sizeof(sojourn_stats->avg_sojourn_msdu[tid]));
167 PRINT("\n...........................................");
168 PRINT("...................................");
169 PRINT("...................................");
170 PRINT("...........................................\n");
Amir Patel8f758182019-03-14 15:07:17 +0530171}
172
173static void dp_peer_tx_rate_stats_print(uint8_t *peer_mac,
174 uint64_t peer_cookie,
175 void *buffer,
176 uint32_t buffer_len)
177{
178 int i = 0;
179 struct wlan_tx_rate_stats *tx_stats;
180 struct wlan_tx_sojourn_stats *sojourn_stats;
181
Pranita Solanke67a1dde2019-03-16 18:10:32 +0530182 if (buffer_len < (WLANSTATS_CACHE_SIZE *
Amir Patel8f758182019-03-14 15:07:17 +0530183 sizeof(struct wlan_tx_rate_stats))
184 + sizeof(struct wlan_tx_sojourn_stats)) {
Amir Patel42c63e42019-03-27 13:08:12 +0530185 PRINT("invalid buffer len, return");
Amir Patel8f758182019-03-14 15:07:17 +0530186 return;
187 }
188 tx_stats = (struct wlan_tx_rate_stats *)buffer;
Amir Patel42c63e42019-03-27 13:08:12 +0530189 PRINT("\n...........................................");
190 PRINT("...................................");
191 PRINT("...................................");
192 PRINT("...........................................\n");
193 PRINT("PEER %02hhx:%02hhx:%02hhx:%02hhx%02hhx:%02hhx\n\n",
194 peer_mac[0],
195 peer_mac[1],
196 peer_mac[2],
197 peer_mac[3],
198 peer_mac[4],
199 peer_mac[5]);
200 PRINT("\tPEER Cookie: %016llx", peer_cookie);
201 PRINT("\n...........................................");
202 PRINT("...................................");
203 PRINT("...................................");
204 PRINT("...........................................\n");
205 PRINT("\tTx statistics:\n");
206 PRINT("\t\t%10s | %10s | %10s | %10s | %10s",
207 "rate",
208 "rix",
209 "attempts",
210 "success",
211 "ppdus");
212
Pranita Solanke67a1dde2019-03-16 18:10:32 +0530213 for (i = 0; i < WLANSTATS_CACHE_SIZE; i++) {
Amir Patel42c63e42019-03-27 13:08:12 +0530214 if (tx_stats->rix != INVALID_CACHE_IDX) {
215 PRINT("\t\t%10u | %10u | %10u | %10u | %10u\n",
216 tx_stats->rate,
217 tx_stats->rix,
218 tx_stats->mpdu_attempts,
219 tx_stats->mpdu_success,
220 tx_stats->num_ppdus);
221 }
Amir Patel8f758182019-03-14 15:07:17 +0530222 tx_stats = tx_stats + 1;
223 }
224
Amir Patel42c63e42019-03-27 13:08:12 +0530225 sojourn_stats = (struct wlan_tx_sojourn_stats *)((uint8_t *)buffer
226 + (WLANSTATS_CACHE_SIZE *
227 sizeof(struct wlan_tx_rate_stats)));
Amir Patel8f758182019-03-14 15:07:17 +0530228 dp_peer_tx_sojourn_stats_print(peer_mac, peer_cookie, sojourn_stats);
229
Viyom Mittal9184b992019-03-19 16:00:08 +0530230 return;
Amir Patel8f758182019-03-14 15:07:17 +0530231}
232
Viyom Mittal9184b992019-03-19 16:00:08 +0530233static void dp_peer_stats_handler(uint32_t cache_type,
Amir Patel8f758182019-03-14 15:07:17 +0530234 uint8_t *peer_mac,
235 uint64_t peer_cookie,
236 void *buffer,
237 uint32_t buffer_len)
238{
239 switch (cache_type) {
240 case DP_PEER_RX_RATE_STATS:
241 dp_peer_rx_rate_stats_print(peer_mac, peer_cookie,
242 buffer, buffer_len);
243 break;
244 case DP_PEER_TX_RATE_STATS:
245 dp_peer_tx_rate_stats_print(peer_mac, peer_cookie,
246 buffer, buffer_len);
247 break;
248 }
249}
250
251static void
252dp_peer_stats_event_callback(char *ifname,
253 uint32_t cmdid,
254 uint8_t *data,
255 size_t len)
256{
Amir Patel8f758182019-03-14 15:07:17 +0530257 struct nlattr *tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_MAX + 1];
258 struct nlattr *tb;
259 void *buffer = NULL;
260 uint32_t buffer_len = 0;
261 uint8_t *peer_mac;
262 uint32_t cache_type;
263 uint64_t peer_cookie;
264
265 if (cmdid != QCA_NL80211_VENDOR_SUBCMD_PEER_STATS_CACHE_FLUSH) {
266 /* ignore anyother events*/
267 return;
268 }
269
270 if (strncmp(interface, ifname, sizeof(interface)) != 0) {
271 /* ignore events for other interfaces*/
272 return;
273 }
274
275 if (nla_parse(tb_array, QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_MAX,
276 (struct nlattr *)data, len, NULL)) {
Amir Patel42c63e42019-03-27 13:08:12 +0530277 PRINT("Invalid event\n");
Amir Patel8f758182019-03-14 15:07:17 +0530278 return;
279 }
280
281 tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_TYPE];
282 if (!tb) {
Amir Patel42c63e42019-03-27 13:08:12 +0530283 PRINT("Cache type in NULL, return");
Amir Patel8f758182019-03-14 15:07:17 +0530284 return;
285 }
286 cache_type = nla_get_u32(tb);
287
288 tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_MAC];
289 if (!tb) {
Amir Patel42c63e42019-03-27 13:08:12 +0530290 PRINT("Peer mac addr is null, return");
Amir Patel8f758182019-03-14 15:07:17 +0530291 return;
292 }
293 peer_mac = (uint8_t *)nla_data(tb);
294
295 tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_DATA];
296 if (tb) {
297 buffer = (void *)nla_data(tb);
298 buffer_len = nla_len(tb);
299 }
300
301 tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_COOKIE];
302 if (!tb) {
Amir Patel42c63e42019-03-27 13:08:12 +0530303 PRINT("peer cookie attribute is null, return");
Amir Patel8f758182019-03-14 15:07:17 +0530304 return;
305 }
306 peer_cookie = nla_get_u64(tb);
307 if (!buffer) {
Amir Patel42c63e42019-03-27 13:08:12 +0530308 PRINT(" stats buffer is null, return");
Amir Patel8f758182019-03-14 15:07:17 +0530309 return;
310 }
311
312 dp_peer_stats_handler(cache_type, peer_mac, peer_cookie,
313 buffer, buffer_len);
314}
315
316int main(int argc, char *argv[])
317{
Amir Patel8f758182019-03-14 15:07:17 +0530318 int err = 0;
319 wifi_cfg80211_context cfg80211_ctxt;
320 char *ifname;
321 int num_msecs = 0;
Amir Patel8f758182019-03-14 15:07:17 +0530322 int status = 0;
323
324 if (argc < 2) {
325 fprintf(stderr, "Invalid commands args\n");
326 return -EIO;
327 }
328
329 /* Reset the cfg80211 context to 0 if the application does not pass
330 * custom private event and command sockets. In this case, the default
331 * port is used for netlink communication.
332 */
333 memset(&cfg80211_ctxt, 0, sizeof(wifi_cfg80211_context));
334
335 ifname = argv[1];
336 memcpy(interface, ifname, sizeof(interface));
337 cfg80211_ctxt.event_callback = dp_peer_stats_event_callback;
338
339 err = wifi_init_nl80211(&cfg80211_ctxt);
340 if (err) {
341 fprintf(stderr, "unable to create NL socket\n");
342 return -EIO;
343 }
344
345 /* Starting event thread to listen for responses*/
346 if (wifi_nl80211_start_event_thread(&cfg80211_ctxt)) {
347 fprintf(stderr, "Unable to setup nl80211 event thread\n");
348 status = -EIO;
349 goto cleanup;
350 }
351
352 while (true) {
353 /*sleep for 1 ms*/
354 usleep(1000);
355 num_msecs++;
356 }
357
358 wifi_destroy_nl80211(&cfg80211_ctxt);
359 return 0;
360
361cleanup:
362 wifi_destroy_nl80211(&cfg80211_ctxt);
363 return status;
364}