Commit a02ae758e8780d737b6d0135d6292bb3043e7eea

Authored by Johannes Berg
Committed by John W. Linville
1 parent af2ced6a32

mac80211: cleanup reorder buffer handling

The reorder buffer handling is written in a quite
peculiar style (especially comments) and also has
a quirk where it invokes the entire reorder code
in ieee80211_sta_manage_reorder_buf() for just a
handful of lines in it with a special argument.

Split out ieee80211_release_reorder_frames which
can then be invoked from BAR handling and other
reordering code, clean up code and comments and
remove function arguments that are now unused from
ieee80211_sta_manage_reorder_buf().

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

Showing 1 changed file with 81 additions and 81 deletions Side-by-side Diff

... ... @@ -27,11 +27,10 @@
27 27 #include "tkip.h"
28 28 #include "wme.h"
29 29  
30   -static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
31   - struct tid_ampdu_rx *tid_agg_rx,
32   - struct sk_buff *skb,
33   - u16 mpdu_seq_num,
34   - int bar_req);
  30 +static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw,
  31 + struct tid_ampdu_rx *tid_agg_rx,
  32 + u16 head_seq_num);
  33 +
35 34 /*
36 35 * monitor mode reception
37 36 *
38 37  
... ... @@ -1592,11 +1591,11 @@
1592 1591  
1593 1592 if (ieee80211_is_back_req(bar->frame_control)) {
1594 1593 if (!rx->sta)
1595   - return RX_CONTINUE;
  1594 + return RX_DROP_MONITOR;
1596 1595 tid = le16_to_cpu(bar->control) >> 12;
1597 1596 if (rx->sta->ampdu_mlme.tid_state_rx[tid]
1598 1597 != HT_AGG_STATE_OPERATIONAL)
1599   - return RX_CONTINUE;
  1598 + return RX_DROP_MONITOR;
1600 1599 tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid];
1601 1600  
1602 1601 start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4;
... ... @@ -1606,13 +1605,10 @@
1606 1605 mod_timer(&tid_agg_rx->session_timer,
1607 1606 TU_TO_EXP_TIME(tid_agg_rx->timeout));
1608 1607  
1609   - /* manage reordering buffer according to requested */
1610   - /* sequence number */
1611   - rcu_read_lock();
1612   - ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, NULL,
1613   - start_seq_num, 1);
1614   - rcu_read_unlock();
1615   - return RX_DROP_UNUSABLE;
  1608 + /* release stored frames up to start of BAR */
  1609 + ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num);
  1610 + kfree_skb(skb);
  1611 + return RX_QUEUED;
1616 1612 }
1617 1613  
1618 1614 return RX_CONTINUE;
1619 1615  
... ... @@ -2223,7 +2219,19 @@
2223 2219 tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
2224 2220 }
2225 2221  
  2222 +static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw,
  2223 + struct tid_ampdu_rx *tid_agg_rx,
  2224 + u16 head_seq_num)
  2225 +{
  2226 + int index;
2226 2227  
  2228 + while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) {
  2229 + index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
  2230 + tid_agg_rx->buf_size;
  2231 + ieee80211_release_reorder_frame(hw, tid_agg_rx, index);
  2232 + }
  2233 +}
  2234 +
2227 2235 /*
2228 2236 * Timeout (in jiffies) for skb's that are waiting in the RX reorder buffer. If
2229 2237 * the skb was added to the buffer longer than this time ago, the earlier
2230 2238  
2231 2239  
... ... @@ -2234,15 +2242,17 @@
2234 2242 #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10)
2235 2243  
2236 2244 /*
2237   - * As it function blongs to Rx path it must be called with
2238   - * the proper rcu_read_lock protection for its flow.
  2245 + * As this function belongs to the RX path it must be under
  2246 + * rcu_read_lock protection. It returns false if the frame
  2247 + * can be processed immediately, true if it was consumed.
2239 2248 */
2240   -static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
2241   - struct tid_ampdu_rx *tid_agg_rx,
2242   - struct sk_buff *skb,
2243   - u16 mpdu_seq_num,
2244   - int bar_req)
  2249 +static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
  2250 + struct tid_ampdu_rx *tid_agg_rx,
  2251 + struct sk_buff *skb)
