diff options
author | Ron Rindjunsky <ron.rindjunsky@intel.com> | 2007-12-25 10:00:36 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:01:01 -0500 |
commit | 713647169e3aaca16be4cfba42513bd4558abec0 (patch) | |
tree | 460c9454def4c5bd99104760637ae52a8137b38c | |
parent | b580781e038968fb2529460e8b61e3bf77de112a (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.h | 3 | ||||
-rw-r--r-- | net/mac80211/rx.c | 62 | ||||
-rw-r--r-- | net/mac80211/util.c | 15 |
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); | |||
801 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ | 801 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ |
802 | extern const unsigned char rfc1042_header[6]; | 802 | extern const unsigned char rfc1042_header[6]; |
803 | extern const unsigned char bridge_tunnel_header[6]; | 803 | extern const unsigned char bridge_tunnel_header[6]; |
804 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len); | 804 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, |
805 | enum ieee80211_if_types type); | ||
805 | int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, | 806 | int 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); |
807 | void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx, | 808 | void 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 | ||
27 | u8 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 | ||
1379 | static ieee80211_txrx_result | 1386 | static ieee80211_txrx_result |
1387 | ieee80211_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 | |||
1429 | static ieee80211_txrx_result | ||
1380 | ieee80211_rx_h_mgmt(struct ieee80211_txrx_data *rx) | 1430 | ieee80211_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 | */ | ||
1770 | u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | 1824 | u8 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 | ||
130 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len) | 130 | u8 *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 | } |