diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index db60e069d..983c2ced5 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -2040,6 +2040,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); } } diff --git a/wpa_supplicant/wmm_ac.c b/wpa_supplicant/wmm_ac.c index 47d74368c..5625d3663 100644 --- a/wpa_supplicant/wmm_ac.c +++ b/wpa_supplicant/wmm_ac.c @@ -910,3 +910,86 @@ 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(tspecs_count, + sizeof(*wpa_s->last_tspecs)); + 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) +{ + if (wpa_s->last_tspecs) { + 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) +{ + unsigned int i; + + if (!wpa_s->wmm_ac_assoc_info || !wpa_s->last_tspecs_count) + return 0; + + wpa_printf(MSG_DEBUG, "WMM AC: Restore %u 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; +} diff --git a/wpa_supplicant/wmm_ac.h b/wpa_supplicant/wmm_ac.h index 2b02025b3..5171b1683 100644 --- a/wpa_supplicant/wmm_ac.h +++ b/wpa_supplicant/wmm_ac.h @@ -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 */ diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index b048728d8..32676cde9 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -438,6 +438,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; @@ -1529,8 +1530,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; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 52137d402..9d24b9427 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -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; @@ -929,6 +930,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; };