2245 2252 {
  2253 + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
  2254 + u16 sc = le16_to_cpu(hdr->seq_ctrl);
  2255 + u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4;
2246 2256 u16 head_seq_num, buf_size;
2247 2257 int index;
2248 2258  
2249 2259  
2250 2260  
2251 2261  
2252 2262  
2253 2263  
2254 2264  
... ... @@ -2252,47 +2262,37 @@
2252 2262 /* frame with out of date sequence number */
2253 2263 if (seq_less(mpdu_seq_num, head_seq_num)) {
2254 2264 dev_kfree_skb(skb);
2255   - return 1;
  2265 + return true;
2256 2266 }
2257 2267  
2258   - /* if frame sequence number exceeds our buffering window size or
2259   - * block Ack Request arrived - release stored frames */
2260   - if ((!seq_less(mpdu_seq_num, head_seq_num + buf_size)) || (bar_req)) {
2261   - /* new head to the ordering buffer */
2262   - if (bar_req)
2263   - head_seq_num = mpdu_seq_num;
2264   - else
2265   - head_seq_num =
2266   - seq_inc(seq_sub(mpdu_seq_num, buf_size));
  2268 + /*
  2269 + * If frame the sequence number exceeds our buffering window
  2270 + * size release some previous frames to make room for this one.
  2271 + */
  2272 + if (!seq_less(mpdu_seq_num, head_seq_num + buf_size)) {
  2273 + head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size));
2267 2274 /* release stored frames up to new head to stack */
2268   - while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) {
2269   - index = seq_sub(tid_agg_rx->head_seq_num,
2270   - tid_agg_rx->ssn)
2271   - % tid_agg_rx->buf_size;
2272   - ieee80211_release_reorder_frame(hw, tid_agg_rx,
2273   - index);
2274   - }
2275   - if (bar_req)
2276   - return 1;
  2275 + ieee80211_release_reorder_frames(hw, tid_agg_rx, head_seq_num);
2277 2276 }
2278 2277  
2279   - /* now the new frame is always in the range of the reordering */
2280   - /* buffer window */
2281   - index = seq_sub(mpdu_seq_num, tid_agg_rx->ssn)
2282   - % tid_agg_rx->buf_size;
  2278 + /* Now the new frame is always in the range of the reordering buffer */
  2279 +
  2280 + index = seq_sub(mpdu_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size;
  2281 +
2283 2282 /* check if we already stored this frame */
2284 2283 if (tid_agg_rx->reorder_buf[index]) {
2285 2284 dev_kfree_skb(skb);
2286   - return 1;
  2285 + return true;
2287 2286 }
2288 2287  
2289   - /* if arrived mpdu is in the right order and nothing else stored */
2290   - /* release it immediately */
  2288 + /*
  2289 + * If the current MPDU is in the right order and nothing else
  2290 + * is stored we can process it directly, no need to buffer it.
  2291 + */
2291 2292 if (mpdu_seq_num == tid_agg_rx->head_seq_num &&
2292   - tid_agg_rx->stored_mpdu_num == 0) {
2293   - tid_agg_rx->head_seq_num =
2294   - seq_inc(tid_agg_rx->head_seq_num);
2295   - return 0;
  2293 + tid_agg_rx->stored_mpdu_num == 0) {
  2294 + tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
  2295 + return false;
2296 2296 }
2297 2297  
2298 2298 /* put the frame in the reordering buffer */
... ... @@ -2300,8 +2300,8 @@
2300 2300 tid_agg_rx->reorder_time[index] = jiffies;
2301 2301 tid_agg_rx->stored_mpdu_num++;
2302 2302 /* release the buffer until next missing frame */
2303   - index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn)
2304   - % tid_agg_rx->buf_size;
  2303 + index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
  2304 + tid_agg_rx->buf_size;
