aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRon Rindjunsky <ron.rindjunsky@intel.com>2007-12-25 10:00:36 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:01:01 -0500
commit713647169e3aaca16be4cfba42513bd4558abec0 (patch)
tree460c9454def4c5bd99104760637ae52a8137b38c
parentb580781e038968fb2529460e8b61e3bf77de112a (diff)
mac80211: A-MPDU Rx adding BAR handling capability
This patch adds the ability to handle Block Ack Request Signed-off-by: Ron Rindjunsky <ron.rindjunsky@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/rx.c62
-rw-r--r--net/mac80211/util.c15
3 files changed, 74 insertions, 6 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 740d69d5bbd3..662e69ef7eed 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -801,7 +801,8 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev);
801extern void *mac80211_wiphy_privid; /* for wiphy privid */ 801extern void *mac80211_wiphy_privid; /* for wiphy privid */
802extern const unsigned char rfc1042_header[6]; 802extern const unsigned char rfc1042_header[6];
803extern const unsigned char bridge_tunnel_header[6]; 803extern const unsigned char bridge_tunnel_header[6];
804u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len); 804u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
805 enum ieee80211_if_types type);
805int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, 806int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
806 int rate, int erp, int short_preamble); 807 int rate, int erp, int short_preamble);
807void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx, 808void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx,
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index e7b1eb8da25c..ed3b81639203 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -24,6 +24,10 @@
24#include "tkip.h" 24#include "tkip.h"
25#include "wme.h" 25#include "wme.h"
26 26
27u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
28 struct tid_ampdu_rx *tid_agg_rx,
29 struct sk_buff *skb, u16 mpdu_seq_num,
30 int bar_req);
27/* 31/*
28 * monitor mode reception 32 * monitor mode reception
29 * 33 *
@@ -64,7 +68,9 @@ static inline int should_drop_frame(struct ieee80211_rx_status *status,
64 if (((hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_FTYPE)) == 68 if (((hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_FTYPE)) ==
65 cpu_to_le16(IEEE80211_FTYPE_CTL)) && 69 cpu_to_le16(IEEE80211_FTYPE_CTL)) &&
66 ((hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE)) != 70 ((hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE)) !=
67 cpu_to_le16(IEEE80211_STYPE_PSPOLL))) 71 cpu_to_le16(IEEE80211_STYPE_PSPOLL)) &&
72 ((hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE)) !=
73 cpu_to_le16(IEEE80211_STYPE_BACK_REQ)))
68 return 1; 74 return 1;
69 return 0; 75 return 0;
70} 76}
@@ -634,7 +640,8 @@ ieee80211_rx_h_sta_process(struct ieee80211_txrx_data *rx)
634 * BSSID to avoid keeping the current IBSS network alive in cases where 640 * BSSID to avoid keeping the current IBSS network alive in cases where
635 * other STAs are using different BSSID. */ 641 * other STAs are using different BSSID. */
636 if (rx->sdata->type == IEEE80211_IF_TYPE_IBSS) { 642 if (rx->sdata->type == IEEE80211_IF_TYPE_IBSS) {
637 u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len); 643 u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
644 IEEE80211_IF_TYPE_IBSS);
638 if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0) 645 if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0)
639 sta->last_rx = jiffies; 646 sta->last_rx = jiffies;
640 } else 647 } else
@@ -1377,6 +1384,49 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
1377} 1384}
1378 1385
1379static ieee80211_txrx_result 1386static ieee80211_txrx_result
1387ieee80211_rx_h_ctrl(struct ieee80211_txrx_data *rx)
1388{
1389 struct ieee80211_local *local = rx->local;
1390 struct ieee80211_hw *hw = &local->hw;
1391 struct sk_buff *skb = rx->skb;
1392 struct ieee80211_bar *bar = (struct ieee80211_bar *) skb->data;
1393 struct tid_ampdu_rx *tid_agg_rx;
1394 u16 start_seq_num;
1395 u16 tid;
1396
1397 if (likely((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL))
1398 return TXRX_CONTINUE;
1399
1400 if ((rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BACK_REQ) {
1401 if (!rx->sta)
1402 return TXRX_CONTINUE;
1403 tid = le16_to_cpu(bar->control) >> 12;
1404 tid_agg_rx = &(rx->sta->ampdu_mlme.tid_rx[tid]);
1405 if (tid_agg_rx->state != HT_AGG_STATE_OPERATIONAL)
1406 return TXRX_CONTINUE;
1407
1408 start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4;
1409
1410 /* reset session timer */
1411 if (tid_agg_rx->timeout) {
1412 unsigned long expires =
1413 jiffies + (tid_agg_rx->timeout / 1000) * HZ;
1414 mod_timer(&tid_agg_rx->session_timer, expires);
1415 }
1416
1417 /* manage reordering buffer according to requested */
1418 /* sequence number */
1419 rcu_read_lock();
1420 ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, NULL,
1421 start_seq_num, 1);
1422 rcu_read_unlock();
1423 return TXRX_DROP;
1424 }
1425
1426 return TXRX_CONTINUE;
1427}
1428
1429static ieee80211_txrx_result
1380ieee80211_rx_h_mgmt(struct ieee80211_txrx_data *rx) 1430ieee80211_rx_h_mgmt(struct ieee80211_txrx_data *rx)
1381{ 1431{
1382 struct ieee80211_sub_if_data *sdata; 1432 struct ieee80211_sub_if_data *sdata;
@@ -1527,6 +1577,7 @@ ieee80211_rx_handler ieee80211_rx_handlers[] =
1527 ieee80211_rx_h_remove_qos_control, 1577 ieee80211_rx_h_remove_qos_control,
1528 ieee80211_rx_h_amsdu, 1578 ieee80211_rx_h_amsdu,
1529 ieee80211_rx_h_data, 1579 ieee80211_rx_h_data,
1580 ieee80211_rx_h_ctrl,
1530 ieee80211_rx_h_mgmt, 1581 ieee80211_rx_h_mgmt,
1531 NULL 1582 NULL
1532}; 1583};
@@ -1683,8 +1734,6 @@ void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, struct sk_buff *skb,
1683 return; 1734 return;
1684 } 1735 }
1685 1736
1686 bssid = ieee80211_get_bssid(hdr, skb->len);
1687
1688 list_for_each_entry_rcu(sdata, &local->interfaces, list) { 1737 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
1689 if (!netif_running(sdata->dev)) 1738 if (!netif_running(sdata->dev))
1690 continue; 1739 continue;
@@ -1692,6 +1741,7 @@ void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, struct sk_buff *skb,
1692 if (sdata->type == IEEE80211_IF_TYPE_MNTR) 1741 if (sdata->type == IEEE80211_IF_TYPE_MNTR)
1693 continue; 1742 continue;
1694 1743
1744 bssid = ieee80211_get_bssid(hdr, skb->len, sdata->type);
1695 rx.flags |= IEEE80211_TXRXD_RXRA_MATCH; 1745 rx.flags |= IEEE80211_TXRXD_RXRA_MATCH;
1696 prepares = prepare_for_handlers(sdata, bssid, &rx, hdr); 1746 prepares = prepare_for_handlers(sdata, bssid, &rx, hdr);
1697 /* prepare_for_handlers can change sta */ 1747 /* prepare_for_handlers can change sta */
@@ -1767,6 +1817,10 @@ static inline u16 seq_sub(u16 sq1, u16 sq2)
1767} 1817}
1768 1818
1769 1819
1820/*
1821 * As it function blongs to Rx path it must be called with
1822 * the proper rcu_read_lock protection for its flow.
1823 */
1770u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, 1824u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
1771 struct tid_ampdu_rx *tid_agg_rx, 1825 struct tid_ampdu_rx *tid_agg_rx,
1772 struct sk_buff *skb, u16 mpdu_seq_num, 1826 struct sk_buff *skb, u16 mpdu_seq_num,
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 2b02b2b9d645..adb85dd5098d 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -127,7 +127,8 @@ void ieee80211_prepare_rates(struct ieee80211_local *local,
127 } 127 }
128} 128}
129 129
130u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len) 130u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
131 enum ieee80211_if_types type)
131{ 132{
132 u16 fc; 133 u16 fc;
133 134
@@ -159,6 +160,18 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len)
159 case IEEE80211_FTYPE_CTL: 160 case IEEE80211_FTYPE_CTL:
160 if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL) 161 if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)
161 return hdr->addr1; 162 return hdr->addr1;
163 else if ((fc & IEEE80211_FCTL_STYPE) ==
164 IEEE80211_STYPE_BACK_REQ) {
165 switch (type) {
166 case IEEE80211_IF_TYPE_STA:
167 return hdr->addr2;
168 case IEEE80211_IF_TYPE_AP:
169 case IEEE80211_IF_TYPE_VLAN:
170 return hdr->addr1;
171 default:
172 return NULL;
173 }
174 }
162 else 175 else
163 return NULL; 176 return NULL;
164 } 177 }