@@ -2048,6 +2048,9 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
wmm_ac_notify_assoc(wpa_s, data->assoc_info.resp_ies,
data->assoc_info.resp_ies_len,
&data->assoc_info.wmm_params);
+
+ if (wpa_s->reassoc_same_bss)
+ wmm_ac_restore_tspecs(wpa_s);
}
}
@@ -910,3 +910,77 @@ int wpas_wmm_ac_status(struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
return pos;
}
+
+static u8 wmm_ac_get_tspecs_count(struct wpa_supplicant *wpa_s)
+{
+ int ac, dir, tspecs_count = 0;
+
+ for (ac = 0; ac < WMM_AC_NUM; ac++)
+ for (dir = 0; dir < TS_DIR_IDX_COUNT; dir++)
+ if (wpa_s->tspecs[ac][dir])
+ tspecs_count++;
+ return tspecs_count;
+}
+
+void wmm_ac_save_tspecs(struct wpa_supplicant *wpa_s)
+{
+ int ac, dir, tspecs_count;
+
+ wpa_printf(MSG_DEBUG, "WMM AC: Save last configured tspecs");
+
+ if (!wpa_s->wmm_ac_assoc_info)
+ return;
+
+ tspecs_count = wmm_ac_get_tspecs_count(wpa_s);
+ if (!tspecs_count) {
+ wpa_printf(MSG_DEBUG, "WMM AC: No configured TSPECs");
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "WMM AC: saving tspecs");
+
+ wmm_ac_clear_saved_tspecs(wpa_s);
+ wpa_s->last_tspecs = os_calloc(sizeof(*wpa_s->last_tspecs),
+ tspecs_count);
+ if (!wpa_s->last_tspecs) {
+ wpa_printf(MSG_ERROR, "WMM AC: Failed to save tspecs!");
+ return;
+ }
+
+ for (ac = 0; ac < WMM_AC_NUM; ac++) {
+ for (dir = 0; dir < TS_DIR_IDX_COUNT; dir++) {
+ if (!wpa_s->tspecs[ac][dir])
+ continue;
+
+ wpa_s->last_tspecs[wpa_s->last_tspecs_count++] =
+ *wpa_s->tspecs[ac][dir];
+ }
+ }
+
+ wpa_printf(MSG_DEBUG, "WMM AC: successfully saved %d TSPECs",
+ wpa_s->last_tspecs_count);
+}
+
+void wmm_ac_clear_saved_tspecs(struct wpa_supplicant *wpa_s)
+{
+ wpa_printf(MSG_DEBUG, "WMM AC: Clear saved tspecs");
+ os_free(wpa_s->last_tspecs);
+ wpa_s->last_tspecs = NULL;
+ wpa_s->last_tspecs_count = 0;
+}
+
+int wmm_ac_restore_tspecs(struct wpa_supplicant *wpa_s)
+{
+ int i;
+
+ if (!wpa_s->wmm_ac_assoc_info || !wpa_s->last_tspecs_count)
+ return 0;
+
+ wpa_printf(MSG_DEBUG, "WMM AC: Restore %d saved tspecs",
+ wpa_s->last_tspecs_count);
+
+ for (i = 0; i < wpa_s->last_tspecs_count; i++)
+ wmm_ac_add_ts(wpa_s, wpa_s->bssid, &wpa_s->last_tspecs[i]);
+
+ return 0;
+}
@@ -169,5 +169,8 @@ int wpas_wmm_ac_delts(struct wpa_supplicant *wpa_s, u8 tsid);
void wmm_ac_rx_action(struct wpa_supplicant *wpa_s, const u8 *da,
const u8 *sa, const u8 *data, size_t len);
int wpas_wmm_ac_status(struct wpa_supplicant *wpa_s, char *buf, size_t buflen);
+void wmm_ac_save_tspecs(struct wpa_supplicant *wpa_s);
+void wmm_ac_clear_saved_tspecs(struct wpa_supplicant *wpa_s);
+int wmm_ac_restore_tspecs(struct wpa_supplicant *wpa_s);
#endif /* WMM_AC_H */
@@ -435,6 +435,7 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
wpa_tdls_deinit(wpa_s->wpa);
#endif /* CONFIG_TDLS */
+ wmm_ac_clear_saved_tspecs(wpa_s);
pmksa_candidate_free(wpa_s->wpa);
wpa_sm_deinit(wpa_s->wpa);
wpa_s->wpa = NULL;
@@ -1489,8 +1490,15 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
else
rand_style = ssid->mac_addr;
+ wmm_ac_clear_saved_tspecs(wpa_s);
+ wpa_s->reassoc_same_bss = 0;
+
if (wpa_s->last_ssid == ssid) {
wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS");
+ if (wpa_s->current_bss && wpa_s->current_bss == bss) {
+ wmm_ac_save_tspecs(wpa_s);
+ wpa_s->reassoc_same_bss = 1;
+ }
} else if (rand_style > 0) {
if (wpas_update_random_addr(wpa_s, rand_style) < 0)
return;
@@ -444,6 +444,7 @@ struct wpa_supplicant {
u8 pending_bssid[ETH_ALEN]; /* If wpa_state == WPA_ASSOCIATING, this
* field contains the target BSSID. */
int reassociate; /* reassociation requested */
+ int reassoc_same_bss; /* reassociating to the same bss */
int disconnected; /* all connections disabled; i.e., do no reassociate
* before this has been cleared */
struct wpa_ssid *current_ssid;
@@ -926,6 +927,8 @@ struct wpa_supplicant {
struct wmm_tspec_element *tspecs[WMM_AC_NUM][TS_DIR_IDX_COUNT];
struct wmm_ac_addts_request *addts_request;
u8 wmm_ac_last_dialog_token;
+ struct wmm_tspec_element *last_tspecs;
+ u8 last_tspecs_count;
struct rrm_data rrm;
};