diff options
author | Daniel Drake <dsd@gentoo.org> | 2006-05-01 17:45:50 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2006-05-05 17:10:41 -0400 |
commit | 8462fe3cd9ec8951871a20a4dfe36321ab075964 (patch) | |
tree | 8b3c6db6091ee99b4791a911734229181ef6f473 | |
parent | 461c078c9cdfc1d24a436a87daed90f18c3b0d0d (diff) |
[PATCH] softmac: suggest per-frame-type TX rate
This patch is the first step towards rate control inside softmac.
The txrates substructure has been extended to provide
different fields for different types of packets (management/data,
unicast/multicast). These fields are updated on association to values
compatible with the access point we are associating to.
Drivers can then use the new ieee80211softmac_suggest_txrate() function
call when deciding which rate to transmit each frame at. This is
immensely useful for ZD1211, and bcm can use it too.
The user can still specify a rate through iwconfig, which is matched
for all transmissions (assuming the rate they have specified is in
the rate set required by the AP).
At a later date, we can incorporate automatic rate management into
the ieee80211softmac_recalc_txrates() function.
This patch also removes the mcast_fallback field. Sam Leffler pointed
out that this field is meaningless, because no driver will ever be
retransmitting mcast frames (they are not acked).
Signed-off-by: Daniel Drake <dsd@gentoo.org>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | include/net/ieee80211softmac.h | 38 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_assoc.c | 19 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_module.c | 117 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_priv.h | 3 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_wx.c | 4 |
5 files changed, 141 insertions, 40 deletions
diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h index 052ed596a4e4..703463a8828b 100644 --- a/include/net/ieee80211softmac.h +++ b/include/net/ieee80211softmac.h | |||
@@ -86,6 +86,9 @@ struct ieee80211softmac_assoc_info { | |||
86 | 86 | ||
87 | /* BSSID we're trying to associate to */ | 87 | /* BSSID we're trying to associate to */ |
88 | char bssid[ETH_ALEN]; | 88 | char bssid[ETH_ALEN]; |
89 | |||
90 | /* Rates supported by the network */ | ||
91 | struct ieee80211softmac_ratesinfo supported_rates; | ||
89 | 92 | ||
90 | /* some flags. | 93 | /* some flags. |
91 | * static_essid is valid if the essid is constant, | 94 | * static_essid is valid if the essid is constant, |
@@ -132,23 +135,26 @@ enum { | |||
132 | struct ieee80211softmac_txrates { | 135 | struct ieee80211softmac_txrates { |
133 | /* The Bit-Rate to be used for multicast frames. */ | 136 | /* The Bit-Rate to be used for multicast frames. */ |
134 | u8 mcast_rate; | 137 | u8 mcast_rate; |
135 | /* The Bit-Rate to be used for multicast fallback | 138 | |
136 | * (If the device supports fallback and hardware-retry) | 139 | /* The Bit-Rate to be used for multicast management frames. */ |
137 | */ | 140 | u8 mgt_mcast_rate; |
138 | u8 mcast_fallback; | 141 | |
139 | /* The Bit-Rate to be used for any other (normal) data packet. */ | 142 | /* The Bit-Rate to be used for any other (normal) data packet. */ |
140 | u8 default_rate; | 143 | u8 default_rate; |
141 | /* The Bit-Rate to be used for default fallback | 144 | /* The Bit-Rate to be used for default fallback |
142 | * (If the device supports fallback and hardware-retry) | 145 | * (If the device supports fallback and hardware-retry) |
143 | */ | 146 | */ |
144 | u8 default_fallback; | 147 | u8 default_fallback; |
148 | |||
149 | /* This is the rate that the user asked for */ | ||
150 | u8 user_rate; | ||
145 | }; | 151 | }; |
146 | 152 | ||
147 | /* Bits for txrates_change callback. */ | 153 | /* Bits for txrates_change callback. */ |
148 | #define IEEE80211SOFTMAC_TXRATECHG_DEFAULT (1 << 0) /* default_rate */ | 154 | #define IEEE80211SOFTMAC_TXRATECHG_DEFAULT (1 << 0) /* default_rate */ |
149 | #define IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK (1 << 1) /* default_fallback */ | 155 | #define IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK (1 << 1) /* default_fallback */ |
150 | #define IEEE80211SOFTMAC_TXRATECHG_MCAST (1 << 2) /* mcast_rate */ | 156 | #define IEEE80211SOFTMAC_TXRATECHG_MCAST (1 << 2) /* mcast_rate */ |
151 | #define IEEE80211SOFTMAC_TXRATECHG_MCAST_FBACK (1 << 3) /* mcast_fallback */ | 157 | #define IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST (1 << 3) /* mgt_mcast_rate */ |
152 | 158 | ||
153 | struct ieee80211softmac_device { | 159 | struct ieee80211softmac_device { |
154 | /* 802.11 structure for data stuff */ | 160 | /* 802.11 structure for data stuff */ |
@@ -250,6 +256,28 @@ extern void ieee80211softmac_fragment_lost(struct net_device *dev, | |||
250 | * Note that the rates need to be sorted. */ | 256 | * Note that the rates need to be sorted. */ |
251 | extern void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates); | 257 | extern void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates); |
252 | 258 | ||
259 | /* Helper function which advises you the rate at which a frame should be | ||
260 | * transmitted at. */ | ||
261 | static inline u8 ieee80211softmac_suggest_txrate(struct ieee80211softmac_device *mac, | ||
262 | int is_multicast, | ||
263 | int is_mgt) | ||
264 | { | ||
265 | struct ieee80211softmac_txrates *txrates = &mac->txrates; | ||
266 | |||
267 | if (!mac->associated) | ||
268 | return txrates->mgt_mcast_rate; | ||
269 | |||
270 | /* We are associated, sending unicast frame */ | ||
271 | if (!is_multicast) | ||
272 | return txrates->default_rate; | ||
273 | |||
274 | /* We are associated, sending multicast frame */ | ||
275 | if (is_mgt) | ||
276 | return txrates->mgt_mcast_rate; | ||
277 | else | ||
278 | return txrates->mcast_rate; | ||
279 | } | ||
280 | |||
253 | /* Start the SoftMAC. Call this after you initialized the device | 281 | /* Start the SoftMAC. Call this after you initialized the device |
254 | * and it is ready to run. | 282 | * and it is ready to run. |
255 | */ | 283 | */ |
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c index 01f21334767c..5d90b9a6ee50 100644 --- a/net/ieee80211/softmac/ieee80211softmac_assoc.c +++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c | |||
@@ -96,6 +96,7 @@ ieee80211softmac_disassoc(struct ieee80211softmac_device *mac) | |||
96 | mac->associated = 0; | 96 | mac->associated = 0; |
97 | mac->associnfo.bssvalid = 0; | 97 | mac->associnfo.bssvalid = 0; |
98 | mac->associnfo.associating = 0; | 98 | mac->associnfo.associating = 0; |
99 | ieee80211softmac_init_txrates(mac); | ||
99 | ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL); | 100 | ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL); |
100 | spin_unlock_irqrestore(&mac->lock, flags); | 101 | spin_unlock_irqrestore(&mac->lock, flags); |
101 | } | 102 | } |
@@ -118,24 +119,15 @@ ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reas | |||
118 | static inline int | 119 | static inline int |
119 | we_support_all_basic_rates(struct ieee80211softmac_device *mac, u8 *from, u8 from_len) | 120 | we_support_all_basic_rates(struct ieee80211softmac_device *mac, u8 *from, u8 from_len) |
120 | { | 121 | { |
121 | int idx, search, found; | 122 | int idx; |
122 | u8 rate, search_rate; | 123 | u8 rate; |
123 | 124 | ||
124 | for (idx = 0; idx < (from_len); idx++) { | 125 | for (idx = 0; idx < (from_len); idx++) { |
125 | rate = (from)[idx]; | 126 | rate = (from)[idx]; |
126 | if (!(rate & IEEE80211_BASIC_RATE_MASK)) | 127 | if (!(rate & IEEE80211_BASIC_RATE_MASK)) |
127 | continue; | 128 | continue; |
128 | found = 0; | ||
129 | rate &= ~IEEE80211_BASIC_RATE_MASK; | 129 | rate &= ~IEEE80211_BASIC_RATE_MASK; |
130 | for (search = 0; search < mac->ratesinfo.count; search++) { | 130 | if (!ieee80211softmac_ratesinfo_rate_supported(&mac->ratesinfo, rate)) |
131 | search_rate = mac->ratesinfo.rates[search]; | ||
132 | search_rate &= ~IEEE80211_BASIC_RATE_MASK; | ||
133 | if (rate == search_rate) { | ||
134 | found = 1; | ||
135 | break; | ||
136 | } | ||
137 | } | ||
138 | if (!found) | ||
139 | return 0; | 131 | return 0; |
140 | } | 132 | } |
141 | return 1; | 133 | return 1; |
@@ -310,6 +302,9 @@ ieee80211softmac_associated(struct ieee80211softmac_device *mac, | |||
310 | struct ieee80211softmac_network *net) | 302 | struct ieee80211softmac_network *net) |
311 | { | 303 | { |
312 | mac->associnfo.associating = 0; | 304 | mac->associnfo.associating = 0; |
305 | mac->associnfo.supported_rates = net->supported_rates; | ||
306 | ieee80211softmac_recalc_txrates(mac); | ||
307 | |||
313 | mac->associated = 1; | 308 | mac->associated = 1; |
314 | if (mac->set_bssid_filter) | 309 | if (mac->set_bssid_filter) |
315 | mac->set_bssid_filter(mac->dev, net->bssid); | 310 | mac->set_bssid_filter(mac->dev, net->bssid); |
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c index 6252be2c0db9..4b2e57d12418 100644 --- a/net/ieee80211/softmac/ieee80211softmac_module.c +++ b/net/ieee80211/softmac/ieee80211softmac_module.c | |||
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | #include "ieee80211softmac_priv.h" | 27 | #include "ieee80211softmac_priv.h" |
28 | #include <linux/sort.h> | 28 | #include <linux/sort.h> |
29 | #include <linux/etherdevice.h> | ||
29 | 30 | ||
30 | struct net_device *alloc_ieee80211softmac(int sizeof_priv) | 31 | struct net_device *alloc_ieee80211softmac(int sizeof_priv) |
31 | { | 32 | { |
@@ -61,14 +62,6 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv) | |||
61 | softmac->wait_for_scan = ieee80211softmac_wait_for_scan_implementation; | 62 | softmac->wait_for_scan = ieee80211softmac_wait_for_scan_implementation; |
62 | softmac->stop_scan = ieee80211softmac_stop_scan_implementation; | 63 | softmac->stop_scan = ieee80211softmac_stop_scan_implementation; |
63 | 64 | ||
64 | //TODO: The mcast rate has to be assigned dynamically somewhere (in scanning, association. Not sure...) | ||
65 | // It has to be set to the highest rate all stations in the current network can handle. | ||
66 | softmac->txrates.mcast_rate = IEEE80211_CCK_RATE_1MB; | ||
67 | softmac->txrates.mcast_fallback = IEEE80211_CCK_RATE_1MB; | ||
68 | /* This is reassigned in ieee80211softmac_start to sane values. */ | ||
69 | softmac->txrates.default_rate = IEEE80211_CCK_RATE_1MB; | ||
70 | softmac->txrates.default_fallback = IEEE80211_CCK_RATE_1MB; | ||
71 | |||
72 | /* to start with, we can't send anything ... */ | 65 | /* to start with, we can't send anything ... */ |
73 | netif_carrier_off(dev); | 66 | netif_carrier_off(dev); |
74 | 67 | ||
@@ -170,15 +163,82 @@ static void ieee80211softmac_start_check_rates(struct ieee80211softmac_device *m | |||
170 | } | 163 | } |
171 | } | 164 | } |
172 | 165 | ||
173 | void ieee80211softmac_start(struct net_device *dev) | 166 | int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate) |
167 | { | ||
168 | int search; | ||
169 | u8 search_rate; | ||
170 | |||
171 | for (search = 0; search < ri->count; search++) { | ||
172 | search_rate = ri->rates[search]; | ||
173 | search_rate &= ~IEEE80211_BASIC_RATE_MASK; | ||
174 | if (rate == search_rate) | ||
175 | return 1; | ||
176 | } | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | /* Finds the highest rate which is: | ||
182 | * 1. Present in ri (optionally a basic rate) | ||
183 | * 2. Supported by the device | ||
184 | * 3. Less than or equal to the user-defined rate | ||
185 | */ | ||
186 | static u8 highest_supported_rate(struct ieee80211softmac_device *mac, | ||
187 | struct ieee80211softmac_ratesinfo *ri, int basic_only) | ||
188 | { | ||
189 | u8 user_rate = mac->txrates.user_rate; | ||
190 | int i; | ||
191 | |||
192 | if (ri->count == 0) { | ||
193 | dprintk(KERN_ERR PFX "empty ratesinfo?\n"); | ||
194 | return IEEE80211_CCK_RATE_1MB; | ||
195 | } | ||
196 | |||
197 | for (i = ri->count - 1; i >= 0; i--) { | ||
198 | u8 rate = ri->rates[i]; | ||
199 | if (basic_only && !(rate & IEEE80211_BASIC_RATE_MASK)) | ||
200 | continue; | ||
201 | rate &= ~IEEE80211_BASIC_RATE_MASK; | ||
202 | if (rate > user_rate) | ||
203 | continue; | ||
204 | if (ieee80211softmac_ratesinfo_rate_supported(&mac->ratesinfo, rate)) | ||
205 | return rate; | ||
206 | } | ||
207 | |||
208 | /* If we haven't found a suitable rate by now, just trust the user */ | ||
209 | return user_rate; | ||
210 | } | ||
211 | |||
212 | void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac) | ||
213 | { | ||
214 | struct ieee80211softmac_txrates *txrates = &mac->txrates; | ||
215 | struct ieee80211softmac_txrates oldrates; | ||
216 | u32 change = 0; | ||
217 | |||
218 | if (mac->txrates_change) | ||
219 | oldrates = mac->txrates; | ||
220 | |||
221 | change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; | ||
222 | txrates->default_rate = highest_supported_rate(mac, &mac->associnfo.supported_rates, 0); | ||
223 | |||
224 | change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK; | ||
225 | txrates->default_fallback = lower_rate(mac, txrates->default_rate); | ||
226 | |||
227 | change |= IEEE80211SOFTMAC_TXRATECHG_MCAST; | ||
228 | txrates->mcast_rate = highest_supported_rate(mac, &mac->associnfo.supported_rates, 1); | ||
229 | |||
230 | if (mac->txrates_change) | ||
231 | mac->txrates_change(mac->dev, change, &oldrates); | ||
232 | |||
233 | } | ||
234 | |||
235 | void ieee80211softmac_init_txrates(struct ieee80211softmac_device *mac) | ||
174 | { | 236 | { |
175 | struct ieee80211softmac_device *mac = ieee80211_priv(dev); | ||
176 | struct ieee80211_device *ieee = mac->ieee; | 237 | struct ieee80211_device *ieee = mac->ieee; |
177 | u32 change = 0; | 238 | u32 change = 0; |
239 | struct ieee80211softmac_txrates *txrates = &mac->txrates; | ||
178 | struct ieee80211softmac_txrates oldrates; | 240 | struct ieee80211softmac_txrates oldrates; |
179 | 241 | ||
180 | ieee80211softmac_start_check_rates(mac); | ||
181 | |||
182 | /* TODO: We need some kind of state machine to lower the default rates | 242 | /* TODO: We need some kind of state machine to lower the default rates |
183 | * if we loose too many packets. | 243 | * if we loose too many packets. |
184 | */ | 244 | */ |
@@ -193,22 +253,37 @@ void ieee80211softmac_start(struct net_device *dev) | |||
193 | more reliable. Note similar logic in | 253 | more reliable. Note similar logic in |
194 | ieee80211softmac_wx_set_rate() */ | 254 | ieee80211softmac_wx_set_rate() */ |
195 | if (ieee->modulation & IEEE80211_CCK_MODULATION) { | 255 | if (ieee->modulation & IEEE80211_CCK_MODULATION) { |
196 | mac->txrates.default_rate = IEEE80211_CCK_RATE_11MB; | 256 | txrates->user_rate = IEEE80211_CCK_RATE_11MB; |
197 | change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; | ||
198 | mac->txrates.default_fallback = IEEE80211_CCK_RATE_5MB; | ||
199 | change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK; | ||
200 | } else if (ieee->modulation & IEEE80211_OFDM_MODULATION) { | 257 | } else if (ieee->modulation & IEEE80211_OFDM_MODULATION) { |
201 | mac->txrates.default_rate = IEEE80211_OFDM_RATE_54MB; | 258 | txrates->user_rate = IEEE80211_OFDM_RATE_54MB; |
202 | change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; | ||
203 | mac->txrates.default_fallback = IEEE80211_OFDM_RATE_24MB; | ||
204 | change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK; | ||
205 | } else | 259 | } else |
206 | assert(0); | 260 | assert(0); |
261 | |||
262 | txrates->default_rate = IEEE80211_CCK_RATE_1MB; | ||
263 | change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; | ||
264 | |||
265 | txrates->default_fallback = IEEE80211_CCK_RATE_1MB; | ||
266 | change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK; | ||
267 | |||
268 | txrates->mcast_rate = IEEE80211_CCK_RATE_1MB; | ||
269 | change |= IEEE80211SOFTMAC_TXRATECHG_MCAST; | ||
270 | |||
271 | txrates->mgt_mcast_rate = IEEE80211_CCK_RATE_1MB; | ||
272 | change |= IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST; | ||
273 | |||
207 | if (mac->txrates_change) | 274 | if (mac->txrates_change) |
208 | mac->txrates_change(dev, change, &oldrates); | 275 | mac->txrates_change(mac->dev, change, &oldrates); |
209 | 276 | ||
210 | mac->running = 1; | 277 | mac->running = 1; |
211 | } | 278 | } |
279 | |||
280 | void ieee80211softmac_start(struct net_device *dev) | ||
281 | { | ||
282 | struct ieee80211softmac_device *mac = ieee80211_priv(dev); | ||
283 | |||
284 | ieee80211softmac_start_check_rates(mac); | ||
285 | ieee80211softmac_init_txrates(mac); | ||
286 | } | ||
212 | EXPORT_SYMBOL_GPL(ieee80211softmac_start); | 287 | EXPORT_SYMBOL_GPL(ieee80211softmac_start); |
213 | 288 | ||
214 | void ieee80211softmac_stop(struct net_device *dev) | 289 | void ieee80211softmac_stop(struct net_device *dev) |
diff --git a/net/ieee80211/softmac/ieee80211softmac_priv.h b/net/ieee80211/softmac/ieee80211softmac_priv.h index 5de0abf157e3..fa1f8e3acfc0 100644 --- a/net/ieee80211/softmac/ieee80211softmac_priv.h +++ b/net/ieee80211/softmac/ieee80211softmac_priv.h | |||
@@ -116,7 +116,10 @@ ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac, | |||
116 | struct ieee80211softmac_essid *essid); | 116 | struct ieee80211softmac_essid *essid); |
117 | 117 | ||
118 | /* Rates related */ | 118 | /* Rates related */ |
119 | int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate); | ||
119 | u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta); | 120 | u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta); |
121 | void ieee80211softmac_init_txrates(struct ieee80211softmac_device *mac); | ||
122 | void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac); | ||
120 | static inline u8 lower_rate(struct ieee80211softmac_device *mac, u8 rate) { | 123 | static inline u8 lower_rate(struct ieee80211softmac_device *mac, u8 rate) { |
121 | return ieee80211softmac_lower_rate_delta(mac, rate, 1); | 124 | return ieee80211softmac_lower_rate_delta(mac, rate, 1); |
122 | } | 125 | } |
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c index b7d83cd4d56c..22aa6199185b 100644 --- a/net/ieee80211/softmac/ieee80211softmac_wx.c +++ b/net/ieee80211/softmac/ieee80211softmac_wx.c | |||
@@ -211,8 +211,8 @@ ieee80211softmac_wx_set_rate(struct net_device *net_dev, | |||
211 | if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION)) | 211 | if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION)) |
212 | goto out_unlock; | 212 | goto out_unlock; |
213 | 213 | ||
214 | mac->txrates.default_rate = rate; | 214 | mac->txrates.user_rate = rate; |
215 | mac->txrates.default_fallback = lower_rate(mac, rate); | 215 | ieee80211softmac_recalc_txrates(mac); |
216 | err = 0; | 216 | err = 0; |
217 | 217 | ||
218 | out_unlock: | 218 | out_unlock: |