Commit 8acbea61 authored by Paul Stewart's avatar Paul Stewart Committed by John W. Linville

mwifiex: Track BA sequence number reset

Some stations reset the sequence number for traffic-ids (TIDs)
as they initiate a block-ACK session.  In order to detect such
behavior, mwifiex must note the starting sequence number given
during the ADDBA request.  If the first received sequence number
after the ADDBA falls outside the receive window for this TID but
after the the ADDBA starting sequence number, we can assume that
this AP has reset its sequence number during the ADDBA.  In this
case we must adjust the input window backward to incorporate this
received sequence number instead of ignoring it.  Otherwise, we
could fail to successfully retrieve an arbitrarily large number
of downstream frames at the beginning of the block-ACK session.
Signed-off-by: default avatarPaul Stewart <pstew@chromium.org>
Acked-by: default avatarBing Zhao <bzhao@marvell.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent b6a8cf2c
......@@ -279,6 +279,8 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
new_node->tid = tid;
memcpy(new_node->ta, ta, ETH_ALEN);
new_node->start_win = seq_num;
new_node->init_win = seq_num;
new_node->flags = 0;
if (mwifiex_queuing_ra_based(priv)) {
dev_dbg(priv->adapter->dev,
......@@ -298,11 +300,12 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
}
if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM &&
last_seq >= new_node->start_win)
last_seq >= new_node->start_win) {
new_node->start_win = last_seq + 1;
new_node->flags |= RXREOR_INIT_WINDOW_SHIFT;
}
new_node->win_size = win_size;
new_node->flags = 0;
new_node->rx_reorder_ptr = kzalloc(sizeof(void *) * win_size,
GFP_KERNEL);
......@@ -452,6 +455,7 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
struct mwifiex_rx_reorder_tbl *tbl;
int start_win, end_win, win_size;
u16 pkt_index;
bool init_window_shift = false;
tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
if (!tbl) {
......@@ -466,18 +470,29 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
start_win = tbl->start_win;
win_size = tbl->win_size;
end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
if (tbl->flags & RXREOR_INIT_WINDOW_SHIFT) {
init_window_shift = true;
tbl->flags &= ~RXREOR_INIT_WINDOW_SHIFT;
}
mod_timer(&tbl->timer_context.timer,
jiffies + msecs_to_jiffies(MIN_FLUSH_TIMER_MS * win_size));
/*
* If seq_num is less then starting win then ignore and drop the
* packet
*/
if (tbl->flags & RXREOR_FORCE_NO_DROP) {
dev_dbg(priv->adapter->dev,
"RXREOR_FORCE_NO_DROP when HS is activated\n");
tbl->flags &= ~RXREOR_FORCE_NO_DROP;
} else if (init_window_shift && seq_num < start_win &&
seq_num >= tbl->init_win) {
dev_dbg(priv->adapter->dev,
"Sender TID sequence number reset %d->%d for SSN %d\n",
start_win, seq_num, tbl->init_win);
tbl->start_win = start_win = seq_num;
end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
} else {
/*
* If seq_num is less then starting win then ignore and drop
* the packet
*/
if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) {
if (seq_num >= ((start_win + TWOPOW11) &
(MAX_TID_VALUE - 1)) &&
......
......@@ -43,6 +43,7 @@
enum mwifiex_rxreor_flags {
RXREOR_FORCE_NO_DROP = 1<<0,
RXREOR_INIT_WINDOW_SHIFT = 1<<1,
};
static inline void mwifiex_reset_11n_rx_seq_num(struct mwifiex_private *priv)
......
......@@ -575,6 +575,7 @@ struct mwifiex_rx_reorder_tbl {
struct list_head list;
int tid;
u8 ta[ETH_ALEN];
int init_win;
int start_win;
int win_size;
void **rx_reorder_ptr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment