AP: Use QoS nullfunc for connection poll
When polling a station that has been inactive for a while, hostapd currently always uses a null data frame. This is a bit strange with uAPSD clients (though it seems to mostly work) since the EOSP bit can never be set in a non-QoS frame. Make hostapd use QoS null data frames for probing when the station is a QoS STA. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
ed908a55da
commit
1473f95e98
1 changed files with 23 additions and 11 deletions
|
@ -322,12 +322,16 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
|||
#ifndef CONFIG_NATIVE_WINDOWS
|
||||
/* send data frame to poll STA and check whether this frame
|
||||
* is ACKed */
|
||||
struct ieee80211_hdr hdr;
|
||||
struct {
|
||||
struct ieee80211_hdr hdr;
|
||||
u16 qos_ctl;
|
||||
} STRUCT_PACKED nulldata;
|
||||
int size = sizeof(struct ieee80211_hdr);
|
||||
|
||||
wpa_printf(MSG_DEBUG, " Polling STA with data frame");
|
||||
sta->flags |= WLAN_STA_PENDING_POLL;
|
||||
|
||||
os_memset(&hdr, 0, sizeof(hdr));
|
||||
os_memset(&nulldata, 0, sizeof(nulldata));
|
||||
if (hapd->driver &&
|
||||
os_strcmp(hapd->driver->name, "hostap") == 0) {
|
||||
/*
|
||||
|
@ -335,22 +339,30 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx)
|
|||
* but it is apparently not retried so TX Exc events
|
||||
* are not received for it.
|
||||
*/
|
||||
hdr.frame_control =
|
||||
nulldata.hdr.frame_control =
|
||||
IEEE80211_FC(WLAN_FC_TYPE_DATA,
|
||||
WLAN_FC_STYPE_DATA);
|
||||
} else {
|
||||
hdr.frame_control =
|
||||
IEEE80211_FC(WLAN_FC_TYPE_DATA,
|
||||
WLAN_FC_STYPE_NULLFUNC);
|
||||
if (sta->flags & WLAN_STA_WMM) {
|
||||
nulldata.hdr.frame_control =
|
||||
IEEE80211_FC(WLAN_FC_TYPE_DATA,
|
||||
WLAN_FC_STYPE_QOS_NULL);
|
||||
size = sizeof(nulldata);
|
||||
} else
|
||||
nulldata.hdr.frame_control =
|
||||
IEEE80211_FC(WLAN_FC_TYPE_DATA,
|
||||
WLAN_FC_STYPE_NULLFUNC);
|
||||
}
|
||||
|
||||
hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);
|
||||
os_memcpy(hdr.IEEE80211_DA_FROMDS, sta->addr, ETH_ALEN);
|
||||
os_memcpy(hdr.IEEE80211_BSSID_FROMDS, hapd->own_addr,
|
||||
nulldata.hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);
|
||||
os_memcpy(nulldata.hdr.IEEE80211_DA_FROMDS, sta->addr,
|
||||
ETH_ALEN);
|
||||
os_memcpy(nulldata.hdr.IEEE80211_BSSID_FROMDS, hapd->own_addr,
|
||||
ETH_ALEN);
|
||||
os_memcpy(nulldata.hdr.IEEE80211_SA_FROMDS, hapd->own_addr,
|
||||
ETH_ALEN);
|
||||
os_memcpy(hdr.IEEE80211_SA_FROMDS, hapd->own_addr, ETH_ALEN);
|
||||
|
||||
if (hostapd_drv_send_mlme(hapd, &hdr, sizeof(hdr)) < 0)
|
||||
if (hostapd_drv_send_mlme(hapd, &nulldata, size) < 0)
|
||||
perror("ap_handle_timer: send");
|
||||
#endif /* CONFIG_NATIVE_WINDOWS */
|
||||
} else if (sta->timeout_next != STA_REMOVE) {
|
||||
|
|
Loading…
Reference in a new issue