DSCP: Parse WFA Capabilities element in (Re)Association Response frame

Add support to parse WFA Capabilities element from the (Re)Association
Response frame. Also register a timeout for the station to wait before
sending a new DSCP query if requested by AP.

Signed-off-by: Veerendranath Jakkam <vjakkam@codeaurora.org>
This commit is contained in:
Veerendranath Jakkam 2021-07-29 20:02:22 +05:30 committed by Jouni Malinen
parent a4aae9f9b8
commit c903257fb1
4 changed files with 85 additions and 0 deletions

View file

@ -1136,6 +1136,17 @@ is as shown below:
- External applications shall clear active DSCP policies upon receiving - External applications shall clear active DSCP policies upon receiving
"CTRL-EVENT-DISCONNECTED" or "CTRL-EVENT-DSCP-POLICY clear_all" events. "CTRL-EVENT-DISCONNECTED" or "CTRL-EVENT-DSCP-POLICY clear_all" events.
- Control interface event message format to indicate wpa_supplicant started
a timer to wait until the unsolicited DSCP request from the AP.
<3>CTRL-EVENT-DSCP-POLICY request_wait start
- Control interface event message format to indicate timeout to receive the
unsolicited DSCP request. This event is expected only when an unsolicited
DSCP request is not received from the AP before timeout.
<3>CTRL-EVENT-DSCP-POLICY request_wait end
DSCP Response: DSCP Response:
A QoS Management STA that enables DSCP Policy capability shall respond A QoS Management STA that enables DSCP Policy capability shall respond
with DSCP response on receipt of a successful DSCP request from its with DSCP response on receipt of a successful DSCP request from its

View file

@ -2977,6 +2977,9 @@ no_pfs:
wpa_s->assoc_freq = data->assoc_info.freq; wpa_s->assoc_freq = data->assoc_info.freq;
wpas_handle_assoc_resp_qos_mgmt(wpa_s, data->assoc_info.resp_ies,
data->assoc_info.resp_ies_len);
return 0; return 0;
} }

View file

