diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 069e0267f..180e2f9dd 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -7373,6 +7373,7 @@ static int get_sta_handler(struct nl_msg *msg, void *arg) [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 }, [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 }, [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 }, + [NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 }, }; nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), @@ -7408,6 +7409,9 @@ static int get_sta_handler(struct nl_msg *msg, void *arg) if (stats[NL80211_STA_INFO_TX_PACKETS]) data->tx_packets = nla_get_u32(stats[NL80211_STA_INFO_TX_PACKETS]); + if (stats[NL80211_STA_INFO_TX_FAILED]) + data->tx_retry_failed = + nla_get_u32(stats[NL80211_STA_INFO_TX_FAILED]); return NL_SKIP; } diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index ba2edffed..848d33ddd 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -4324,6 +4324,24 @@ static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf, } +static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf, + size_t buflen) +{ + struct hostap_sta_driver_data sta; + int ret; + + ret = wpa_drv_pktcnt_poll(wpa_s, &sta); + if (ret) + return -1; + + ret = os_snprintf(buf, buflen, "TXGOOD=%lu\nTXBAD=%lu\nRXGOOD=%lu\n", + sta.tx_packets, sta.tx_retry_failed, sta.rx_packets); + if (ret < 0 || (size_t) ret > buflen) + return -1; + return ret; +} + + char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, char *buf, size_t *resp_len) { @@ -4825,6 +4843,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, } else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) { reply_len = wpa_supplicant_signal_poll(wpa_s, reply, reply_size); + } else if (os_strncmp(buf, "PKTCNT_POLL", 11) == 0) { + reply_len = wpa_supplicant_pktcnt_poll(wpa_s, reply, + reply_size); #ifdef CONFIG_AUTOSCAN } else if (os_strncmp(buf, "AUTOSCAN ", 9) == 0) { if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9)) diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index ac0936a70..43fdb64b8 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -463,6 +463,15 @@ static inline int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s, return -1; } +static inline int wpa_drv_pktcnt_poll(struct wpa_supplicant *wpa_s, + struct hostap_sta_driver_data *sta) +{ + if (wpa_s->driver->read_sta_data) + return wpa_s->driver->read_sta_data(wpa_s->drv_priv, sta, + wpa_s->bssid); + return -1; +} + static inline int wpa_drv_set_ap_wps_ie(struct wpa_supplicant *wpa_s, const struct wpabuf *beacon, const struct wpabuf *proberesp, diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 2cb9513d0..e510b9bd4 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -2174,6 +2174,13 @@ static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc, } +static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "PKTCNT_POLL"); +} + + static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -2619,6 +2626,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = { { "signal_poll", wpa_cli_cmd_signal_poll, NULL, cli_cmd_flag_none, "= get signal parameters" }, + { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL, + cli_cmd_flag_none, + "= get TX/RX packet counters" }, { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL, cli_cmd_flag_none, "= trigger IEEE 802.1X/EAPOL reauthentication" },