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
|
#ifndef CONFIG_NATIVE_WINDOWS
|
||||||
/* send data frame to poll STA and check whether this frame
|
/* send data frame to poll STA and check whether this frame
|
||||||
* is ACKed */
|
* 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");
|
wpa_printf(MSG_DEBUG, " Polling STA with data frame");
|
||||||
sta->flags |= WLAN_STA_PENDING_POLL;
|
sta->flags |= WLAN_STA_PENDING_POLL;
|
||||||
|
|
||||||
os_memset(&hdr, 0, sizeof(hdr));
|
os_memset(&nulldata, 0, sizeof(nulldata));
|
||||||
if (hapd->driver &&
|
if (hapd->driver &&
|
||||||
os_strcmp(hapd->driver->name, "hostap") == 0) {
|
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
|
* but it is apparently not retried so TX Exc events
|
||||||
* are not received for it.
|
* are not received for it.
|
||||||
*/
|
*/
|
||||||
hdr.frame_control =
|
nulldata.hdr.frame_control =
|
||||||
IEEE80211_FC(WLAN_FC_TYPE_DATA,
|
IEEE80211_FC(WLAN_FC_TYPE_DATA,
|
||||||
WLAN_FC_STYPE_DATA);
|
WLAN_FC_STYPE_DATA);
|
||||||
} else {
|
} else {
|
||||||
hdr.frame_control =
|
if (sta->flags & WLAN_STA_WMM) {
|
||||||
IEEE80211_FC(WLAN_FC_TYPE_DATA,
|
nulldata.hdr.frame_control =
|
||||||
WLAN_FC_STYPE_NULLFUNC);
|
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);
|
nulldata.hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS);
|
||||||
os_memcpy(hdr.IEEE80211_DA_FROMDS, sta->addr, ETH_ALEN);
|
os_memcpy(nulldata.hdr.IEEE80211_DA_FROMDS, sta->addr,
|
||||||
os_memcpy(hdr.IEEE80211_BSSID_FROMDS, hapd->own_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);
|
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");
|
perror("ap_handle_timer: send");
|
||||||
#endif /* CONFIG_NATIVE_WINDOWS */
|
#endif /* CONFIG_NATIVE_WINDOWS */
|
||||||
} else if (sta->timeout_next != STA_REMOVE) {
|
} else if (sta->timeout_next != STA_REMOVE) {
|
||||||
|
|
Loading…
Reference in a new issue