aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
authorJouni Malinen <jouni.malinen@atheros.com>2009-05-05 13:35:14 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-05-06 15:15:04 -0400
commit4d050f1daed3babf6fcc337f862a245d31af4452 (patch)
treeea684e5168772b822fdb0bd162378fd252227f3c /net/mac80211/rx.c
parent2d3babd11f91501f49c6af212e6795bd8954f4d4 (diff)
mac80211: Add a timeout for frames in the RX reorder buffer
This patch allows skbs to be released from the RX reorder buffer in case they have been there for an unexpectedly long time without us having received the missing frames before them. Previously, these frames were only released when the reorder window moved and that could take very long time unless new frames were received constantly (e.g., TCP connections could be killed more or less indefinitely). This situation should not happen very frequently, but it looks like there are some scenarious that trigger it for some reason. As such, this should be considered mostly a workaround to speed up recovery from unexpected siutation that could result in connections hanging for long periods of time. The changes here will only check for timeout situation when adding new RX frames to the reorder buffer. It does not handle all possible cases, but seems to help for most cases that could result from common network usage (e.g., TCP retrying at least couple of times). For more completely coverage, a timer could be used to periodically check whether there are any frames remaining in the reorder buffer if no new frames are received. Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 9f2a29d1890b..24d41705ac0b 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2313,6 +2313,15 @@ no_frame:
2313 2313
2314 2314
2315/* 2315/*
2316 * Timeout (in jiffies) for skb's that are waiting in the RX reorder buffer. If
2317 * the skb was added to the buffer longer than this time ago, the earlier
2318 * frames that have not yet been received are assumed to be lost and the skb
2319 * can be released for processing. This may also release other skb's from the
2320 * reorder buffer if there are no additional gaps between the frames.
2321 */
2322#define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10)
2323
2324/*
2316 * As it function blongs to Rx path it must be called with 2325 * As it function blongs to Rx path it must be called with
2317 * the proper rcu_read_lock protection for its flow. 2326 * the proper rcu_read_lock protection for its flow.
2318 */ 2327 */
@@ -2377,13 +2386,49 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
2377 2386
2378 /* put the frame in the reordering buffer */ 2387 /* put the frame in the reordering buffer */
2379 tid_agg_rx->reorder_buf[index] = skb; 2388 tid_agg_rx->reorder_buf[index] = skb;
2389 tid_agg_rx->reorder_time[index] = jiffies;
2380 memcpy(tid_agg_rx->reorder_buf[index]->cb, rxstatus, 2390 memcpy(tid_agg_rx->reorder_buf[index]->cb, rxstatus,
2381 sizeof(*rxstatus)); 2391 sizeof(*rxstatus));
2382 tid_agg_rx->stored_mpdu_num++; 2392 tid_agg_rx->stored_mpdu_num++;
2383 /* release the buffer until next missing frame */ 2393 /* release the buffer until next missing frame */
2384 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) 2394 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn)
2385 % tid_agg_rx->buf_size; 2395 % tid_agg_rx->buf_size;
2386 while (tid_agg_rx->reorder_buf[index]) { 2396 if (!tid_agg_rx->reorder_buf[index] &&
2397 tid_agg_rx->stored_mpdu_num > 1) {
2398 /*
2399 * No buffers ready to be released, but check whether any
2400 * frames in the reorder buffer have timed out.
2401 */
2402 int j;
2403 int skipped = 1;
2404 for (j = (index + 1) % tid_agg_rx->buf_size; j != index;
2405 j = (j + 1) % tid_agg_rx->buf_size) {
2406 if (tid_agg_rx->reorder_buf[j] == NULL) {
2407 skipped++;
2408 continue;
2409 }
2410 if (!time_after(jiffies, tid_agg_rx->reorder_time[j] +
2411 HZ / 10))
2412 break;
2413
2414#ifdef CONFIG_MAC80211_HT_DEBUG
2415 if (net_ratelimit())
2416 printk(KERN_DEBUG "%s: release an RX reorder "
2417 "frame due to timeout on earlier "
2418 "frames\n",
2419 wiphy_name(hw->wiphy));
2420#endif
2421 ieee80211_release_reorder_frame(hw, tid_agg_rx, j);
2422
2423 /*
2424 * Increment the head seq# also for the skipped slots.
2425 */
2426 tid_agg_rx->head_seq_num =
2427 (tid_agg_rx->head_seq_num + skipped) &
2428 SEQ_MASK;
2429 skipped = 0;
2430 }
2431 } else while (tid_agg_rx->reorder_buf[index]) {
2387 ieee80211_release_reorder_frame(hw, tid_agg_rx, index); 2432 ieee80211_release_reorder_frame(hw, tid_agg_rx, index);
2388 index = seq_sub(tid_agg_rx->head_seq_num, 2433 index = seq_sub(tid_agg_rx->head_seq_num,
2389 tid_agg_rx->ssn) % tid_agg_rx->buf_size; 2434 tid_agg_rx->ssn) % tid_agg_rx->buf_size;