diff options
author | Johannes Berg <johannes.berg@intel.com> | 2017-11-21 08:46:08 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2017-11-27 05:23:20 -0500 |
commit | 7b6ddeaf27eca72795ceeae2f0f347db1b5f9a30 (patch) | |
tree | cc562ff138989b1e20f0fb19b2e2be1a0aaf90c9 /net/mac80211/tx.c | |
parent | 01a95b2141e337dea15ad48e60a35c72a9b10205 (diff) |
mac80211: use QoS NDP for AP probing
When connected to a QoS/WMM AP, mac80211 should use a QoS NDP
for probing it, instead of a regular non-QoS one, fix this.
Change all the drivers to *not* allow QoS NDP for now, even
though it looks like most of them should be OK with that.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r-- | net/mac80211/tx.c | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 7b8154474b9e..3160954fc406 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -4438,13 +4438,15 @@ struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw, | |||
4438 | EXPORT_SYMBOL(ieee80211_pspoll_get); | 4438 | EXPORT_SYMBOL(ieee80211_pspoll_get); |
4439 | 4439 | ||
4440 | struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, | 4440 | struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, |
4441 | struct ieee80211_vif *vif) | 4441 | struct ieee80211_vif *vif, |
4442 | bool qos_ok) | ||
4442 | { | 4443 | { |
4443 | struct ieee80211_hdr_3addr *nullfunc; | 4444 | struct ieee80211_hdr_3addr *nullfunc; |
4444 | struct ieee80211_sub_if_data *sdata; | 4445 | struct ieee80211_sub_if_data *sdata; |
4445 | struct ieee80211_if_managed *ifmgd; | 4446 | struct ieee80211_if_managed *ifmgd; |
4446 | struct ieee80211_local *local; | 4447 | struct ieee80211_local *local; |
4447 | struct sk_buff *skb; | 4448 | struct sk_buff *skb; |
4449 | bool qos = false; | ||
4448 | 4450 | ||
4449 | if (WARN_ON(vif->type != NL80211_IFTYPE_STATION)) | 4451 | if (WARN_ON(vif->type != NL80211_IFTYPE_STATION)) |
4450 | return NULL; | 4452 | return NULL; |
@@ -4453,7 +4455,17 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, | |||
4453 | ifmgd = &sdata->u.mgd; | 4455 | ifmgd = &sdata->u.mgd; |
4454 | local = sdata->local; | 4456 | local = sdata->local; |
4455 | 4457 | ||
4456 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*nullfunc)); | 4458 | if (qos_ok) { |
4459 | struct sta_info *sta; | ||
4460 | |||
4461 | rcu_read_lock(); | ||
4462 | sta = sta_info_get(sdata, ifmgd->bssid); | ||
4463 | qos = sta && sta->sta.wme; | ||
4464 | rcu_read_unlock(); | ||
4465 | } | ||
4466 | |||
4467 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | ||
4468 | sizeof(*nullfunc) + 2); | ||
4457 | if (!skb) | 4469 | if (!skb) |
4458 | return NULL; | 4470 | return NULL; |
4459 | 4471 | ||
@@ -4463,6 +4475,19 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, | |||
4463 | nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | | 4475 | nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | |
4464 | IEEE80211_STYPE_NULLFUNC | | 4476 | IEEE80211_STYPE_NULLFUNC | |
4465 | IEEE80211_FCTL_TODS); | 4477 | IEEE80211_FCTL_TODS); |
4478 | if (qos) { | ||
4479 | __le16 qos = cpu_to_le16(7); | ||
4480 | |||
4481 | BUILD_BUG_ON((IEEE80211_STYPE_QOS_NULLFUNC | | ||
4482 | IEEE80211_STYPE_NULLFUNC) != | ||
4483 | IEEE80211_STYPE_QOS_NULLFUNC); | ||
4484 | nullfunc->frame_control |= | ||
4485 | cpu_to_le16(IEEE80211_STYPE_QOS_NULLFUNC); | ||
4486 | skb->priority = 7; | ||
4487 | skb_set_queue_mapping(skb, IEEE80211_AC_VO); | ||
4488 | skb_put_data(skb, &qos, sizeof(qos)); | ||
4489 | } | ||
4490 | |||
4466 | memcpy(nullfunc->addr1, ifmgd->bssid, ETH_ALEN); | 4491 | memcpy(nullfunc->addr1, ifmgd->bssid, ETH_ALEN); |
4467 | memcpy(nullfunc->addr2, vif->addr, ETH_ALEN); | 4492 | memcpy(nullfunc->addr2, vif->addr, ETH_ALEN); |
4468 | memcpy(nullfunc->addr3, ifmgd->bssid, ETH_ALEN); | 4493 | memcpy(nullfunc->addr3, ifmgd->bssid, ETH_ALEN); |