- External applications shall clear active DSCP policies upon receiving
"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:
A QoS Management STA that enables DSCP Policy capability shall respond
with DSCP response on receipt of a successful DSCP request from its
#define SCS_RESP_TIMEOUT 1
+#define DSCP_REQ_TIMEOUT 5
void wpas_populate_mscs_descriptor_ie(struct robust_av_data *robust_av,
}
+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,
const u8 *src, const u8 *buf,
size_t len)
wpa_printf(MSG_DEBUG, "QM: Clear all active DSCP policies");
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "clear_all");
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);
+ }
}
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)
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];
more = buf[2] & DSCP_POLICY_CTRL_MORE;
reset = buf[2] & DSCP_POLICY_CTRL_RESET;
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 */
3 + /* OUI */
1 + /* OUI Type */
bool ongoing_scs_req;
u8 dscp_req_dialog_token;
unsigned int enable_dscp_policy_capa:1;
+ unsigned int connection_dscp:1;
+ unsigned int wait_for_dscp_req:1;
};
void wpas_dscp_deinit(struct wpa_supplicant *wpa_s);
int wpas_send_dscp_response(struct wpa_supplicant *wpa_s,
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,
const u8 *bssid, int akmp, int cipher,