peerstats.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677
  1. /*
  2. * Copyright (c) 2019-2020 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. * file: peer rate statitistics application
  20. * This file provides framework to display peer rate statistics
  21. */
  22. #include <netinet/in.h>
  23. #include <arpa/inet.h>
  24. #include <qcatools_lib.h>
  25. #include <dp_rate_stats_pub.h>
  26. #ifndef min
  27. #define min(x, y) ((x) < (y) ? (x) : (y))
  28. #else
  29. #error confilicting defs of min
  30. #endif
  31. #define PRINT(fmt, ...) \
  32. do { \
  33. printf(fmt, ##__VA_ARGS__); \
  34. printf("\n"); \
  35. } while (0)
  36. char interface[IFNAMSIZ];
  37. static void dp_peer_rx_rate_stats_print(uint8_t *peer_mac,
  38. uint64_t peer_cookie,
  39. void *buffer,
  40. uint32_t buffer_len)
  41. {
  42. int i = 0;
  43. struct wlan_rx_rate_stats *rx_stats;
  44. uint8_t is_lithium;
  45. uint8_t chain, max_chain, bw, max_bw;
  46. struct wlan_rx_rate_stats *tmp_rx_stats;;
  47. rx_stats = tmp_rx_stats = (struct wlan_rx_rate_stats *)buffer;
  48. PRINT("\n......................................");
  49. PRINT("......................................");
  50. PRINT("PEER %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
  51. peer_mac[0],
  52. peer_mac[1],
  53. peer_mac[2],
  54. peer_mac[3],
  55. peer_mac[4],
  56. peer_mac[5]);
  57. PRINT("\tpeer cookie: %016"PRIx64"\n",
  58. (peer_cookie & 0xFFFFFFFF00000000) >>
  59. WLANSTATS_PEER_COOKIE_LSB);
  60. is_lithium = (peer_cookie & WLANSTATS_COOKIE_PLATFORM_OFFSET)
  61. >> WLANSTATS_PEER_COOKIE_LSB;
  62. if (is_lithium) {
  63. max_chain = 8;
  64. max_bw = 8;
  65. } else {
  66. max_chain = 4;
  67. max_bw = 4;
  68. }
  69. PRINT("\n..............................................");
  70. PRINT("................................");
  71. PRINT("................................................");
  72. PRINT(".................................\n");
  73. PRINT("\tRx statistics:");
  74. PRINT(" %10s | %10s | %10s | %10s | %10s | %10s|",
  75. "rate",
  76. "rix",
  77. "bytes",
  78. "msdus",
  79. "mpdus",
  80. "ppdus");
  81. PRINT(" %10s | %10s | %10s |",
  82. "retries",
  83. "sgi",
  84. "rssi\n");
  85. for (i = 0; i < WLANSTATS_CACHE_SIZE; i++) {
  86. if (rx_stats->rix != INVALID_CACHE_IDX) {
  87. PRINT(" %10u | %10u | %10u | %10u | %10u | %10u |",
  88. rx_stats->rate,
  89. GET_DP_PEER_STATS_RIX(rx_stats->rix),
  90. rx_stats->num_bytes,
  91. rx_stats->num_msdus,
  92. rx_stats->num_mpdus,
  93. rx_stats->num_ppdus);
  94. PRINT(" %10u | %10u | %10lu |\n",
  95. rx_stats->num_retries,
  96. rx_stats->num_sgi,
  97. rx_stats->avg_rssi);
  98. }
  99. rx_stats = rx_stats + 1;
  100. }
  101. if (is_lithium) {
  102. PRINT("\n %10s | %10s | %10s | %10s | %10s |",
  103. "rate",
  104. "rssi 1 p20",
  105. "rssi 1 e20",
  106. "rssi 1 e40 low20",
  107. "rssi 1 e40 high20");
  108. PRINT("\n | %10s | %10s | %10s | %10s |",
  109. "rssi 1 ext80 low20",
  110. "rssi 1 ext80 low_high20",
  111. "rssi 1 ext80 high_low20",
  112. "rssi 1 ext80 high20");
  113. PRINT("\n | %10s | %10s | %10s | %10s |",
  114. "rssi 2 p20",
  115. "rssi 2 e20",
  116. "rssi 2 e40 low20",
  117. "rssi 2 e40 high20");
  118. PRINT("\n | %10s | %10s | %10s | %10s |",
  119. "rssi 2 ext80 low20",
  120. "rssi 2 ext80 low_high20",
  121. "rssi 2 ext80 high_low20",
  122. "rssi 2 ext80 high20");
  123. PRINT("\n | %10s | %10s | %10s | %10s |",
  124. "rssi 3 p20",
  125. "rssi 3 e20",
  126. "rssi 3 e40 low20",
  127. "rssi 3 e40 high20");
  128. PRINT("\n | %10s | %10s | %10s | %10s |",
  129. "rssi 3 ext80 low20",
  130. "rssi 3 ext80 low_high20",
  131. "rssi 3 ext80 high_low20",
  132. "rssi 3 ext80 high20");
  133. PRINT("\n | %10s | %10s | %10s | %10s |",
  134. "rssi 4 p20",
  135. "rssi 4 e20",
  136. "rssi 4 e40 low20",
  137. "rssi 4 e40 high20");
  138. PRINT("\n | %10s | %10s | %10s | %10s |",
  139. "rssi 4 ext80 low20",
  140. "rssi 4 ext80 low_high20",
  141. "rssi 4 ext80 high_low20",
  142. "rssi 4 ext80 high20");
  143. PRINT("\n | %10s | %10s | %10s | %10s |",
  144. "rssi 5 p20",
  145. "rssi 5 e20",
  146. "rssi 5 e40 low20",
  147. "rssi 5 e40 high20");
  148. PRINT("\n | %10s | %10s | %10s | %10s |",
  149. "rssi 5 ext80 low20",
  150. "rssi 5 ext80 low_high20",
  151. "rssi 5 ext80 high_low20",
  152. "rssi 5 ext80 high20");
  153. PRINT("\n | %10s | %10s | %10s | %10s |",
  154. "rssi 6 p20",
  155. "rssi 6 e20",
  156. "rssi 6 e40 low20",
  157. "rssi 6 e40 high20");
  158. PRINT("\n | %10s | %10s | %10s | %10s |",
  159. "rssi 6 ext80 low20",
  160. "rssi 6 ext80 low_high20",
  161. "rssi 6 ext80 high_low20",
  162. "rssi 6 ext80 high20");
  163. PRINT("\n | %10s | %10s | %10s | %10s |",
  164. "rssi 7 p20",
  165. "rssi 7 e20",
  166. "rssi 7 e40 low20",
  167. "rssi 7 e40 high20");
  168. PRINT("\n | %10s | %10s | %10s | %10s |",
  169. "rssi 7 ext80 low20",
  170. "rssi 7 ext80 low_high20",
  171. "rssi 7 ext80 high_low20",
  172. "rssi 7 ext80 high20");
  173. PRINT("\n | %10s | %10s | %10s | %10s |",
  174. "rssi 8 p20",
  175. "rssi 8 e20",
  176. "rssi 8 e40 low20",
  177. "rssi 8 e40 high20");
  178. PRINT("\n | %10s | %10s | %10s | %10s |\n\n\n",
  179. "rssi 8 ext80 low20",
  180. "rssi 8 ext80 low_high20",
  181. "rssi 8 ext80 high_low20",
  182. "rssi 8 ext80 high20");
  183. } else {
  184. PRINT("\n %10s | %10s | %10s | %10s | %10s |",
  185. "rate",
  186. "rssi 1 p20",
  187. "rssi 1 e20",
  188. "rssi 1 e40",
  189. "rssi 1 e80");
  190. PRINT(" | %10s | %10s | %10s | %10s |",
  191. "rssi 2 p20",
  192. "rssi 2 e20",
  193. "rssi 2 e40",
  194. "rssi 2 e80");
  195. PRINT(" | %10s | %10s | %10s | %10s |",
  196. "rssi 3 p20",
  197. "rssi 3 e20",
  198. "rssi 3 e40",
  199. "rssi 3 e80");
  200. PRINT(" | %10s | %10s | %10s | %10s |\n\n\n",
  201. "rssi 4 p20",
  202. "rssi 4 e20",
  203. "rssi 4 e40",
  204. "rssi 4 e80");
  205. }
  206. for (i = 0; i < WLANSTATS_CACHE_SIZE; i++) {
  207. if (tmp_rx_stats->rix != INVALID_CACHE_IDX) {
  208. printf(" %10u |", tmp_rx_stats->rate);
  209. for (chain = 0; chain < max_chain; chain++) {
  210. for (bw = 0; bw < max_bw; bw++) {
  211. printf(" %10lu |",
  212. tmp_rx_stats->avg_rssi_ant[chain][bw]);
  213. }
  214. printf(" \n\t ");
  215. }
  216. PRINT(" ");
  217. }
  218. tmp_rx_stats = tmp_rx_stats + 1;
  219. }
  220. }
  221. static void
  222. dp_peer_tx_sojourn_stats_print(uint8_t *peer_mac,
  223. uint64_t peer_cookie,
  224. struct wlan_tx_sojourn_stats *sojourn_stats)
  225. {
  226. uint8_t tid;
  227. PRINT("\n..........................................");
  228. PRINT("....................................");
  229. PRINT("....................................");
  230. PRINT(".........................................\n");
  231. PRINT("PEER %02hhx:%02hhx:%02hhx:%02hhx%02hhx:%02hhx\n",
  232. peer_mac[0],
  233. peer_mac[1],
  234. peer_mac[2],
  235. peer_mac[3],
  236. peer_mac[4],
  237. peer_mac[5]);
  238. PRINT("\tPEER Cookie: %016"PRIx64"\n", peer_cookie);
  239. PRINT("\n...........................................");
  240. PRINT("...................................");
  241. PRINT("..................................");
  242. PRINT("............................................");
  243. PRINT("\n\tSojourn statistics:\n");
  244. PRINT("\t\t%10s %10s %20s %20s\n", "tid", "ave", "sum", "num");
  245. for (tid = 0; tid < WLAN_DATA_TID_MAX; tid++) {
  246. /* change sum_sojourn_msdu data type to u64 */
  247. PRINT("\t\t%10d %10lu %20u %20u\n",
  248. tid,
  249. sojourn_stats->avg_sojourn_msdu[tid],
  250. sojourn_stats->sum_sojourn_msdu[tid],
  251. sojourn_stats->num_msdus[tid]);
  252. }
  253. #ifdef __LP64__
  254. PRINT("sizeof(avg) : %"PRIu64,
  255. #else
  256. PRINT("sizeof(avg) : %"PRIu32,
  257. #endif
  258. sizeof(sojourn_stats->avg_sojourn_msdu[tid]));
  259. PRINT("\n...........................................");
  260. PRINT("...................................");
  261. PRINT("...................................");
  262. PRINT("...........................................\n");
  263. }
  264. static void dp_peer_tx_rate_stats_print(uint8_t *peer_mac,
  265. uint64_t peer_cookie,
  266. void *buffer,
  267. uint32_t buffer_len)
  268. {
  269. int i = 0;
  270. struct wlan_tx_rate_stats *tx_stats;
  271. struct wlan_tx_sojourn_stats *sojourn_stats;
  272. if (buffer_len < (WLANSTATS_CACHE_SIZE *
  273. sizeof(struct wlan_tx_rate_stats))
  274. + sizeof(struct wlan_tx_sojourn_stats)) {
  275. PRINT("invalid buffer len, return");
  276. return;
  277. }
  278. tx_stats = (struct wlan_tx_rate_stats *)buffer;
  279. PRINT("\n...........................................");
  280. PRINT("...................................");
  281. PRINT("...................................");
  282. PRINT("...........................................\n");
  283. PRINT("PEER %02hhx:%02hhx:%02hhx:%02hhx%02hhx:%02hhx\n\n",
  284. peer_mac[0],
  285. peer_mac[1],
  286. peer_mac[2],
  287. peer_mac[3],
  288. peer_mac[4],
  289. peer_mac[5]);
  290. PRINT("\tPEER Cookie: %016"PRIx64, peer_cookie);
  291. PRINT("\n...........................................");
  292. PRINT("...................................");
  293. PRINT("...................................");
  294. PRINT("...........................................\n");
  295. PRINT("\tTx statistics:\n");
  296. PRINT("\t\t%10s | %10s | %10s | %10s | %10s",
  297. "rate",
  298. "rix",
  299. "attempts",
  300. "success",
  301. "ppdus");
  302. PRINT(" %10s | %10s | %10s |",
  303. "msdus",
  304. "bytes",
  305. "retries\n");
  306. for (i = 0; i < WLANSTATS_CACHE_SIZE; i++) {
  307. if (tx_stats->rix != INVALID_CACHE_IDX) {
  308. PRINT("\t\t%10u | %10u | %10u | %10u | %10u\n",
  309. tx_stats->rate,
  310. GET_DP_PEER_STATS_RIX(tx_stats->rix),
  311. tx_stats->mpdu_attempts,
  312. tx_stats->mpdu_success,
  313. tx_stats->num_ppdus);
  314. PRINT(" %10u | %10u | %10u |\n",
  315. tx_stats->num_msdus,
  316. tx_stats->num_bytes,
  317. tx_stats->num_retries);
  318. }
  319. tx_stats = tx_stats + 1;
  320. }
  321. sojourn_stats = (struct wlan_tx_sojourn_stats *)((uint8_t *)buffer
  322. + (WLANSTATS_CACHE_SIZE *
  323. sizeof(struct wlan_tx_rate_stats)));
  324. dp_peer_tx_sojourn_stats_print(peer_mac, peer_cookie, sojourn_stats);
  325. return;
  326. }
  327. static void dp_peer_avg_rate_stats_print(uint8_t *peer_mac,
  328. uint64_t peer_cookie,
  329. void *buffer,
  330. uint32_t buffer_len)
  331. {
  332. struct wlan_avg_rate_stats *stats = buffer;
  333. enum wlan_rate_ppdu_type type;
  334. static const char *type2str[] = {
  335. "SU",
  336. "MU-MIMO",
  337. "MU-OFDMA",
  338. "MU-MIMO-OFDMA",
  339. };
  340. uint32_t mpdu;
  341. uint32_t psr;
  342. uint32_t avg_mbps;
  343. uint32_t avg_snr;
  344. PRINT("peer %02hhx:%02hhx:%02hhx:%02hhx%02hhx:%02hhx",
  345. peer_mac[0],
  346. peer_mac[1],
  347. peer_mac[2],
  348. peer_mac[3],
  349. peer_mac[4],
  350. peer_mac[5]);
  351. PRINT(" %20s %15s %15s %15s %15s %15s",
  352. "mode",
  353. "rate(mbps)",
  354. "total ppdu",
  355. "snr value",
  356. "snr count",
  357. "psr value");
  358. PRINT("Avg tx stats: ");
  359. for (type = 0; type < WLAN_RATE_MAX; type++) {
  360. psr = 0;
  361. avg_mbps = 0;
  362. avg_snr = 0;
  363. if (stats->tx[type].num_ppdu > 0)
  364. avg_mbps = stats->tx[type].sum_mbps /
  365. stats->tx[type].num_ppdu;
  366. if (stats->tx[type].num_snr > 0)
  367. avg_snr = stats->tx[type].sum_snr /
  368. stats->tx[type].num_snr;
  369. mpdu = stats->tx[type].num_mpdu +
  370. stats->tx[type].num_retry;
  371. if (mpdu > 0)
  372. psr = (100 * stats->tx[type].num_mpdu) / mpdu;
  373. PRINT(" %20s %15u %15u %15u %15u %15u",
  374. type2str[type],
  375. avg_mbps, stats->tx[type].num_ppdu,
  376. avg_snr, stats->tx[type].num_snr,
  377. psr);
  378. }
  379. PRINT("");
  380. PRINT("Avg rx stats: ");
  381. for (type = 0; type < WLAN_RATE_MAX; type++) {
  382. psr = 0;
  383. avg_mbps = 0;
  384. avg_snr = 0;
  385. if (stats->rx[type].num_ppdu > 0)
  386. avg_mbps = stats->rx[type].sum_mbps /
  387. stats->rx[type].num_ppdu;
  388. if (stats->rx[type].num_snr > 0)
  389. avg_snr = stats->rx[type].sum_snr /
  390. stats->rx[type].num_snr;
  391. mpdu = stats->rx[type].num_mpdu +
  392. stats->rx[type].num_retry;
  393. if (mpdu > 0)
  394. psr = (100 * stats->rx[type].num_mpdu) / mpdu;
  395. PRINT(" %20s %15u %15u %15u %15u %15u",
  396. type2str[type],
  397. avg_mbps, stats->rx[type].num_ppdu,
  398. avg_snr, stats->rx[type].num_snr,
  399. psr);
  400. }
  401. PRINT("");
  402. PRINT("");
  403. }
  404. static void dp_peer_tx_link_stats_print(uint8_t *peer_mac,
  405. uint64_t peer_cookie,
  406. void *buffer,
  407. uint32_t buffer_len)
  408. {
  409. struct wlan_tx_link_stats *tx_stats;
  410. uint8_t is_lithium;
  411. is_lithium = (peer_cookie & WLANSTATS_COOKIE_PLATFORM_OFFSET)
  412. >> WLANSTATS_PEER_COOKIE_LSB;
  413. if (!is_lithium) {
  414. PRINT("Not supported in non-lithium platforms\n");
  415. return;
  416. }
  417. if (buffer_len < sizeof(struct wlan_tx_link_stats)) {
  418. PRINT("invalid buffer len, return");
  419. return;
  420. }
  421. tx_stats = (struct wlan_tx_link_stats *)buffer;
  422. PRINT("\n\n");
  423. PRINT("========= PEER TX LINK QUALITY METRICS =========\n");
  424. PRINT("PEER %02hhx:%02hhx:%02hhx:%02hhx%02hhx:%02hhx",
  425. peer_mac[0],
  426. peer_mac[1],
  427. peer_mac[2],
  428. peer_mac[3],
  429. peer_mac[4],
  430. peer_mac[5]);
  431. PRINT("num_ppdus: %u", tx_stats->num_ppdus);
  432. PRINT("bytes: %"PRIu64, tx_stats->bytes);
  433. PRINT("phy_rate_actual_su: %u kbps", tx_stats->phy_rate_actual_su);
  434. PRINT("phy_rate_actual_mu: %u kbps", tx_stats->phy_rate_actual_mu);
  435. PRINT("ofdma_usage: %u", tx_stats->ofdma_usage);
  436. PRINT("mu_mimo_usage: %u", tx_stats->mu_mimo_usage);
  437. PRINT("bw_usage_avg: %u MHz", tx_stats->bw.usage_avg);
  438. PRINT("bw_usage_packets: 20MHz: %u 40MHz: %u 80MHz: %u 160MHz: %u",
  439. tx_stats->bw.usage_counter[0], tx_stats->bw.usage_counter[1],
  440. tx_stats->bw.usage_counter[2], tx_stats->bw.usage_counter[3]);
  441. PRINT("bw_usage_max:: %u%%", tx_stats->bw.usage_max);
  442. PRINT("ack_rssi: %lu", tx_stats->ack_rssi);
  443. PRINT("pkt_error_rate: %u%%", tx_stats->pkt_error_rate);
  444. }
  445. static void dp_peer_rx_link_stats_print(uint8_t *peer_mac,
  446. uint64_t peer_cookie,
  447. void *buffer,
  448. uint32_t buffer_len)
  449. {
  450. struct wlan_rx_link_stats *rx_stats;
  451. uint8_t is_lithium;
  452. is_lithium = (peer_cookie & WLANSTATS_COOKIE_PLATFORM_OFFSET)
  453. >> WLANSTATS_PEER_COOKIE_LSB;
  454. if (!is_lithium) {
  455. PRINT("Not supported in non-lithium platforms\n");
  456. return;
  457. }
  458. if (buffer_len < sizeof(struct wlan_rx_link_stats)) {
  459. PRINT("invalid buffer len, return");
  460. return;
  461. }
  462. rx_stats = (struct wlan_rx_link_stats *)buffer;
  463. PRINT("\n\n");
  464. PRINT("========= PEER RX LINK QUALITY METRICS =========\n");
  465. PRINT("PEER %02hhx:%02hhx:%02hhx:%02hhx%02hhx:%02hhx",
  466. peer_mac[0],
  467. peer_mac[1],
  468. peer_mac[2],
  469. peer_mac[3],
  470. peer_mac[4],
  471. peer_mac[5]);
  472. PRINT("num_ppdus: %u", rx_stats->num_ppdus);
  473. PRINT("bytes: %"PRIu64, rx_stats->bytes);
  474. PRINT("phy_rate_actual_su: %u kbps", rx_stats->phy_rate_actual_su);
  475. PRINT("phy_rate_actual_mu: %u kbps", rx_stats->phy_rate_actual_mu);
  476. PRINT("ofdma_usage: %u", rx_stats->ofdma_usage);
  477. PRINT("mu_mimo_usage: %u", rx_stats->mu_mimo_usage);
  478. PRINT("bw_usage_avg: %u MHz", rx_stats->bw.usage_avg);
  479. PRINT("bw_usage_packets: 20MHz: %u 40MHz: %u 80MHz: %u 160MHz: %u",
  480. rx_stats->bw.usage_counter[0], rx_stats->bw.usage_counter[1],
  481. rx_stats->bw.usage_counter[2], rx_stats->bw.usage_counter[3]);
  482. PRINT("bw_usage_max: %u%%", rx_stats->bw.usage_max);
  483. PRINT("su_rssi: %lu", rx_stats->su_rssi);
  484. PRINT("pkt_error_rate: %u%%", rx_stats->pkt_error_rate);
  485. }
  486. static void dp_peer_stats_handler(uint32_t cache_type,
  487. uint8_t *peer_mac,
  488. uint64_t peer_cookie,
  489. void *buffer,
  490. uint32_t buffer_len)
  491. {
  492. switch (cache_type) {
  493. case DP_PEER_RX_RATE_STATS:
  494. if (getenv("SKIP_RX_RATE_STATS"))
  495. break;
  496. dp_peer_rx_rate_stats_print(peer_mac, peer_cookie,
  497. buffer, buffer_len);
  498. break;
  499. case DP_PEER_TX_RATE_STATS:
  500. if (getenv("SKIP_TX_RATE_STATS"))
  501. break;
  502. dp_peer_tx_rate_stats_print(peer_mac, peer_cookie,
  503. buffer, buffer_len);
  504. break;
  505. case DP_PEER_TX_LINK_STATS:
  506. dp_peer_tx_link_stats_print(peer_mac, peer_cookie,
  507. buffer, buffer_len);
  508. break;
  509. case DP_PEER_RX_LINK_STATS:
  510. dp_peer_rx_link_stats_print(peer_mac, peer_cookie,
  511. buffer, buffer_len);
  512. break;
  513. case DP_PEER_AVG_RATE_STATS:
  514. if (getenv("SKIP_AVG_RATE_STATS"))
  515. break;
  516. dp_peer_avg_rate_stats_print(peer_mac, peer_cookie,
  517. buffer, buffer_len);
  518. break;
  519. }
  520. }
  521. static void
  522. dp_peer_stats_event_callback(char *ifname,
  523. uint32_t cmdid,
  524. uint8_t *data,
  525. size_t len)
  526. {
  527. struct nlattr *tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_MAX + 1];
  528. struct nlattr *tb;
  529. void *buffer = NULL;
  530. uint32_t buffer_len = 0;
  531. uint8_t *peer_mac;
  532. uint32_t cache_type;
  533. uint64_t peer_cookie;
  534. if (cmdid != QCA_NL80211_VENDOR_SUBCMD_PEER_STATS_CACHE_FLUSH) {
  535. /* ignore anyother events*/
  536. return;
  537. }
  538. if (strncmp(interface, ifname, sizeof(interface)) != 0) {
  539. /* ignore events for other interfaces*/
  540. return;
  541. }
  542. if (nla_parse(tb_array, QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_MAX,
  543. (struct nlattr *)data, len, NULL)) {
  544. PRINT("Invalid event\n");
  545. return;
  546. }
  547. tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_TYPE];
  548. if (!tb) {
  549. PRINT("Cache type in NULL, return");
  550. return;
  551. }
  552. cache_type = nla_get_u32(tb);
  553. tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_MAC];
  554. if (!tb) {
  555. PRINT("Peer mac addr is null, return");
  556. return;
  557. }
  558. peer_mac = (uint8_t *)nla_data(tb);
  559. tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_DATA];
  560. if (tb) {
  561. buffer = (void *)nla_data(tb);
  562. buffer_len = nla_len(tb);
  563. }
  564. tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_COOKIE];
  565. if (!tb) {
  566. PRINT("peer cookie attribute is null, return");
  567. return;
  568. }
  569. peer_cookie = nla_get_u64(tb);
  570. if (!buffer) {
  571. PRINT(" stats buffer is null, return");
  572. return;
  573. }
  574. dp_peer_stats_handler(cache_type, peer_mac, peer_cookie,
  575. buffer, buffer_len);
  576. }
  577. int main(int argc, char *argv[])
  578. {
  579. int err = 0;
  580. wifi_cfg80211_context cfg80211_ctxt;
  581. char *ifname;
  582. int num_msecs = 0;
  583. int status = 0;
  584. if (argc < 2) {
  585. fprintf(stderr, "Invalid commands args\n");
  586. return -EIO;
  587. }
  588. /* Reset the cfg80211 context to 0 if the application does not pass
  589. * custom private event and command sockets. In this case, the default
  590. * port is used for netlink communication.
  591. */
  592. memset(&cfg80211_ctxt, 0, sizeof(wifi_cfg80211_context));
  593. ifname = argv[1];
  594. memcpy(interface, ifname, sizeof(interface));
  595. cfg80211_ctxt.event_callback = dp_peer_stats_event_callback;
  596. err = wifi_init_nl80211(&cfg80211_ctxt);
  597. if (err) {
  598. fprintf(stderr, "unable to create NL socket\n");
  599. return -EIO;
  600. }
  601. /* Starting event thread to listen for responses*/
  602. if (wifi_nl80211_start_event_thread(&cfg80211_ctxt)) {
  603. fprintf(stderr, "Unable to setup nl80211 event thread\n");
  604. status = -EIO;
  605. goto cleanup;
  606. }
  607. while (true) {
  608. /*sleep for 1 ms*/
  609. usleep(1000);
  610. num_msecs++;
  611. }
  612. wifi_destroy_nl80211(&cfg80211_ctxt);
  613. return 0;
  614. cleanup:
  615. wifi_destroy_nl80211(&cfg80211_ctxt);
  616. return status;
  617. }