mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									01a95b2141
								
							
						
					
					
						commit
						7b6ddeaf27
					
				
					 7 changed files with 42 additions and 10 deletions
				
			
		| 
						 | 
				
			
			@ -1113,7 +1113,7 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp,
 | 
			
		|||
		if (!avp->assoc)
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
		skb = ieee80211_nullfunc_get(sc->hw, vif);
 | 
			
		||||
		skb = ieee80211_nullfunc_get(sc->hw, vif, false);
 | 
			
		||||
		if (!skb)
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -198,7 +198,7 @@ void __cw1200_cqm_bssloss_sm(struct cw1200_common *priv,
 | 
			
		|||
 | 
			
		||||
		priv->bss_loss_state++;
 | 
			
		||||
 | 
			
		||||
		skb = ieee80211_nullfunc_get(priv->hw, priv->vif);
 | 
			
		||||
		skb = ieee80211_nullfunc_get(priv->hw, priv->vif, false);
 | 
			
		||||
		WARN_ON(!skb);
 | 
			
		||||
		if (skb)
 | 
			
		||||
			cw1200_tx(priv->hw, NULL, skb);
 | 
			
		||||
| 
						 | 
				
			
			@ -2265,7 +2265,7 @@ static int cw1200_upload_null(struct cw1200_common *priv)
 | 
			
		|||
		.rate = 0xFF,
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	frame.skb = ieee80211_nullfunc_get(priv->hw, priv->vif);
 | 
			
		||||
	frame.skb = ieee80211_nullfunc_get(priv->hw, priv->vif, false);
 | 
			
		||||
	if (!frame.skb)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -566,7 +566,7 @@ static int wl1251_build_null_data(struct wl1251 *wl)
 | 
			
		|||
		size = sizeof(struct wl12xx_null_data_template);
 | 
			
		||||
		ptr = NULL;
 | 
			
		||||
	} else {
 | 
			
		||||
		skb = ieee80211_nullfunc_get(wl->hw, wl->vif);
 | 
			
		||||
		skb = ieee80211_nullfunc_get(wl->hw, wl->vif, false);
 | 
			
		||||
		if (!skb)
 | 
			
		||||
			goto out;
 | 
			
		||||
		size = skb->len;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1069,7 +1069,8 @@ int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 | 
			
		|||
		ptr = NULL;
 | 
			
		||||
	} else {
 | 
			
		||||
		skb = ieee80211_nullfunc_get(wl->hw,
 | 
			
		||||
					     wl12xx_wlvif_to_vif(wlvif));
 | 
			
		||||
					     wl12xx_wlvif_to_vif(wlvif),
 | 
			
		||||
					     false);
 | 
			
		||||
		if (!skb)
 | 
			
		||||
			goto out;
 | 
			
		||||
		size = skb->len;
 | 
			
		||||
| 
						 | 
				
			
			@ -1096,7 +1097,7 @@ int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl,
 | 
			
		|||
	struct sk_buff *skb = NULL;
 | 
			
		||||
	int ret = -ENOMEM;
 | 
			
		||||
 | 
			
		||||
	skb = ieee80211_nullfunc_get(wl->hw, vif);
 | 
			
		||||
	skb = ieee80211_nullfunc_get(wl->hw, vif, false);
 | 
			
		||||
	if (!skb)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4470,18 +4470,24 @@ struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
 | 
			
		|||
 * ieee80211_nullfunc_get - retrieve a nullfunc template
 | 
			
		||||
 * @hw: pointer obtained from ieee80211_alloc_hw().
 | 
			
		||||
 * @vif: &struct ieee80211_vif pointer from the add_interface callback.
 | 
			
		||||
 * @qos_ok: QoS NDP is acceptable to the caller, this should be set
 | 
			
		||||
 *	if at all possible
 | 
			
		||||
 *
 | 
			
		||||
 * Creates a Nullfunc template which can, for example, uploaded to
 | 
			
		||||
 * hardware. The template must be updated after association so that correct
 | 
			
		||||
 * BSSID and address is used.
 | 
			
		||||
 *
 | 
			
		||||
 * If @qos_ndp is set and the association is to an AP with QoS/WMM, the
 | 
			
		||||
 * returned packet will be QoS NDP.
 | 
			
		||||
 *
 | 
			
		||||
 * Note: Caller (or hardware) is responsible for setting the
 | 
			
		||||
 * &IEEE80211_FCTL_PM bit as well as Duration and Sequence Control fields.
 | 
			
		||||
 *
 | 
			
		||||
 * Return: The nullfunc template. %NULL on error.
 | 
			
		||||
 */
 | 
			
		||||
struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
 | 
			
		||||
				       struct ieee80211_vif *vif);
 | 
			
		||||
				       struct ieee80211_vif *vif,
 | 
			
		||||
				       bool qos_ok);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ieee80211_probereq_get - retrieve a Probe Request template
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -895,7 +895,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local,
 | 
			
		|||
	struct ieee80211_hdr_3addr *nullfunc;
 | 
			
		||||
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 | 
			
		||||
 | 
			
		||||
	skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif);
 | 
			
		||||
	skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif, true);
 | 
			
		||||
	if (!skb)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4438,13 +4438,15 @@ struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
 | 
			
		|||
EXPORT_SYMBOL(ieee80211_pspoll_get);
 | 
			
		||||
 | 
			
		||||
struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
 | 
			
		||||
				       struct ieee80211_vif *vif)
 | 
			
		||||
				       struct ieee80211_vif *vif,
 | 
			
		||||
				       bool qos_ok)
 | 
			
		||||
{
 | 
			
		||||
	struct ieee80211_hdr_3addr *nullfunc;
 | 
			
		||||
	struct ieee80211_sub_if_data *sdata;
 | 
			
		||||
	struct ieee80211_if_managed *ifmgd;
 | 
			
		||||
	struct ieee80211_local *local;
 | 
			
		||||
	struct sk_buff *skb;
 | 
			
		||||
	bool qos = false;
 | 
			
		||||
 | 
			
		||||
	if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
 | 
			
		||||
		return NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -4453,7 +4455,17 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
 | 
			
		|||
	ifmgd = &sdata->u.mgd;
 | 
			
		||||
	local = sdata->local;
 | 
			
		||||
 | 
			
		||||
	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*nullfunc));
 | 
			
		||||
	if (qos_ok) {
 | 
			
		||||
		struct sta_info *sta;
 | 
			
		||||
 | 
			
		||||
		rcu_read_lock();
 | 
			
		||||
		sta = sta_info_get(sdata, ifmgd->bssid);
 | 
			
		||||
		qos = sta && sta->sta.wme;
 | 
			
		||||
		rcu_read_unlock();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
 | 
			
		||||
			    sizeof(*nullfunc) + 2);
 | 
			
		||||
	if (!skb)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4463,6 +4475,19 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
 | 
			
		|||
	nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
 | 
			
		||||
					      IEEE80211_STYPE_NULLFUNC |
 | 
			
		||||
					      IEEE80211_FCTL_TODS);
 | 
			
		||||
	if (qos) {
 | 
			
		||||
		__le16 qos = cpu_to_le16(7);
 | 
			
		||||
 | 
			
		||||
		BUILD_BUG_ON((IEEE80211_STYPE_QOS_NULLFUNC |
 | 
			
		||||
			      IEEE80211_STYPE_NULLFUNC) !=
 | 
			
		||||
			     IEEE80211_STYPE_QOS_NULLFUNC);
 | 
			
		||||
		nullfunc->frame_control |=
 | 
			
		||||
			cpu_to_le16(IEEE80211_STYPE_QOS_NULLFUNC);
 | 
			
		||||
		skb->priority = 7;
 | 
			
		||||
		skb_set_queue_mapping(skb, IEEE80211_AC_VO);
 | 
			
		||||
		skb_put_data(skb, &qos, sizeof(qos));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memcpy(nullfunc->addr1, ifmgd->bssid, ETH_ALEN);
 | 
			
		||||
	memcpy(nullfunc->addr2, vif->addr, ETH_ALEN);
 | 
			
		||||
	memcpy(nullfunc->addr3, ifmgd->bssid, ETH_ALEN);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue