Add connect fail reason code from the driver to assoc reject event
Add support to report a vendor specific connect fail reason code fetched from the driver to users by adding the reason code to the event CTRL-EVENT-ASSOC-REJECT. Fetch the connect fail reason code when the driver sends a failure connection result and append the reason code, if available, to assoc reject event. Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
parent
7423fa6e8f
commit
60c902f408
5 changed files with 173 additions and 4 deletions
|
@ -5062,6 +5062,34 @@ struct freq_survey {
|
|||
#define SURVEY_HAS_CHAN_TIME_RX BIT(3)
|
||||
#define SURVEY_HAS_CHAN_TIME_TX BIT(4)
|
||||
|
||||
/**
|
||||
* enum sta_connect_fail_reason_codes - STA connect failure reason code values
|
||||
* @STA_CONNECT_FAIL_REASON_UNSPECIFIED: No reason code specified for
|
||||
* connection failure.
|
||||
* @STA_CONNECT_FAIL_REASON_NO_BSS_FOUND: No Probe Response frame received
|
||||
* for unicast Probe Request frame.
|
||||
* @STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL: STA failed to send auth request.
|
||||
* @STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED: AP didn't send ACK for
|
||||
* auth request.
|
||||
* @STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED: Auth response is not
|
||||
* received from AP.
|
||||
* @STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL: STA failed to send
|
||||
* Association Request frame.
|
||||
* @STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED: AP didn't send ACK for
|
||||
* Association Request frame.
|
||||
* @STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED: Association Response
|
||||
* frame is not received from AP.
|
||||
*/
|
||||
enum sta_connect_fail_reason_codes {
|
||||
STA_CONNECT_FAIL_REASON_UNSPECIFIED = 0,
|
||||
STA_CONNECT_FAIL_REASON_NO_BSS_FOUND = 1,
|
||||
STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL = 2,
|
||||
STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED = 3,
|
||||
STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED = 4,
|
||||
STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL = 5,
|
||||
STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED = 6,
|
||||
STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED = 7,
|
||||
};
|
||||
|
||||
/**
|
||||
* union wpa_event_data - Additional data for wpa_supplicant_event() calls
|
||||
|
@ -5463,6 +5491,11 @@ union wpa_event_data {
|
|||
* FILS ERP messages
|
||||
*/
|
||||
u16 fils_erp_next_seq_num;
|
||||
|
||||
/**
|
||||
* reason_code - Connection failure reason code from the driver
|
||||
*/
|
||||
enum sta_connect_fail_reason_codes reason_code;
|
||||
} assoc_reject;
|
||||
|
||||
struct timeout_event {
|
||||
|
|
|
@ -174,6 +174,7 @@ struct wpa_driver_nl80211_data {
|
|||
unsigned int control_port_ap:1;
|
||||
unsigned int multicast_registrations:1;
|
||||
unsigned int no_rrm:1;
|
||||
unsigned int get_sta_info_vendor_cmd_avail:1;
|
||||
|
||||
u64 vendor_scan_cookie;
|
||||
u64 remain_on_chan_cookie;
|
||||
|
|
|
@ -994,6 +994,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
|
|||
case QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE:
|
||||
drv->add_sta_node_vendor_cmd_avail = 1;
|
||||
break;
|
||||
case QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO:
|
||||
drv->get_sta_info_vendor_cmd_avail = 1;
|
||||
break;
|
||||
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -296,6 +296,94 @@ static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv,
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_DRIVER_NL80211_QCA
|
||||
|
||||
static int qca_drv_connect_fail_reason_code_handler(struct nl_msg *msg,
|
||||
void *arg)
|
||||
{
|
||||
struct nlattr *tb[NL80211_ATTR_MAX + 1];
|
||||
struct nlattr *tb_sta_info[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX + 1];
|
||||
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
|
||||
u32 *reason_code = arg;
|
||||
|
||||
*reason_code = 0;
|
||||
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
|
||||
genlmsg_attrlen(gnlh, 0), NULL);
|
||||
|
||||
if (!tb[NL80211_ATTR_VENDOR_DATA]) {
|
||||
wpa_printf(MSG_ERROR, "%s: Vendor data not found", __func__);
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
nla_parse(tb_sta_info, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX,
|
||||
nla_data(tb[NL80211_ATTR_VENDOR_DATA]),
|
||||
nla_len(tb[NL80211_ATTR_VENDOR_DATA]), NULL);
|
||||
|
||||
if (!tb_sta_info[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE]) {
|
||||
wpa_printf(MSG_INFO, "%s: Vendor attr not found", __func__);
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
*reason_code = nla_get_u32(tb_sta_info[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE]);
|
||||
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
|
||||
static enum qca_sta_connect_fail_reason_codes
|
||||
drv_get_connect_fail_reason_code(struct wpa_driver_nl80211_data *drv)
|
||||
{
|
||||
enum qca_sta_connect_fail_reason_codes reason_code;
|
||||
struct nl_msg *msg;
|
||||
int ret;
|
||||
|
||||
msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
|
||||
if (!msg || nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
|
||||
QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO)) {
|
||||
nlmsg_free(msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = send_and_recv_msgs(drv, msg,
|
||||
qca_drv_connect_fail_reason_code_handler,
|
||||
&reason_code, NULL, NULL);
|
||||
if (ret)
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: Get connect fail reason_code failed: ret=%d (%s)",
|
||||
ret, strerror(-ret));
|
||||
|
||||
return reason_code;
|
||||
}
|
||||
|
||||
|
||||
static enum sta_connect_fail_reason_codes
|
||||
convert_connect_fail_reason_codes(enum qca_sta_connect_fail_reason_codes
|
||||
reason_code)
|
||||
{
|
||||
switch (reason_code) {
|
||||
case QCA_STA_CONNECT_FAIL_REASON_NO_BSS_FOUND:
|
||||
return STA_CONNECT_FAIL_REASON_NO_BSS_FOUND;
|
||||
case QCA_STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL:
|
||||
return STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL;
|
||||
case QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED:
|
||||
return STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED;
|
||||
case QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED:
|
||||
return STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED;
|
||||
case QCA_STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL:
|
||||
return STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL;
|
||||
case QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED:
|
||||
return STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED;
|
||||
case QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED:
|
||||
return STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED;
|
||||
default:
|
||||
return STA_CONNECT_FAIL_REASON_UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
||||
|
||||
|
||||
static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
|
||||
enum nl80211_commands cmd, struct nlattr *status,
|
||||
struct nlattr *addr, struct nlattr *req_ie,
|
||||
|
@ -385,6 +473,17 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
|
|||
if (fils_erp_next_seq_num)
|
||||
event.assoc_reject.fils_erp_next_seq_num =
|
||||
nla_get_u16(fils_erp_next_seq_num);
|
||||
|
||||
#ifdef CONFIG_DRIVER_NL80211_QCA
|
||||
if (drv->get_sta_info_vendor_cmd_avail) {
|
||||
enum qca_sta_connect_fail_reason_codes reason_code;
|
||||
|
||||
reason_code = drv_get_connect_fail_reason_code(drv);
|
||||
event.assoc_reject.reason_code =
|
||||
convert_connect_fail_reason_codes(reason_code);
|
||||
}
|
||||
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
||||
|
||||
wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -4425,6 +4425,31 @@ static void wpa_supplicant_event_assoc_auth(struct wpa_supplicant *wpa_s,
|
|||
}
|
||||
|
||||
|
||||
static const char * connect_fail_reason(enum sta_connect_fail_reason_codes code)
|
||||
{
|
||||
switch (code) {
|
||||
case STA_CONNECT_FAIL_REASON_UNSPECIFIED:
|
||||
return "";
|
||||
case STA_CONNECT_FAIL_REASON_NO_BSS_FOUND:
|
||||
return "no_bss_found";
|
||||
case STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL:
|
||||
return "auth_tx_fail";
|
||||
case STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED:
|
||||
return "auth_no_ack_received";
|
||||
case STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED:
|
||||
return "auth_no_resp_received";
|
||||
case STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL:
|
||||
return "assoc_req_tx_fail";
|
||||
case STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED:
|
||||
return "assoc_no_ack_received";
|
||||
case STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED:
|
||||
return "assoc_no_resp_received";
|
||||
default:
|
||||
return "unknown_reason";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s,
|
||||
union wpa_event_data *data)
|
||||
{
|
||||
|
@ -4444,21 +4469,29 @@ static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s,
|
|||
|
||||
if (data->assoc_reject.bssid)
|
||||
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
|
||||
"bssid=" MACSTR " status_code=%u%s%s%s",
|
||||
"bssid=" MACSTR " status_code=%u%s%s%s%s%s",
|
||||
MAC2STR(data->assoc_reject.bssid),
|
||||
data->assoc_reject.status_code,
|
||||
data->assoc_reject.timed_out ? " timeout" : "",
|
||||
data->assoc_reject.timeout_reason ? "=" : "",
|
||||
data->assoc_reject.timeout_reason ?
|
||||
data->assoc_reject.timeout_reason : "");
|
||||
data->assoc_reject.timeout_reason : "",
|
||||
data->assoc_reject.reason_code !=
|
||||
STA_CONNECT_FAIL_REASON_UNSPECIFIED ?
|
||||
" qca_driver_reason=" : "",
|
||||
connect_fail_reason(data->assoc_reject.reason_code));
|
||||
else
|
||||
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
|
||||
"status_code=%u%s%s%s",
|
||||
"status_code=%u%s%s%s%s%s",
|
||||
data->assoc_reject.status_code,
|
||||
data->assoc_reject.timed_out ? " timeout" : "",
|
||||
data->assoc_reject.timeout_reason ? "=" : "",
|
||||
data->assoc_reject.timeout_reason ?
|
||||
data->assoc_reject.timeout_reason : "");
|
||||
data->assoc_reject.timeout_reason : "",
|
||||
data->assoc_reject.reason_code !=
|
||||
STA_CONNECT_FAIL_REASON_UNSPECIFIED ?
|
||||
" qca_driver_reason=" : "",
|
||||
connect_fail_reason(data->assoc_reject.reason_code));
|
||||
wpa_s->assoc_status_code = data->assoc_reject.status_code;
|
||||
wpas_notify_assoc_status_code(wpa_s);
|
||||
|
||||
|
|
Loading…
Reference in a new issue