123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468 |
- /*
- * Copyright (c) 2019 The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for
- * any purpose with or without fee is hereby granted, provided that the
- * above copyright notice and this permission notice appear in all
- * copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
- * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
- /**
- * file: peer rate statitistics application
- * This file provides framework to display peer rate statistics
- */
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <qcatools_lib.h>
- #include <dp_rate_stats_pub.h>
- #ifndef min
- #define min(x, y) ((x) < (y) ? (x) : (y))
- #else
- #error confilicting defs of min
- #endif
- #define PRINT(fmt, ...) \
- do { \
- printf(fmt, ##__VA_ARGS__); \
- printf("\n"); \
- } while (0)
- char interface[IFNAMSIZ];
- static void dp_peer_rx_rate_stats_print(uint8_t *peer_mac,
- uint64_t peer_cookie,
- void *buffer,
- uint32_t buffer_len)
- {
- int i = 0;
- struct wlan_rx_rate_stats *rx_stats;
- uint8_t is_lithium;
- uint8_t chain, max_chain, bw, max_bw;
- struct wlan_rx_rate_stats *tmp_rx_stats;;
- rx_stats = tmp_rx_stats = (struct wlan_rx_rate_stats *)buffer;
- PRINT("\n......................................");
- PRINT("......................................");
- PRINT("PEER %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
- peer_mac[0],
- peer_mac[1],
- peer_mac[2],
- peer_mac[3],
- peer_mac[4],
- peer_mac[5]);
- PRINT("\tpeer cookie: %016lx\n", (peer_cookie & 0xFFFFFFFF00000000)
- >> WLANSTATS_PEER_COOKIE_LSB);
- is_lithium = (peer_cookie & WLANSTATS_COOKIE_PLATFORM_OFFSET)
- >> WLANSTATS_PEER_COOKIE_LSB;
- if (is_lithium) {
- max_chain = 8;
- max_bw = 8;
- } else {
- max_chain = 4;
- max_bw = 4;
- }
- PRINT("\n..............................................");
- PRINT("................................");
- PRINT("................................................");
- PRINT(".................................\n");
- PRINT("\tRx statistics:");
- PRINT(" %10s | %10s | %10s | %10s | %10s | %10s|",
- "rate",
- "rix",
- "bytes",
- "msdus",
- "mpdus",
- "ppdus");
- PRINT(" %10s | %10s | %10s |",
- "retries",
- "sgi",
- "rssi\n");
- for (i = 0; i < WLANSTATS_CACHE_SIZE; i++) {
- if (rx_stats->rix != INVALID_CACHE_IDX) {
- PRINT(" %10u | %10u | %10u | %10u | %10u | %10u |",
- rx_stats->rate,
- GET_DP_PEER_STATS_RIX(rx_stats->rix),
- rx_stats->num_bytes,
- rx_stats->num_msdus,
- rx_stats->num_mpdus,
- rx_stats->num_ppdus);
- PRINT(" %10u | %10u | %10lu |\n",
- rx_stats->num_retries,
- rx_stats->num_sgi,
- rx_stats->avg_rssi);
- }
- rx_stats = rx_stats + 1;
- }
- if (is_lithium) {
- PRINT("\n %10s | %10s | %10s | %10s | %10s |",
- "rate",
- "rssi 1 p20",
- "rssi 1 e20",
- "rssi 1 e40 low20",
- "rssi 1 e40 high20");
- PRINT("\n | %10s | %10s | %10s | %10s |",
- "rssi 1 ext80 low20",
- "rssi 1 ext80 low_high20",
- "rssi 1 ext80 high_low20",
- "rssi 1 ext80 high20");
- PRINT("\n | %10s | %10s | %10s | %10s |",
- "rssi 2 p20",
- "rssi 2 e20",
- "rssi 2 e40 low20",
- "rssi 2 e40 high20");
- PRINT("\n | %10s | %10s | %10s | %10s |",
- "rssi 2 ext80 low20",
- "rssi 2 ext80 low_high20",
- "rssi 2 ext80 high_low20",
- "rssi 2 ext80 high20");
- PRINT("\n | %10s | %10s | %10s | %10s |",
- "rssi 3 p20",
- "rssi 3 e20",
- "rssi 3 e40 low20",
- "rssi 3 e40 high20");
- PRINT("\n | %10s | %10s | %10s | %10s |",
- "rssi 3 ext80 low20",
- "rssi 3 ext80 low_high20",
- "rssi 3 ext80 high_low20",
- "rssi 3 ext80 high20");
- PRINT("\n | %10s | %10s | %10s | %10s |",
- "rssi 4 p20",
- "rssi 4 e20",
- "rssi 4 e40 low20",
- "rssi 4 e40 high20");
- PRINT("\n | %10s | %10s | %10s | %10s |",
- "rssi 4 ext80 low20",
- "rssi 4 ext80 low_high20",
- "rssi 4 ext80 high_low20",
- "rssi 4 ext80 high20");
- PRINT("\n | %10s | %10s | %10s | %10s |",
- "rssi 5 p20",
- "rssi 5 e20",
- "rssi 5 e40 low20",
- "rssi 5 e40 high20");
- PRINT("\n | %10s | %10s | %10s | %10s |",
- "rssi 5 ext80 low20",
- "rssi 5 ext80 low_high20",
- "rssi 5 ext80 high_low20",
- "rssi 5 ext80 high20");
- PRINT("\n | %10s | %10s | %10s | %10s |",
- "rssi 6 p20",
- "rssi 6 e20",
- "rssi 6 e40 low20",
- "rssi 6 e40 high20");
- PRINT("\n | %10s | %10s | %10s | %10s |",
- "rssi 6 ext80 low20",
- "rssi 6 ext80 low_high20",
- "rssi 6 ext80 high_low20",
- "rssi 6 ext80 high20");
- PRINT("\n | %10s | %10s | %10s | %10s |",
- "rssi 7 p20",
- "rssi 7 e20",
- "rssi 7 e40 low20",
- "rssi 7 e40 high20");
- PRINT("\n | %10s | %10s | %10s | %10s |",
- "rssi 7 ext80 low20",
- "rssi 7 ext80 low_high20",
- "rssi 7 ext80 high_low20",
- "rssi 7 ext80 high20");
- PRINT("\n | %10s | %10s | %10s | %10s |",
- "rssi 8 p20",
- "rssi 8 e20",
- "rssi 8 e40 low20",
- "rssi 8 e40 high20");
- PRINT("\n | %10s | %10s | %10s | %10s |\n\n\n",
- "rssi 8 ext80 low20",
- "rssi 8 ext80 low_high20",
- "rssi 8 ext80 high_low20",
- "rssi 8 ext80 high20");
- } else {
- PRINT("\n %10s | %10s | %10s | %10s | %10s |",
- "rate",
- "rssi 1 p20",
- "rssi 1 e20",
- "rssi 1 e40",
- "rssi 1 e80");
- PRINT(" | %10s | %10s | %10s | %10s |",
- "rssi 2 p20",
- "rssi 2 e20",
- "rssi 2 e40",
- "rssi 2 e80");
- PRINT(" | %10s | %10s | %10s | %10s |",
- "rssi 3 p20",
- "rssi 3 e20",
- "rssi 3 e40",
- "rssi 3 e80");
- PRINT(" | %10s | %10s | %10s | %10s |\n\n\n",
- "rssi 4 p20",
- "rssi 4 e20",
- "rssi 4 e40",
- "rssi 4 e80");
- }
- for (i = 0; i < WLANSTATS_CACHE_SIZE; i++) {
- if (tmp_rx_stats->rix != INVALID_CACHE_IDX) {
- printf(" %10u |", tmp_rx_stats->rate);
- for (chain = 0; chain < max_chain; chain++) {
- for (bw = 0; bw < max_bw; bw++) {
- printf(" %10lu |",
- tmp_rx_stats->avg_rssi_ant[chain][bw]);
- }
- printf(" \n\t ");
- }
- PRINT(" ");
- }
- tmp_rx_stats = tmp_rx_stats + 1;
- }
- }
- static void
- dp_peer_tx_sojourn_stats_print(uint8_t *peer_mac,
- uint64_t peer_cookie,
- struct wlan_tx_sojourn_stats *sojourn_stats)
- {
- uint8_t tid;
- PRINT("\n..........................................");
- PRINT("....................................");
- PRINT("....................................");
- PRINT(".........................................\n");
- PRINT("PEER %02hhx:%02hhx:%02hhx:%02hhx%02hhx:%02hhx\n",
- peer_mac[0],
- peer_mac[1],
- peer_mac[2],
- peer_mac[3],
- peer_mac[4],
- peer_mac[5]);
- PRINT("\tPEER Cookie: %016lx\n", peer_cookie);
- PRINT("\n...........................................");
- PRINT("...................................");
- PRINT("..................................");
- PRINT("............................................");
- PRINT("\n\tSojourn statistics:\n");
- PRINT("\t\t%10s %10s %20s %20s\n", "tid", "ave", "sum", "num");
- for (tid = 0; tid < WLAN_DATA_TID_MAX; tid++) {
- /* change sum_sojourn_msdu data type to u64 */
- PRINT("\t\t%10d %10lu %20u %20u\n",
- tid,
- sojourn_stats->avg_sojourn_msdu[tid],
- sojourn_stats->sum_sojourn_msdu[tid],
- sojourn_stats->num_msdus[tid]);
- }
- PRINT("sizeof(avg): %lu", sizeof(sojourn_stats->avg_sojourn_msdu[tid]));
- PRINT("\n...........................................");
- PRINT("...................................");
- PRINT("...................................");
- PRINT("...........................................\n");
- }
- static void dp_peer_tx_rate_stats_print(uint8_t *peer_mac,
- uint64_t peer_cookie,
- void *buffer,
- uint32_t buffer_len)
- {
- int i = 0;
- struct wlan_tx_rate_stats *tx_stats;
- struct wlan_tx_sojourn_stats *sojourn_stats;
- if (buffer_len < (WLANSTATS_CACHE_SIZE *
- sizeof(struct wlan_tx_rate_stats))
- + sizeof(struct wlan_tx_sojourn_stats)) {
- PRINT("invalid buffer len, return");
- return;
- }
- tx_stats = (struct wlan_tx_rate_stats *)buffer;
- PRINT("\n...........................................");
- PRINT("...................................");
- PRINT("...................................");
- PRINT("...........................................\n");
- PRINT("PEER %02hhx:%02hhx:%02hhx:%02hhx%02hhx:%02hhx\n\n",
- peer_mac[0],
- peer_mac[1],
- peer_mac[2],
- peer_mac[3],
- peer_mac[4],
- peer_mac[5]);
- PRINT("\tPEER Cookie: %016lx", peer_cookie);
- PRINT("\n...........................................");
- PRINT("...................................");
- PRINT("...................................");
- PRINT("...........................................\n");
- PRINT("\tTx statistics:\n");
- PRINT("\t\t%10s | %10s | %10s | %10s | %10s",
- "rate",
- "rix",
- "attempts",
- "success",
- "ppdus");
- PRINT(" %10s | %10s | %10s |",
- "msdus",
- "bytes",
- "retries\n");
- for (i = 0; i < WLANSTATS_CACHE_SIZE; i++) {
- if (tx_stats->rix != INVALID_CACHE_IDX) {
- PRINT("\t\t%10u | %10u | %10u | %10u | %10u\n",
- tx_stats->rate,
- GET_DP_PEER_STATS_RIX(tx_stats->rix),
- tx_stats->mpdu_attempts,
- tx_stats->mpdu_success,
- tx_stats->num_ppdus);
- PRINT(" %10u | %10u | %10lu |\n",
- tx_stats->num_msdus,
- tx_stats->num_bytes,
- tx_stats->num_retries);
- }
- tx_stats = tx_stats + 1;
- }
- sojourn_stats = (struct wlan_tx_sojourn_stats *)((uint8_t *)buffer
- + (WLANSTATS_CACHE_SIZE *
- sizeof(struct wlan_tx_rate_stats)));
- dp_peer_tx_sojourn_stats_print(peer_mac, peer_cookie, sojourn_stats);
- return;
- }
- static void dp_peer_stats_handler(uint32_t cache_type,
- uint8_t *peer_mac,
- uint64_t peer_cookie,
- void *buffer,
- uint32_t buffer_len)
- {
- switch (cache_type) {
- case DP_PEER_RX_RATE_STATS:
- dp_peer_rx_rate_stats_print(peer_mac, peer_cookie,
- buffer, buffer_len);
- break;
- case DP_PEER_TX_RATE_STATS:
- dp_peer_tx_rate_stats_print(peer_mac, peer_cookie,
- buffer, buffer_len);
- break;
- }
- }
- static void
- dp_peer_stats_event_callback(char *ifname,
- uint32_t cmdid,
- uint8_t *data,
- size_t len)
- {
- struct nlattr *tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_MAX + 1];
- struct nlattr *tb;
- void *buffer = NULL;
- uint32_t buffer_len = 0;
- uint8_t *peer_mac;
- uint32_t cache_type;
- uint64_t peer_cookie;
- if (cmdid != QCA_NL80211_VENDOR_SUBCMD_PEER_STATS_CACHE_FLUSH) {
- /* ignore anyother events*/
- return;
- }
- if (strncmp(interface, ifname, sizeof(interface)) != 0) {
- /* ignore events for other interfaces*/
- return;
- }
- if (nla_parse(tb_array, QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_MAX,
- (struct nlattr *)data, len, NULL)) {
- PRINT("Invalid event\n");
- return;
- }
- tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_TYPE];
- if (!tb) {
- PRINT("Cache type in NULL, return");
- return;
- }
- cache_type = nla_get_u32(tb);
- tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_MAC];
- if (!tb) {
- PRINT("Peer mac addr is null, return");
- return;
- }
- peer_mac = (uint8_t *)nla_data(tb);
- tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_DATA];
- if (tb) {
- buffer = (void *)nla_data(tb);
- buffer_len = nla_len(tb);
- }
- tb = tb_array[QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_COOKIE];
- if (!tb) {
- PRINT("peer cookie attribute is null, return");
- return;
- }
- peer_cookie = nla_get_u64(tb);
- if (!buffer) {
- PRINT(" stats buffer is null, return");
- return;
- }
- dp_peer_stats_handler(cache_type, peer_mac, peer_cookie,
- buffer, buffer_len);
- }
- int main(int argc, char *argv[])
- {
- int err = 0;
- wifi_cfg80211_context cfg80211_ctxt;
- char *ifname;
- int num_msecs = 0;
- int status = 0;
- if (argc < 2) {
- fprintf(stderr, "Invalid commands args\n");
- return -EIO;
- }
- /* Reset the cfg80211 context to 0 if the application does not pass
- * custom private event and command sockets. In this case, the default
- * port is used for netlink communication.
- */
- memset(&cfg80211_ctxt, 0, sizeof(wifi_cfg80211_context));
- ifname = argv[1];
- memcpy(interface, ifname, sizeof(interface));
- cfg80211_ctxt.event_callback = dp_peer_stats_event_callback;
- err = wifi_init_nl80211(&cfg80211_ctxt);
- if (err) {
- fprintf(stderr, "unable to create NL socket\n");
- return -EIO;
- }
- /* Starting event thread to listen for responses*/
- if (wifi_nl80211_start_event_thread(&cfg80211_ctxt)) {
- fprintf(stderr, "Unable to setup nl80211 event thread\n");
- status = -EIO;
- goto cleanup;
- }
- while (true) {
- /*sleep for 1 ms*/
- usleep(1000);
- num_msecs++;
- }
- wifi_destroy_nl80211(&cfg80211_ctxt);
- return 0;
- cleanup:
- wifi_destroy_nl80211(&cfg80211_ctxt);
- return status;
- }
|