2305 2305 if (!tid_agg_rx->reorder_buf[index] &&
2306 2306 tid_agg_rx->stored_mpdu_num > 1) {
2307 2307 /*
2308 2308  
... ... @@ -2312,12 +2312,12 @@
2312 2312 int skipped = 1;
2313 2313 for (j = (index + 1) % tid_agg_rx->buf_size; j != index;
2314 2314 j = (j + 1) % tid_agg_rx->buf_size) {
2315   - if (tid_agg_rx->reorder_buf[j] == NULL) {
  2315 + if (!tid_agg_rx->reorder_buf[j]) {
2316 2316 skipped++;
2317 2317 continue;
2318 2318 }
2319 2319 if (!time_after(jiffies, tid_agg_rx->reorder_time[j] +
2320   - HZ / 10))
  2320 + HT_RX_REORDER_BUF_TIMEOUT))
2321 2321 break;
2322 2322  
2323 2323 #ifdef CONFIG_MAC80211_HT_DEBUG
2324 2324  
2325 2325  
2326 2326  
2327 2327  
2328 2328  
2329 2329  
2330 2330  
2331 2331  
2332 2332  
2333 2333  
... ... @@ -2333,51 +2333,56 @@
2333 2333 * Increment the head seq# also for the skipped slots.
2334 2334 */
2335 2335 tid_agg_rx->head_seq_num =
2336   - (tid_agg_rx->head_seq_num + skipped) &
2337   - SEQ_MASK;
  2336 + (tid_agg_rx->head_seq_num + skipped) & SEQ_MASK;
2338 2337 skipped = 0;
2339 2338 }
2340 2339 } else while (tid_agg_rx->reorder_buf[index]) {
2341 2340 ieee80211_release_reorder_frame(hw, tid_agg_rx, index);
2342   - index = seq_sub(tid_agg_rx->head_seq_num,
2343   - tid_agg_rx->ssn) % tid_agg_rx->buf_size;
  2341 + index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
  2342 + tid_agg_rx->buf_size;
2344 2343 }
2345   - return 1;
  2344 +
  2345 + return true;
2346 2346 }
2347 2347  
2348   -static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
2349   - struct sk_buff *skb)
  2348 +/*
  2349 + * Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns
  2350 + * true if the MPDU was buffered, false if it should be processed.
  2351 + */
  2352 +static bool ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
  2353 + struct sk_buff *skb)
2350 2354 {
2351 2355 struct ieee80211_hw *hw = &local->hw;
2352 2356 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2353 2357 struct sta_info *sta;
2354 2358 struct tid_ampdu_rx *tid_agg_rx;
2355 2359 u16 sc;
2356   - u16 mpdu_seq_num;
2357   - u8 ret = 0;
2358 2360 int tid;
2359 2361  
  2362 + if (!ieee80211_is_data_qos(hdr->frame_control))
  2363 + return false;
  2364 +
  2365 + /*
  2366 + * filter the QoS data rx stream according to
  2367 + * STA/TID and check if this STA/TID is on aggregation
  2368 + */
  2369 +
2360 2370 sta = sta_info_get(local, hdr->addr2);
2361 2371 if (!sta)
2362   - return ret;
  2372 + return false;
2363 2373  
2364   - /* filter the QoS data rx stream according to
2365   - * STA/TID and check if this STA/TID is on aggregation */
2366   - if (!ieee80211_is_data_qos(hdr->frame_control))
2367   - goto end_reorder;
2368   -
2369 2374 tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
2370 2375  
2371 2376 if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL)
2372   - goto end_reorder;
  2377 + return false;
2373 2378  
2374 2379 tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
2375 2380  
2376 2381 /* qos null data frames are excluded */
2377 2382 if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC)))
2378   - goto end_reorder;
  2383 + return false;
2379 2384  
2380   - /* new un-ordered ampdu frame - process it */
  2385 + /* new, potentially un-ordered, ampdu frame - process it */
2381 2386  
2382 2387 /* reset session timer */
2383 2388 if (tid_agg_rx->timeout)
2384 2389  
... ... @@ -2389,16 +2394,11 @@
2389 2394 if (sc & IEEE80211_SCTL_FRAG) {
2390 2395 ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr,
2391 2396 tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP);
2392   - ret = 1;
2393   - goto end_reorder;
  2397 + dev_kfree_skb(skb);
  2398 + return true;
2394 2399 }
2395 2400  
2396   - /* according to mpdu sequence number deal with reordering buffer */
2397   - mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4;
2398   - ret = ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb,
2399   - mpdu_seq_num, 0);
2400   - end_reorder:
2401   - return ret;
  2401 + return ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb);
2402 2402 }
2403 2403  
2404 2404 /*