@ -17,6 +17,7 @@
#define SCS_RESP_TIMEOUT 1 #define SCS_RESP_TIMEOUT 1
#define DSCP_REQ_TIMEOUT 5
void wpas_populate_mscs_descriptor_ie(struct robust_av_data *robust_av, void wpas_populate_mscs_descriptor_ie(struct robust_av_data *robust_av,
@ -550,6 +551,48 @@ void wpas_handle_assoc_resp_mscs(struct wpa_supplicant *wpa_s, const u8 *bssid,
} }
static void wpas_wait_for_dscp_req_timer(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_supplicant *wpa_s = eloop_ctx;
/* Once timeout is over, reset wait flag and allow sending DSCP query */
wpa_printf(MSG_DEBUG,
"QM: Wait time over for sending DSCP request - allow DSCP query");
wpa_s->wait_for_dscp_req = 0;
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "request_wait end");
}
void wpas_handle_assoc_resp_qos_mgmt(struct wpa_supplicant *wpa_s,
const u8 *ies, size_t ies_len)
{
const u8 *wfa_capa;
wpa_s->connection_dscp = 0;
if (wpa_s->wait_for_dscp_req)
eloop_cancel_timeout(wpas_wait_for_dscp_req_timer, wpa_s, NULL);
if (!ies || ies_len == 0 || !wpa_s->enable_dscp_policy_capa)
return;
wfa_capa = get_vendor_ie(ies, ies_len, WFA_CAPA_IE_VENDOR_TYPE);
if (!wfa_capa || wfa_capa[1] < 6 || wfa_capa[6] < 1 ||
!(wfa_capa[7] & WFA_CAPA_QM_DSCP_POLICY))
return; /* AP does not enable QM DSCP Policy */
wpa_s->connection_dscp = 1;
wpa_s->wait_for_dscp_req = !!(wfa_capa[7] &
WFA_CAPA_QM_UNSOLIC_DSCP);
if (!wpa_s->wait_for_dscp_req)
return;
/* Register a timeout after which dscp query can be sent to AP. */
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "request_wait start");
eloop_register_timeout(DSCP_REQ_TIMEOUT, 0,
wpas_wait_for_dscp_req_timer, wpa_s, NULL);
}
void wpas_handle_robust_av_scs_recv_action(struct wpa_supplicant *wpa_s, void wpas_handle_robust_av_scs_recv_action(struct wpa_supplicant *wpa_s,
const u8 *src, const u8 *buf, const u8 *src, const u8 *buf,
size_t len) size_t len)
@ -1116,6 +1159,11 @@ void wpas_dscp_deinit(struct wpa_supplicant *wpa_s)
wpa_printf(MSG_DEBUG, "QM: Clear all active DSCP policies"); wpa_printf(MSG_DEBUG, "QM: Clear all active DSCP policies");
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "clear_all"); wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "clear_all");
wpa_s->dscp_req_dialog_token = 0; wpa_s->dscp_req_dialog_token = 0;
wpa_s->connection_dscp = 0;
if (wpa_s->wait_for_dscp_req) {
wpa_s->wait_for_dscp_req = 0;
eloop_cancel_timeout(wpas_wait_for_dscp_req_timer, wpa_s, NULL);
}
} }
@ -1194,6 +1242,12 @@ void wpas_handle_qos_mgmt_recv_action(struct wpa_supplicant *wpa_s,
return; return;
} }
if (!wpa_s->connection_dscp) {
wpa_printf(MSG_DEBUG,
"QM: DSCP Policy capability not enabled for the current association - ignore QoS Management Action frames");
return;
}
if (len < 1) if (len < 1)
return; return;
@ -1211,6 +1265,12 @@ void wpas_handle_qos_mgmt_recv_action(struct wpa_supplicant *wpa_s,
return; return;
} }
/* Clear wait_for_dscp_req on receiving first DSCP request from AP */
if (wpa_s->wait_for_dscp_req) {
wpa_s->wait_for_dscp_req = 0;
eloop_cancel_timeout(wpas_wait_for_dscp_req_timer, wpa_s, NULL);
}
wpa_s->dscp_req_dialog_token = buf[1]; wpa_s->dscp_req_dialog_token = buf[1];
more = buf[2] & DSCP_POLICY_CTRL_MORE; more = buf[2] & DSCP_POLICY_CTRL_MORE;
reset = buf[2] & DSCP_POLICY_CTRL_RESET; reset = buf[2] & DSCP_POLICY_CTRL_RESET;
@ -1289,6 +1349,13 @@ int wpas_send_dscp_response(struct wpa_supplicant *wpa_s,
return -1; return -1;
} }
if (!wpa_s->connection_dscp) {
wpa_printf(MSG_ERROR,
"QM: Failed to send DSCP response - DSCP capability not enabled for the current association");
return -1;
}
buf_len = 1 + /* Category */ buf_len = 1 + /* Category */
3 + /* OUI */ 3 + /* OUI */
1 + /* OUI Type */ 1 + /* OUI Type */

View file

@ -1515,6 +1515,8 @@ struct wpa_supplicant {
bool ongoing_scs_req; bool ongoing_scs_req;
u8 dscp_req_dialog_token; u8 dscp_req_dialog_token;
unsigned int enable_dscp_policy_capa:1; unsigned int enable_dscp_policy_capa:1;
unsigned int connection_dscp:1;
unsigned int wait_for_dscp_req:1;
}; };
@ -1861,6 +1863,8 @@ void wpas_handle_qos_mgmt_recv_action(struct wpa_supplicant *wpa_s,
void wpas_dscp_deinit(struct wpa_supplicant *wpa_s); void wpas_dscp_deinit(struct wpa_supplicant *wpa_s);
int wpas_send_dscp_response(struct wpa_supplicant *wpa_s, int wpas_send_dscp_response(struct wpa_supplicant *wpa_s,
struct dscp_resp_data *resp_data); struct dscp_resp_data *resp_data);
void wpas_handle_assoc_resp_qos_mgmt(struct wpa_supplicant *wpa_s,
const u8 *ies, size_t ies_len);
int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s, int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s,
const u8 *bssid, int akmp, int cipher, const u8 *bssid, int akmp, int cipher,