aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <jouni.malinen@atheros.com>2009-12-29 05:59:19 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-01-12 13:50:09 -0500
commite00cfce0cb2a397859607bf515c6de9ce064b64a (patch)
tree038d87e7d90a5bcdd8f689a563221eab883b0546
parent3dc1de0bf23816ed557ac8addf680cd5ee57e805 (diff)
mac80211: Select lowest rate based on basic rate set in AP mode
If the basic rate set is configured to not include the lowest rate (e.g., basic rate set = 6, 12, 24 Mbps in IEEE 802.11g mode), the AP should not send out broadcast frames at 1 Mbps. This type of configuration can be used to optimize channel usage in cases where there is no need for backwards compatibility with IEEE 802.11b-only devices. In AP mode, mac80211 was unconditionally using the lowest rate for Beacon frames and similarly, with all rate control algorithms that use rate_control_send_low(), the lowest rate ended up being used for all broadcast frames (and all unicast frames that are sent before association). Change this to take into account the basic rate configuration in AP mode, i.e., use the lowest rate in the basic rate set instead of the lowest supported rate when selecting the rate. Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--include/net/mac80211.h2
-rw-r--r--net/mac80211/rate.c25
-rw-r--r--net/mac80211/tx.c24
3 files changed, 40 insertions, 11 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index ad4b70034e77..39c516c352be 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2299,6 +2299,7 @@ enum rate_control_changed {
2299 * @max_rate_idx: user-requested maximum rate (not MCS for now) 2299 * @max_rate_idx: user-requested maximum rate (not MCS for now)
2300 * @skb: the skb that will be transmitted, the control information in it needs 2300 * @skb: the skb that will be transmitted, the control information in it needs
2301 * to be filled in 2301 * to be filled in
2302 * @ap: whether this frame is sent out in AP mode
2302 */ 2303 */
2303struct ieee80211_tx_rate_control { 2304struct ieee80211_tx_rate_control {
2304 struct ieee80211_hw *hw; 2305 struct ieee80211_hw *hw;
@@ -2308,6 +2309,7 @@ struct ieee80211_tx_rate_control {
2308 struct ieee80211_tx_rate reported_rate; 2309 struct ieee80211_tx_rate reported_rate;
2309 bool rts, short_preamble; 2310 bool rts, short_preamble;
2310 u8 max_rate_idx; 2311 u8 max_rate_idx;
2312 bool ap;
2311}; 2313};
2312 2314
2313struct rate_control_ops { 2315struct rate_control_ops {
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index b9007f80cb92..6349e7f4dcae 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -207,6 +207,27 @@ static bool rc_no_data_or_no_ack(struct ieee80211_tx_rate_control *txrc)
207 return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc)); 207 return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc));
208} 208}
209 209
210static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, u8 max_rate_idx)
211{
212 u8 i;
213
214 if (basic_rates == 0)
215 return; /* assume basic rates unknown and accept rate */
216 if (*idx < 0)
217 return;
218 if (basic_rates & (1 << *idx))
219 return; /* selected rate is a basic rate */
220
221 for (i = *idx + 1; i <= max_rate_idx; i++) {
222 if (basic_rates & (1 << i)) {
223 *idx = i;
224 return;
225 }
226 }
227
228 /* could not find a basic rate; use original selection */
229}
230
210bool rate_control_send_low(struct ieee80211_sta *sta, 231bool rate_control_send_low(struct ieee80211_sta *sta,
211 void *priv_sta, 232 void *priv_sta,
212 struct ieee80211_tx_rate_control *txrc) 233 struct ieee80211_tx_rate_control *txrc)
@@ -218,6 +239,10 @@ bool rate_control_send_low(struct ieee80211_sta *sta,
218 info->control.rates[0].count = 239 info->control.rates[0].count =
219 (info->flags & IEEE80211_TX_CTL_NO_ACK) ? 240 (info->flags & IEEE80211_TX_CTL_NO_ACK) ?
220 1 : txrc->hw->max_rate_tries; 241 1 : txrc->hw->max_rate_tries;
242 if (!sta && txrc->ap)
243 rc_send_low_broadcast(&info->control.rates[0].idx,
244 txrc->bss_conf->basic_rates,
245 txrc->sband->n_bitrates);
221 return true; 246 return true;
222 } 247 }
223 return false; 248 return false;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 140da4a7f13d..4961168f5091 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -520,6 +520,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
520 txrc.skb = tx->skb; 520 txrc.skb = tx->skb;
521 txrc.reported_rate.idx = -1; 521 txrc.reported_rate.idx = -1;
522 txrc.max_rate_idx = tx->sdata->max_ratectrl_rateidx; 522 txrc.max_rate_idx = tx->sdata->max_ratectrl_rateidx;
523 txrc.ap = tx->sdata->vif.type == NL80211_IFTYPE_AP;
523 524
524 /* set up RTS protection if desired */ 525 /* set up RTS protection if desired */
525 if (len > tx->local->hw.wiphy->rts_threshold) { 526 if (len > tx->local->hw.wiphy->rts_threshold) {
@@ -2060,6 +2061,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
2060 struct beacon_data *beacon; 2061 struct beacon_data *beacon;
2061 struct ieee80211_supported_band *sband; 2062 struct ieee80211_supported_band *sband;
2062 enum ieee80211_band band = local->hw.conf.channel->band; 2063 enum ieee80211_band band = local->hw.conf.channel->band;
2064 struct ieee80211_tx_rate_control txrc;
2063 2065
2064 sband = local->hw.wiphy->bands[band]; 2066 sband = local->hw.wiphy->bands[band];
2065 2067
@@ -2167,21 +2169,21 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
2167 info = IEEE80211_SKB_CB(skb); 2169 info = IEEE80211_SKB_CB(skb);
2168 2170
2169 info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; 2171 info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
2172 info->flags |= IEEE80211_TX_CTL_NO_ACK;
2170 info->band = band; 2173 info->band = band;
2171 /* 2174
2172 * XXX: For now, always use the lowest rate 2175 memset(&txrc, 0, sizeof(txrc));
2173 */ 2176 txrc.hw = hw;
2174 info->control.rates[0].idx = 0; 2177 txrc.sband = sband;
2175 info->control.rates[0].count = 1; 2178 txrc.bss_conf = &sdata->vif.bss_conf;
2176 info->control.rates[1].idx = -1; 2179 txrc.skb = skb;
2177 info->control.rates[2].idx = -1; 2180 txrc.reported_rate.idx = -1;
2178 info->control.rates[3].idx = -1; 2181 txrc.max_rate_idx = sdata->max_ratectrl_rateidx;
2179 info->control.rates[4].idx = -1; 2182 txrc.ap = true;
2180 BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 5); 2183 rate_control_get_rate(sdata, NULL, &txrc);
2181 2184
2182 info->control.vif = vif; 2185 info->control.vif = vif;
2183 2186
2184 info->flags |= IEEE80211_TX_CTL_NO_ACK;
2185 info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; 2187 info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
2186 info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; 2188 info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
2187 out: 2189 out: