wlantest: Add per-TID RX/TX counters
authorJouni Malinen <j@w1.fi>
Tue, 24 Dec 2013 18:21:27 +0000 (20:21 +0200)
committerJouni Malinen <j@w1.fi>
Tue, 24 Dec 2013 18:21:27 +0000 (20:21 +0200)
Signed-hostap: Jouni Malinen <j@w1.fi>

wlantest/ctrl.c
wlantest/rx_data.c
wlantest/wlantest.h
wlantest/wlantest_cli.c
wlantest/wlantest_ctrl.h

index 86bd672..7507c2f 100644 (file)
@@ -290,6 +290,8 @@ static void ctrl_clear_sta_counters(struct wlantest *wt, int sock, u8 *cmd,
        }
 
        os_memset(sta->counters, 0, sizeof(sta->counters));
+       os_memset(sta->tx_tid, 0, sizeof(sta->tx_tid));
+       os_memset(sta->rx_tid, 0, sizeof(sta->rx_tid));
        ctrl_send_simple(wt, sock, WLANTEST_CTRL_SUCCESS);
 }
 
@@ -1195,6 +1197,76 @@ static void ctrl_relog(struct wlantest *wt, int sock)
 }
 
 
+static void ctrl_get_tx_tid(struct wlantest *wt, int sock, u8 *cmd, size_t clen)
+{
+       u8 *addr;
+       size_t addr_len;
+       struct wlantest_bss *bss;
+       struct wlantest_sta *sta;
+       u32 counter;
+       u8 buf[4 + 12], *end, *pos;
+
+       bss = ctrl_get_bss(wt, sock, cmd, clen);
+       sta = ctrl_get_sta(wt, sock, cmd, clen, bss);
+       if (sta == NULL)
+               return;
+
+       addr = attr_get(cmd, clen, WLANTEST_ATTR_TID, &addr_len);
+       if (addr == NULL || addr_len != 4) {
+               ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD);
+               return;
+       }
+       counter = WPA_GET_BE32(addr);
+       if (counter >= 16 + 1) {
+               ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD);
+               return;
+       }
+
+       pos = buf;
+       end = buf + sizeof(buf);
+       WPA_PUT_BE32(pos, WLANTEST_CTRL_SUCCESS);
+       pos += 4;
+       pos = attr_add_be32(pos, end, WLANTEST_ATTR_COUNTER,
+                           sta->tx_tid[counter]);
+       ctrl_send(wt, sock, buf, pos - buf);
+}
+
+
+static void ctrl_get_rx_tid(struct wlantest *wt, int sock, u8 *cmd, size_t clen)
+{
+       u8 *addr;
+       size_t addr_len;
+       struct wlantest_bss *bss;
+       struct wlantest_sta *sta;
+       u32 counter;
+       u8 buf[4 + 12], *end, *pos;
+
+       bss = ctrl_get_bss(wt, sock, cmd, clen);
+       sta = ctrl_get_sta(wt, sock, cmd, clen, bss);
+       if (sta == NULL)
+               return;
+
+       addr = attr_get(cmd, clen, WLANTEST_ATTR_TID, &addr_len);
+       if (addr == NULL || addr_len != 4) {
+               ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD);
+               return;
+       }
+       counter = WPA_GET_BE32(addr);
+       if (counter >= 16 + 1) {
+               ctrl_send_simple(wt, sock, WLANTEST_CTRL_INVALID_CMD);
+               return;
+       }
+
+       pos = buf;
+       end = buf + sizeof(buf);
+       WPA_PUT_BE32(pos, WLANTEST_CTRL_SUCCESS);
+       pos += 4;
+       pos = attr_add_be32(pos, end, WLANTEST_ATTR_COUNTER,
+                           sta->rx_tid[counter]);
+       ctrl_send(wt, sock, buf, pos - buf);
+}
+
+
 static void ctrl_read(int sock, void *eloop_ctx, void *sock_ctx)
 {
        struct wlantest *wt = eloop_ctx;
@@ -1281,6 +1353,12 @@ static void ctrl_read(int sock, void *eloop_ctx, void *sock_ctx)
        case WLANTEST_CTRL_RELOG:
                ctrl_relog(wt, sock);
                break;
+       case WLANTEST_CTRL_GET_TX_TID:
+               ctrl_get_tx_tid(wt, sock, buf + 4, len - 4);
+               break;
+       case WLANTEST_CTRL_GET_RX_TID:
+               ctrl_get_rx_tid(wt, sock, buf + 4, len - 4);
+               break;
        default:
                ctrl_send_simple(wt, sock, WLANTEST_CTRL_UNKNOWN_CMD);
                break;
index eaa2b86..d23425e 100644 (file)
@@ -300,6 +300,8 @@ static void rx_data_bss_prot(struct wlantest *wt,
                return;
        }
 
+       if (sta == NULL)
+               return;
        if (sta->pairwise_cipher & (WPA_CIPHER_TKIP | WPA_CIPHER_CCMP) &&
            !(data[3] & 0x20)) {
                add_note(wt, MSG_INFO, "Expected TKIP/CCMP frame from "
@@ -336,10 +338,19 @@ static void rx_data_bss_prot(struct wlantest *wt,
                         keyid, MAC2STR(hdr->addr2));
        }
 
-       if (qos)
+       if (qos) {
                tid = qos[0] & 0x0f;
-       else
+               if (fc & WLAN_FC_TODS)
+                       sta->tx_tid[tid]++;
+               else
+                       sta->rx_tid[tid]++;
+       } else {
                tid = 0;
+               if (fc & WLAN_FC_TODS)
+                       sta->tx_tid[16]++;
+               else
+                       sta->rx_tid[16]++;
+       }
        if (tk) {
                if (os_memcmp(hdr->addr2, tdls->init->addr, ETH_ALEN) == 0)
                        rsc = tdls->rsc_init[tid];
@@ -434,6 +445,8 @@ static void rx_data_bss(struct wlantest *wt, const struct ieee80211_hdr *hdr,
                rx_data_bss_prot(wt, hdr, qos, dst, src, data, len);
        else {
                const u8 *bssid, *sta_addr, *peer_addr;
+               struct wlantest_bss *bss;
+
                if (fc & WLAN_FC_TODS) {
                        bssid = hdr->addr1;
                        sta_addr = hdr->addr2;
@@ -447,6 +460,27 @@ static void rx_data_bss(struct wlantest *wt, const struct ieee80211_hdr *hdr,
                        sta_addr = hdr->addr2;
                        peer_addr = hdr->addr1;
                }
+
+               bss = bss_get(wt, bssid);
+               if (bss) {
+                       struct wlantest_sta *sta = sta_get(bss, sta_addr);
+
+                       if (sta) {
+                               if (qos) {
+                                       int tid = qos[0] & 0x0f;
+                                       if (fc & WLAN_FC_TODS)
+                                               sta->tx_tid[tid]++;
+                                       else
+                                               sta->rx_tid[tid]++;
+                               } else {
+                                       if (fc & WLAN_FC_TODS)
+                                               sta->tx_tid[16]++;
+                                       else
+                                               sta->rx_tid[16]++;
+                               }
+                       }
+               }
+
                rx_data_process(wt, bssid, sta_addr, dst, src, data, len, 0,
                                peer_addr);
        }
index 60802d5..68531d8 100644 (file)
@@ -97,6 +97,9 @@ struct wlantest_sta {
        u8 gtk[32];
        size_t gtk_len;
        int gtk_idx;
+
+       u32 tx_tid[16 + 1];
+       u32 rx_tid[16 + 1];
 };
 
 struct wlantest_tdls {
index afe38c4..ae84102 100644 (file)
@@ -1452,6 +1452,119 @@ static char ** complete_info_bss(int s, const char *str, int pos)
 }
 
 
+static int cmd_get_tx_tid(int s, int argc, char *argv[])
+{
+       u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
+       u8 buf[100], *end, *pos;
+       int rlen;
+       size_t len;
+
+       if (argc != 3) {
+               printf("get_tx_tid needs three arguments: "
+                      "BSSID, STA address, and TID\n");
+               return -1;
+       }
+
+       pos = buf;
+       end = buf + sizeof(buf);
+       WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_TX_TID);
+       pos += 4;
+
+       pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
+       if (hwaddr_aton(argv[0], pos) < 0) {
+               printf("Invalid BSSID '%s'\n", argv[0]);
+               return -1;
+       }
+       pos += ETH_ALEN;
+
+       pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
+       if (hwaddr_aton(argv[1], pos) < 0) {
+               printf("Invalid STA address '%s'\n", argv[1]);
+               return -1;
+       }
+       pos += ETH_ALEN;
+
+       pos = attr_add_be32(pos, end, WLANTEST_ATTR_TID, atoi(argv[2]));
+
+       rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
+       if (rlen < 0)
+               return -1;
+
+       pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
+       if (pos == NULL || len != 4)
+               return -1;
+       printf("%u\n", WPA_GET_BE32(pos));
+       return 0;
+}
+
+
+static int cmd_get_rx_tid(int s, int argc, char *argv[])
+{
+       u8 resp[WLANTEST_CTRL_MAX_RESP_LEN];
+       u8 buf[100], *end, *pos;
+       int rlen;
+       size_t len;
+
+       if (argc != 3) {
+               printf("get_tx_tid needs three arguments: "
+                      "BSSID, STA address, and TID\n");
+               return -1;
+       }
+
+       pos = buf;
+       end = buf + sizeof(buf);
+       WPA_PUT_BE32(pos, WLANTEST_CTRL_GET_RX_TID);
+       pos += 4;
+
+       pos = attr_hdr_add(pos, end, WLANTEST_ATTR_BSSID, ETH_ALEN);
+       if (hwaddr_aton(argv[0], pos) < 0) {
+               printf("Invalid BSSID '%s'\n", argv[0]);
+               return -1;
+       }
+       pos += ETH_ALEN;
+
+       pos = attr_hdr_add(pos, end, WLANTEST_ATTR_STA_ADDR, ETH_ALEN);
+       if (hwaddr_aton(argv[1], pos) < 0) {
+               printf("Invalid STA address '%s'\n", argv[1]);
+               return -1;
+       }
+       pos += ETH_ALEN;
+
+       pos = attr_add_be32(pos, end, WLANTEST_ATTR_TID, atoi(argv[2]));
+
+       rlen = cmd_send_and_recv(s, buf, pos - buf, resp, sizeof(resp));
+       if (rlen < 0)
+               return -1;
+
+       pos = attr_get(resp + 4, rlen - 4, WLANTEST_ATTR_COUNTER, &len);
+       if (pos == NULL || len != 4)
+               return -1;
+       printf("%u\n", WPA_GET_BE32(pos));
+       return 0;
+}
+
+
+static char ** complete_get_tid(int s, const char *str, int pos)
+{
+       int arg = get_cmd_arg_num(str, pos);
+       char **res = NULL;
+       u8 addr[ETH_ALEN];
+
+       switch (arg) {
+       case 1:
+               res = get_bssid_list(s);
+               break;
+       case 2:
+               if (hwaddr_aton(&str[get_prev_arg_pos(str, pos)], addr) < 0)
+                       break;
+               res = get_sta_list(s, addr, 0);
+               break;
+       }
+
+       return res;
+}
+
+
 struct wlantest_cli_cmd {
        const char *cmd;
        int (*handler)(int s, int argc, char *argv[]);
@@ -1503,6 +1616,12 @@ static const struct wlantest_cli_cmd wlantest_cli_commands[] = {
          "<counter> <BSSID> = get BSS counter value",
          complete_get_bss_counter },
        { "relog", cmd_relog, "= re-open log-file (allow rolling logs)", NULL },
+       { "get_tx_tid", cmd_get_tx_tid,
+         "<BSSID> <STA> <TID> = get STA TX TID counter value",
+         complete_get_tid },
+       { "get_rx_tid", cmd_get_rx_tid,
+         "<BSSID> <STA> <TID> = get STA RX TID counter value",
+         complete_get_tid },
        { NULL, NULL, NULL, NULL }
 };
 
index 41b6583..8ecbaa7 100644 (file)
@@ -36,6 +36,8 @@ enum wlantest_ctrl_cmd {
        WLANTEST_CTRL_CLEAR_TDLS_COUNTERS,
        WLANTEST_CTRL_GET_TDLS_COUNTER,
        WLANTEST_CTRL_RELOG,
+       WLANTEST_CTRL_GET_TX_TID,
+       WLANTEST_CTRL_GET_RX_TID,
 };
 
 enum wlantest_ctrl_attr {
@@ -56,6 +58,7 @@ enum wlantest_ctrl_attr {
        WLANTEST_ATTR_TDLS_COUNTER,
        WLANTEST_ATTR_STA2_ADDR,
        WLANTEST_ATTR_WEPKEY,
+       WLANTEST_ATTR_TID,
 };
 
 enum wlantest_bss_counter {