peerstats.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  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_tx_link_stats_print(uint8_t *peer_mac,
  328. uint64_t peer_cookie,
  329. void *buffer,
  330. uint32_t buffer_len)
  331. {
  332. struct wlan_tx_link_stats *tx_stats;
  333. uint8_t is_lithium;
  334. is_lithium = (peer_cookie & WLANSTATS_COOKIE_PLATFORM_OFFSET)
  335. >> WLANSTATS_PEER_COOKIE_LSB;
  336. if (!is_lithium) {
  337. PRINT("Not supported in non-lithium platforms\n");
  338. return;
  339. }
  340. if (buffer_len < sizeof(struct wlan_tx_link_stats)) {
  341. PRINT("invalid buffer len, return");
  342. return;
  343. }
  344. tx_stats = (struct wlan_tx_link_stats *)buffer;
  345. PRINT("\n\n");
  346. PRINT("========= PEER TX LINK QUALITY METRICS =========\n");
  347. PRINT("PEER %02hhx:%02hhx:%02hhx:%02hhx%02hhx:%02hhx",
  348. peer_mac[0],
  349. peer_mac[1],
  350. peer_mac[2],
  351. peer_mac[3],
  352. peer_mac[4],
  353. peer_mac[5]);
  354. PRINT("num_ppdus: %u", tx_stats->num_ppdus);
  355. PRINT("bytes: %"PRIu64, tx_stats->bytes);
  356. PRINT("phy_rate_actual_su: %u kbps", tx_stats->phy_rate_actual_su);
  357. PRINT("phy_rate_actual_mu: %u kbps", tx_stats->phy_rate_actual_mu);
  358. PRINT("ofdma_usage: %u", tx_stats->ofdma_usage);
  359. PRINT("mu_mimo_usage: %u", tx_stats->mu_mimo_usage);
  360. PRINT("bw_usage_avg: %u MHz", tx_stats->bw.usage_avg);
  361. PRINT("bw_usage_packets: 20MHz: %u 40MHz: %u 80MHz: %u 160MHz: %u",
  362. tx_stats->bw.usage_counter[0], tx_stats->bw.usage_counter[1],
  363. tx_stats->bw.usage_counter[2], tx_stats->bw.usage_counter[3]);
  364. PRINT("bw_usage_max:: %u%%", tx_stats->bw.usage_max);
  365. PRINT("ack_rssi: %lu", tx_stats->ack_rssi);
  366. PRINT("pkt_error_rate: %u%%", tx_stats->pkt_error_rate);
  367. }
  368. static void dp_peer_rx_link_stats_print(uint8_t *peer_mac,
  369. uint64_t peer_cookie,
  370. void *buffer,
  371. uint32_t buffer_len)
  372. {
  373. struct wlan_rx_link_stats *rx_stats;
  374. uint8_t is_lithium;
  375. is_lithium = (peer_cookie & WLANSTATS_COOKIE_PLATFORM_OFFSET)
  376. >> WLANSTATS_PEER_COOKIE_LSB;
  377. if (!is_lithium) {
  378. PRINT("Not supported in non-lithium platforms\n");
  379. return;
  380. }
  381. if (buffer_len < sizeof(struct wlan_rx_link_stats)) {
  382. PRINT("invalid buffer len, return");
  383. return;
  384. }
  385. rx_stats = (struct wlan_rx_link_stats *)buffer;
  386. PRINT("\n\n");
  387. PRINT("========= PEER RX LINK QUALITY METRICS =========\n");
  388. PRINT("PEER %02hhx:%02hhx:%02hhx:%02hhx%02hhx:%02hhx",
  389. peer_mac[0],
  390. peer_mac[1],
  391. peer_mac[2],
  392. peer_mac[3],
  393. peer_mac[4],
  394. peer_mac[5]);
  395. PRINT("num_ppdus: %u", rx_stats->num_ppdus);
  396. PRINT("bytes: %"PRIu64, rx_stats->bytes);
  397. PRINT("phy_rate_actual_su: %u kbps", rx_stats->phy_rate_actual_su);
  398. PRINT("phy_rate_actual_mu: %u kbps", rx_stats->phy_rate_actual_mu);
  399. PRINT("ofdma_usage: %u", rx_stats->ofdma_usage);
  400. PRINT("mu_mimo_usage: %u", rx_stats->mu_mimo_usage);
  401. PRINT("bw_usage_avg: %u MHz", rx_stats->bw.usage_avg);
  402. PRINT("bw_usage_packets: 20MHz: %u 40MHz: %u 80MHz: %u 160MHz: %u",
  403. rx_stats->bw.usage_counter[0], rx_stats->bw.usage_counter[1],
  404. rx_stats->bw.usage_counter[2], rx_stats->bw.usage_counter[3]);
  405. PRINT("bw_usage_max: %u%%", rx_stats->bw.usage_max);
  406. PRINT("su_rssi: %lu", rx_stats->su_rssi);
  407. PRINT("pkt_error_rate: %u%%", rx_stats->pkt_error_rate);
  408. }
  409. static void dp_peer_stats_handler(uint32_t cache_type,
  410. uint8_t *peer_mac,
  411. uint64_t peer_cookie,
  412. void *buffer,
  413. uint32_t buffer_len)
  414. {
  415. switch (cache_type) {
  416. case DP_PEER_RX_RATE_STATS:
  417. dp_peer_rx_rate_stats_print(peer_mac, peer_cookie,
  418. buffer, buffer_len);
  419. break;
  420. case DP_PEER_TX_RATE_STATS:
  421. dp_peer_tx_rate_stats_print(peer_mac, peer_cookie,
  422. buffer, buffer_len);
  423. break;
  424. case DP_PEER_TX_LINK_STATS:
  425. dp_peer_tx_link_stats_print(peer_mac, peer_cookie,
  426. buffer, buffer_len);
  427. break;
  428. case DP_PEER_RX_LINK_STATS:
  429. dp_peer_rx_link_stats_print(peer_mac, peer_cookie,
  430. buffer, buffer_len);
  431. break;
  432. }
  433. }
  434. static void
  435. dp_peer_stats_event_callback(char *ifname,
  436. uint32_t cmdid,
  437. uint8_t *data,
  438. size_t len)
  439. {
  440. struct nlattr *tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_MAX + 1];
  441. struct nlattr *tb;
  442. void *buffer = NULL;
  443. uint32_t buffer_len = 0;
  444. uint8_t *peer_mac;
  445. uint32_t cache_type;
  446. uint64_t peer_cookie;
  447. if (cmdid != QCA_NL80211_VENDOR_SUBCMD_PEER_STATS_CACHE_FLUSH) {
  448. /* ignore anyother events*/
  449. return;
  450. }
  451. if (strncmp(interface, ifname, sizeof(interface)) != 0) {
  452. /* ignore events for other interfaces*/
  453. return;
  454. }
  455. if (nla_parse(tb_array, QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_MAX,
  456. (struct nlattr *)data, len, NULL)) {
  457. PRINT("Invalid event\n");
  458. return;
  459. }
  460. tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_TYPE];
  461. if (!tb) {
  462. PRINT("Cache type in NULL, return");
  463. return;
  464. }
  465. cache_type = nla_get_u32(tb);
  466. tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_MAC];
  467. if (!tb) {
  468. PRINT("Peer mac addr is null, return");
  469. return;
  470. }
  471. peer_mac = (uint8_t *)nla_data(tb);
  472. tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_DATA];
  473. if (tb) {
  474. buffer = (void *)nla_data(tb);
  475. buffer_len = nla_len(tb);
  476. }
  477. tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_COOKIE];
  478. if (!tb) {
  479. PRINT("peer cookie attribute is null, return");
  480. return;
  481. }
  482. peer_cookie = nla_get_u64(tb);
  483. if (!buffer) {
  484. PRINT(" stats buffer is null, return");
  485. return;
  486. }
  487. dp_peer_stats_handler(cache_type, peer_mac, peer_cookie,
  488. buffer, buffer_len);
  489. }
  490. int main(int argc, char *argv[])
  491. {
  492. int err = 0;
  493. wifi_cfg80211_context cfg80211_ctxt;
  494. char *ifname;
  495. int num_msecs = 0;
  496. int status = 0;
  497. if (argc < 2) {
  498. fprintf(stderr, "Invalid commands args\n");
  499. return -EIO;
  500. }
  501. /* Reset the cfg80211 context to 0 if the application does not pass
  502. * custom private event and command sockets. In this case, the default
  503. * port is used for netlink communication.
  504. */
  505. memset(&cfg80211_ctxt, 0, sizeof(wifi_cfg80211_context));
  506. ifname = argv[1];
  507. memcpy(interface, ifname, sizeof(interface));
  508. cfg80211_ctxt.event_callback = dp_peer_stats_event_callback;
  509. err = wifi_init_nl80211(&cfg80211_ctxt);
  510. if (err) {
  511. fprintf(stderr, "unable to create NL socket\n");
  512. return -EIO;
  513. }
  514. /* Starting event thread to listen for responses*/
  515. if (wifi_nl80211_start_event_thread(&cfg80211_ctxt)) {
  516. fprintf(stderr, "Unable to setup nl80211 event thread\n");
  517. status = -EIO;
  518. goto cleanup;
  519. }
  520. while (true) {
  521. /*sleep for 1 ms*/
  522. usleep(1000);
  523. num_msecs++;
  524. }
  525. wifi_destroy_nl80211(&cfg80211_ctxt);
  526. return 0;
  527. cleanup:
  528. wifi_destroy_nl80211(&cfg80211_ctxt);
  529. return status;
  530. }