Commit 9fef6544 authored by Emmanuel Grumbach's avatar Emmanuel Grumbach Committed by Johannes Berg

mac80211: always update the PM state of a peer on MGMT / DATA frames

The 2016 version of the spec is more generic about when the
AP should update the power management state of the peer:
the AP shall update the state based on any management or
data frames. This means that even non-bufferable management
frames should be looked at to update to maintain the power
management state of the peer.

This can avoid problematic cases for example if a station
disappears while being asleep and then re-appears. The AP
would remember it as in power save, but the Authentication
frame couldn't be used to set the peer as awake again.
Note that this issues wasn't really critical since at some
point (after the association) we would have removed the
station and created another one with all the states cleared.
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent e16ea4bb
...@@ -1607,23 +1607,16 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) ...@@ -1607,23 +1607,16 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
/* /*
* Change STA power saving mode only at the end of a frame * Change STA power saving mode only at the end of a frame
* exchange sequence. * exchange sequence, and only for a data or management
* frame as specified in IEEE 802.11-2016 11.2.3.2
*/ */
if (!ieee80211_hw_check(&sta->local->hw, AP_LINK_PS) && if (!ieee80211_hw_check(&sta->local->hw, AP_LINK_PS) &&
!ieee80211_has_morefrags(hdr->frame_control) && !ieee80211_has_morefrags(hdr->frame_control) &&
!ieee80211_is_back_req(hdr->frame_control) && (ieee80211_is_mgmt(hdr->frame_control) ||
ieee80211_is_data(hdr->frame_control)) &&
!(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
(rx->sdata->vif.type == NL80211_IFTYPE_AP || (rx->sdata->vif.type == NL80211_IFTYPE_AP ||
rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) {
/*
* PM bit is only checked in frames where it isn't reserved,
* in AP mode it's reserved in non-bufferable management frames
* (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field)
* BAR frames should be ignored as specified in
* IEEE 802.11-2012 10.2.1.2.
*/
(!ieee80211_is_mgmt(hdr->frame_control) ||
ieee80211_is_bufferable_mmpdu(hdr->frame_control))) {
if (test_sta_flag(sta, WLAN_STA_PS_STA)) { if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
if (!ieee80211_has_pm(hdr->frame_control)) if (!ieee80211_has_pm(hdr->frame_control))
sta_ps_end(sta); sta_ps_end(sta);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment