peerstats.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. /*
  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. * 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 DP_PEER_STATS_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. rx_stats = (struct wlan_rx_rate_stats *)buffer;
  45. DP_PEER_STATS_PRINT("\n......................................");
  46. DP_PEER_STATS_PRINT("......................................");
  47. DP_PEER_STATS_PRINT("PEER %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
  48. peer_mac[0],
  49. peer_mac[1],
  50. peer_mac[2],
  51. peer_mac[3],
  52. peer_mac[4],
  53. peer_mac[5]);
  54. DP_PEER_STATS_PRINT("\tpeer cookie: %016llx\n",
  55. peer_cookie);
  56. DP_PEER_STATS_PRINT("\n..............................................");
  57. DP_PEER_STATS_PRINT("................................");
  58. DP_PEER_STATS_PRINT("................................................");
  59. DP_PEER_STATS_PRINT(".................................\n");
  60. DP_PEER_STATS_PRINT("\tRx statistics:");
  61. DP_PEER_STATS_PRINT(" %10s | %10s | %10s | %10s | %10s | %10s",
  62. "rate",
  63. "rix",
  64. "bytes",
  65. "msdus",
  66. "mpdus",
  67. "ppdus");
  68. DP_PEER_STATS_PRINT("\t\t%10s | %10s | %10s | %10s | %10s | %10s |",
  69. "retries",
  70. "rssi",
  71. "rssi 1 p20",
  72. "rssi 1 e20",
  73. "rssi 1 e40",
  74. "rssi 1 e80");
  75. DP_PEER_STATS_PRINT(" | %10s | | %10s | %10s | %10s | %10s | %10s",
  76. "rssi 2 p20",
  77. "rssi 2 e20",
  78. "rssi 2 e40",
  79. "rssi 2 e80",
  80. "rssi 3 p20",
  81. "rssi 3 e20");
  82. DP_PEER_STATS_PRINT(" | %10s | %10s | %10s | %10s | %10s\n\n\n",
  83. "rssi 3 e40",
  84. "rssi 3 e80",
  85. "rssi 4 p20",
  86. "rssi 4 e20",
  87. "rssi 4 e40",
  88. "rssi 4 e80");
  89. for (i = 0; i < WLANSTATS_MAX_NODE; i++) {
  90. DP_PEER_STATS_PRINT("\t\t%10u | %10u | %10u | %10u | %10u |",
  91. rx_stats->rate,
  92. rx_stats->rix,
  93. rx_stats->num_bytes,
  94. rx_stats->num_msdus,
  95. rx_stats->num_mpdus,
  96. );
  97. DP_PEER_STATS_PRINT(" %10u | %10u | %10u | %10u | %10u |",
  98. rx_stats->num_ppdus,
  99. rx_stats->num_retries,
  100. rx_stats->num_sgi,
  101. rx_stats->avg_rssi,
  102. rx_stats->avg_rssi_ant[0][0]);
  103. DP_PEER_STATS_PRINT(" %10u | %10u | %10u | %10u | %10u |",
  104. rx_stats->avg_rssi_ant[0][1],
  105. rx_stats->avg_rssi_ant[0][2],
  106. rx_stats->avg_rssi_ant[0][3],
  107. rx_stats->avg_rssi_ant[1][0],
  108. rx_stats->avg_rssi_ant[1][1]);
  109. DP_PEER_STATS_PRINT(" %10u | %10u | %10u | %10u | %10u |",
  110. rx_stats->avg_rssi_ant[1][2],
  111. rx_stats->avg_rssi_ant[1][3],
  112. rx_stats->avg_rssi_ant[2][0],
  113. rx_stats->avg_rssi_ant[2][1],
  114. rx_stats->avg_rssi_ant[2][2]);
  115. DP_PEER_STATS_PRINT(" %10u | %10u | %10u\n\n\n",
  116. rx_stats->avg_rssi_ant[2][3],
  117. rx_stats->avg_rssi_ant[3][0],
  118. rx_stats->avg_rssi_ant[3][1],
  119. rx_stats->avg_rssi_ant[3][2],
  120. rx_stats->avg_rssi_ant[3][3]);
  121. rx_stats = rx_stats + 1;
  122. }
  123. }
  124. static void
  125. dp_peer_tx_sojourn_stats_print(uint8_t *peer_mac,
  126. uint64_t peer_cookie,
  127. struct wlan_tx_sojourn_stats *sojourn_stats)
  128. {
  129. uint8_t tid;
  130. DP_PEER_STATS_PRINT("\n..........................................");
  131. DP_PEER_STATS_PRINT("....................................");
  132. DP_PEER_STATS_PRINT("....................................");
  133. DP_PEER_STATS_PRINT(".........................................\n");
  134. DP_PEER_STATS_PRINT("PEER%02hhx:%02hhx:%02hhx:%02hhx%02hhx:%02hhx\n",
  135. peer_mac[0],
  136. peer_mac[1],
  137. peer_mac[2],
  138. peer_mac[3],
  139. peer_mac[4],
  140. peer_mac[5]);
  141. DP_PEER_STATS_PRINT("\tPEER Cookie: %016llx\n",
  142. peer_cookie);
  143. DP_PEER_STATS_PRINT("\n...........................................");
  144. DP_PEER_STATS_PRINT("...................................");
  145. DP_PEER_STATS_PRINT("..................................");
  146. DP_PEER_STATS_PRINT("............................................");
  147. DP_PEER_STATS_PRINT("\n\tSojourn statistics:\n");
  148. DP_PEER_STATS_PRINT("\t\t%10s %10s %20s %20s\n",
  149. "tid",
  150. "ave",
  151. "sum",
  152. "num");
  153. for (tid = 0; tid < WLAN_DATA_TID_MAX; tid++) {
  154. /* change sum_sojourn_msdu data type to u64 */
  155. DP_PEER_STATS_PRINT("\t\t%10d %10u %20u %20u\n",
  156. tid,
  157. sojourn_stats->avg_sojourn_msdu[tid],
  158. sojourn_stats->sum_sojourn_msdu[tid],
  159. sojourn_stats->num_msdus[tid]);
  160. }
  161. DP_PEER_STATS_PRINT("\n...........................................");
  162. DP_PEER_STATS_PRINT("...................................");
  163. DP_PEER_STATS_PRINT("...................................");
  164. DP_PEER_STATS_PRINT("...........................................\n");
  165. }
  166. static void dp_peer_tx_rate_stats_print(uint8_t *peer_mac,
  167. uint64_t peer_cookie,
  168. void *buffer,
  169. uint32_t buffer_len)
  170. {
  171. int i = 0;
  172. struct wlan_tx_rate_stats *tx_stats;
  173. struct wlan_tx_sojourn_stats *sojourn_stats;
  174. if (buffer_len < (WLANSTATS_MAX_NODE *
  175. sizeof(struct wlan_tx_rate_stats))
  176. + sizeof(struct wlan_tx_sojourn_stats)) {
  177. DP_PEER_STATS_PRINT("invalid buffer len, return");
  178. return;
  179. }
  180. tx_stats = (struct wlan_tx_rate_stats *)buffer;
  181. DP_PEER_STATS_PRINT("\n...........................................");
  182. DP_PEER_STATS_PRINT("...................................");
  183. DP_PEER_STATS_PRINT("...................................");
  184. DP_PEER_STATS_PRINT("...........................................\n");
  185. DP_PEER_STATS_PRINT("PEER%02hhx:%02hhx:%02hhx:%02hhx%02hhx:%02hhx\n\n",
  186. peer_mac[0],
  187. peer_mac[1],
  188. peer_mac[2],
  189. peer_mac[3],
  190. peer_mac[4],
  191. peer_mac[5]);
  192. DP_PEER_STATS_PRINT("\tPEER Cookie: %016llx",
  193. peer_cookie);
  194. DP_PEER_STATS_PRINT("\n...........................................");
  195. DP_PEER_STATS_PRINT("...................................");
  196. DP_PEER_STATS_PRINT("...................................");
  197. DP_PEER_STATS_PRINT("...........................................\n");
  198. DP_PEER_STATS_PRINT("\tTx statistics:\n");
  199. DP_PEER_STATS_PRINT("\t\t%10s | %10s | %10s | %10s | %10s",
  200. "rate",
  201. "rix",
  202. "attempts",
  203. "success",
  204. "ppdus");
  205. for (i = 0; i < WLANSTATS_MAX_NODE; i++) {
  206. DP_PEER_STATS_PRINT("\t\t%10u | %10u | %10u | %10u | %10u\n",
  207. tx_stats->rate,
  208. tx_stats->rix,
  209. tx_stats->mpdu_attempts,
  210. tx_stats->mpdu_success,
  211. tx_stats->num_ppdus);
  212. tx_stats = tx_stats + 1;
  213. }
  214. sojourn_stats = buffer + (WLANSTATS_MAX_NODE *
  215. sizeof(struct wlan_tx_rate_stats));
  216. dp_peer_tx_sojourn_stats_print(peer_mac, peer_cookie, sojourn_stats);
  217. return 0;
  218. }
  219. static int dp_peer_stats_handler(uint32_t cache_type,
  220. uint8_t *peer_mac,
  221. uint64_t peer_cookie,
  222. void *buffer,
  223. uint32_t buffer_len)
  224. {
  225. switch (cache_type) {
  226. case DP_PEER_RX_RATE_STATS:
  227. dp_peer_rx_rate_stats_print(peer_mac, peer_cookie,
  228. buffer, buffer_len);
  229. break;
  230. case DP_PEER_TX_RATE_STATS:
  231. dp_peer_tx_rate_stats_print(peer_mac, peer_cookie,
  232. buffer, buffer_len);
  233. break;
  234. }
  235. }
  236. static void
  237. dp_peer_stats_event_callback(char *ifname,
  238. uint32_t cmdid,
  239. uint8_t *data,
  240. size_t len)
  241. {
  242. uint8_t cmd;
  243. struct dbg_event_q_entry *q_entry;
  244. int response_cookie = 0;
  245. struct nlattr *tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_MAX + 1];
  246. struct nlattr *tb;
  247. void *buffer = NULL;
  248. uint32_t buffer_len = 0;
  249. uint8_t *peer_mac;
  250. uint32_t cache_type;
  251. uint64_t peer_cookie;
  252. if (cmdid != QCA_NL80211_VENDOR_SUBCMD_PEER_STATS_CACHE_FLUSH) {
  253. /* ignore anyother events*/
  254. return;
  255. }
  256. if (strncmp(interface, ifname, sizeof(interface)) != 0) {
  257. /* ignore events for other interfaces*/
  258. return;
  259. }
  260. if (nla_parse(tb_array, QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_MAX,
  261. (struct nlattr *)data, len, NULL)) {
  262. printf("INVALID EVENT\n");
  263. return;
  264. }
  265. tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_TYPE];
  266. if (!tb) {
  267. printf("#############%s:%d\n", __func__, __LINE__);
  268. return;
  269. }
  270. cache_type = nla_get_u32(tb);
  271. tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_MAC];
  272. if (!tb) {
  273. printf("#############%s:%d\n", __func__, __LINE__);
  274. return;
  275. }
  276. peer_mac = (uint8_t *)nla_data(tb);
  277. tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_DATA];
  278. if (tb) {
  279. buffer = (void *)nla_data(tb);
  280. buffer_len = nla_len(tb);
  281. }
  282. tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_COOKIE];
  283. if (!tb) {
  284. printf("#############%s:%d\n", __func__, __LINE__);
  285. return;
  286. }
  287. peer_cookie = nla_get_u64(tb);
  288. if (!buffer) {
  289. printf("#############%s:%d\n", __func__, __LINE__);
  290. return;
  291. }
  292. dp_peer_stats_handler(cache_type, peer_mac, peer_cookie,
  293. buffer, buffer_len);
  294. }
  295. int main(int argc, char *argv[])
  296. {
  297. struct cfg80211_data buffer;
  298. int err = 0;
  299. wifi_cfg80211_context cfg80211_ctxt;
  300. char *ifname;
  301. int num_msecs = 0;
  302. void *req_buff = NULL;
  303. int req_buff_sz = 0;
  304. int status = 0;
  305. if (argc < 2) {
  306. fprintf(stderr, "Invalid commands args\n");
  307. return -EIO;
  308. }
  309. /* Reset the cfg80211 context to 0 if the application does not pass
  310. * custom private event and command sockets. In this case, the default
  311. * port is used for netlink communication.
  312. */
  313. memset(&cfg80211_ctxt, 0, sizeof(wifi_cfg80211_context));
  314. ifname = argv[1];
  315. memcpy(interface, ifname, sizeof(interface));
  316. cfg80211_ctxt.event_callback = dp_peer_stats_event_callback;
  317. err = wifi_init_nl80211(&cfg80211_ctxt);
  318. if (err) {
  319. fprintf(stderr, "unable to create NL socket\n");
  320. return -EIO;
  321. }
  322. /* Starting event thread to listen for responses*/
  323. if (wifi_nl80211_start_event_thread(&cfg80211_ctxt)) {
  324. fprintf(stderr, "Unable to setup nl80211 event thread\n");
  325. status = -EIO;
  326. goto cleanup;
  327. }
  328. while (true) {
  329. /*sleep for 1 ms*/
  330. usleep(1000);
  331. num_msecs++;
  332. }
  333. wifi_destroy_nl80211(&cfg80211_ctxt);
  334. return 0;
  335. cleanup:
  336. wifi_destroy_nl80211(&cfg80211_ctxt);
  337. return status;
  338. }