Search Linux Wireless

[PATCH 1/3] mac80211: fix - drop frames for sta with no valid rate

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



If we're associated and scanning mac80211 will allow through
nullfunc and probe request frames. When we're scanning on a
different band than the one we're associated on we should
not send nullfunc frames to the sta on that band as it would
be the incorrect band.

Lets catch the case where no valid rate is usable when associated
and discard those frames and warn only for the case the frame is
not a nullfunc or probe request as those are the only accounted
for frames mac80211 should allow through while scanning.

This fixes an oops which occured due to an assert in ath9k:

http://marc.info/?l=linux-wireless&m=124277331319024

The assert was happening because the rate control algorithm
figures it should find at least one valid dual stream or
single stream rate. Since we allow mac80211 to send get_rate
callback for drivers for a sta on invalid band no valid will
actually have been found and hence the assert.

Signed-off-by: Luis R. Rodriguez <lrodriguez@xxxxxxxxxxx>
---
 include/net/mac80211.h |   11 +++++++++++
 net/mac80211/tx.c      |   38 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 17d61d1..9559efa 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2103,6 +2103,17 @@ rate_lowest_index(struct ieee80211_supported_band *sband,
 	return 0;
 }
 
+static inline
+bool rate_usable_index_exists(struct ieee80211_supported_band *sband,
+			      struct ieee80211_sta *sta)
+{
+	unsigned int i;
+
+	for (i = 0; i < sband->n_bitrates; i++)
+		if (rate_supported(sta, sband->band, i))
+			return true;
+	return false;
+}
 
 int ieee80211_rate_control_register(struct rate_control_ops *ops);
 void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 1436f74..03f9a4e 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -511,6 +511,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
 	int i, len;
 	bool inval = false, rts = false, short_preamble = false;
 	struct ieee80211_tx_rate_control txrc;
+	u32 sta_flags;
 
 	memset(&txrc, 0, sizeof(txrc));
 
@@ -543,7 +544,44 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
 	     (tx->sta && test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))))
 		txrc.short_preamble = short_preamble = true;
 
+	sta_flags = tx->sta ? get_sta_flags(tx->sta) : 0;
+
+	/*
+	 * Lets not bother rate control if we're associated and cannot
+	 * talk to the sta. It makes little since for this to happen,
+	 * it should mean we're scanning on another band somehow some frames
+	 * got through the TX queue -- these should have been not been added
+	 * to our TX queue. There is one excemption to this, but we handle
+	 * these below.
+	 */
+
+	if (unlikely((tx->local->sw_scanning) &&
+	    (sta_flags & WLAN_STA_ASSOC) &&
+	    !rate_usable_index_exists(sband, &tx->sta->sta))) {
+		/*
+		 *  The only accounted for frames of this type in
+		 *  mac80211 are probe requests and null func frames,
+		 *  so just warn for other drop of frames. Drop the
+		 *  frames anyway as we have no usable bit rate.
+		 */
+		if (!ieee80211_is_probe_req(hdr->frame_control) &&
+		    !ieee80211_is_nullfunc(hdr->frame_control)) {
+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
+			printk(KERN_DEBUG "%s: dropped data frame -- no "
+			       "supported rate for station %pM on %c "
+			       "GHz band\n",
+			       tx->dev->name, hdr->addr1,
+			       tx->channel->band ? '5' : '2');
+			WARN_ON(1);
+#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
+		}
+		return TX_DROP;
+	}
 
+	/*
+	 * If we're associated at this point with the sta we know we can at
+	 * least send the frame at the lowest bit rate.
+	 */
 	rate_control_get_rate(tx->sdata, tx->sta, &txrc);
 
 	if (unlikely(info->control.rates[0].idx < 0))
-- 
1.6.0.6

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux