diff options
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 319 |
1 files changed, 151 insertions, 168 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 9776f73c51ad..de5bba7f910a 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <net/ieee80211_radiotap.h> | 19 | #include <net/ieee80211_radiotap.h> |
20 | 20 | ||
21 | #include "ieee80211_i.h" | 21 | #include "ieee80211_i.h" |
22 | #include "driver-ops.h" | ||
22 | #include "led.h" | 23 | #include "led.h" |
23 | #include "mesh.h" | 24 | #include "mesh.h" |
24 | #include "wep.h" | 25 | #include "wep.h" |
@@ -629,15 +630,6 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
629 | * possible. | 630 | * possible. |
630 | */ | 631 | */ |
631 | 632 | ||
632 | if (!ieee80211_has_protected(hdr->frame_control)) { | ||
633 | if (!ieee80211_is_mgmt(hdr->frame_control) || | ||
634 | rx->sta == NULL || !test_sta_flags(rx->sta, WLAN_STA_MFP)) | ||
635 | return RX_CONTINUE; | ||
636 | mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); | ||
637 | if (mmie_keyidx < 0) | ||
638 | return RX_CONTINUE; | ||
639 | } | ||
640 | |||
641 | /* | 633 | /* |
642 | * No point in finding a key and decrypting if the frame is neither | 634 | * No point in finding a key and decrypting if the frame is neither |
643 | * addressed to us nor a multicast frame. | 635 | * addressed to us nor a multicast frame. |
@@ -648,8 +640,14 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
648 | if (rx->sta) | 640 | if (rx->sta) |
649 | stakey = rcu_dereference(rx->sta->key); | 641 | stakey = rcu_dereference(rx->sta->key); |
650 | 642 | ||
643 | if (!ieee80211_has_protected(hdr->frame_control)) | ||
644 | mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); | ||
645 | |||
651 | if (!is_multicast_ether_addr(hdr->addr1) && stakey) { | 646 | if (!is_multicast_ether_addr(hdr->addr1) && stakey) { |
652 | rx->key = stakey; | 647 | rx->key = stakey; |
648 | /* Skip decryption if the frame is not protected. */ | ||
649 | if (!ieee80211_has_protected(hdr->frame_control)) | ||
650 | return RX_CONTINUE; | ||
653 | } else if (mmie_keyidx >= 0) { | 651 | } else if (mmie_keyidx >= 0) { |
654 | /* Broadcast/multicast robust management frame / BIP */ | 652 | /* Broadcast/multicast robust management frame / BIP */ |
655 | if ((rx->status->flag & RX_FLAG_DECRYPTED) && | 653 | if ((rx->status->flag & RX_FLAG_DECRYPTED) && |
@@ -660,6 +658,21 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
660 | mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) | 658 | mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) |
661 | return RX_DROP_MONITOR; /* unexpected BIP keyidx */ | 659 | return RX_DROP_MONITOR; /* unexpected BIP keyidx */ |
662 | rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]); | 660 | rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]); |
661 | } else if (!ieee80211_has_protected(hdr->frame_control)) { | ||
662 | /* | ||
663 | * The frame was not protected, so skip decryption. However, we | ||
664 | * need to set rx->key if there is a key that could have been | ||
665 | * used so that the frame may be dropped if encryption would | ||
666 | * have been expected. | ||
667 | */ | ||
668 | struct ieee80211_key *key = NULL; | ||
669 | if (ieee80211_is_mgmt(hdr->frame_control) && | ||
670 | is_multicast_ether_addr(hdr->addr1) && | ||
671 | (key = rcu_dereference(rx->sdata->default_mgmt_key))) | ||
672 | rx->key = key; | ||
673 | else if ((key = rcu_dereference(rx->sdata->default_key))) | ||
674 | rx->key = key; | ||
675 | return RX_CONTINUE; | ||
663 | } else { | 676 | } else { |
664 | /* | 677 | /* |
665 | * The device doesn't give us the IV so we won't be | 678 | * The device doesn't give us the IV so we won't be |
@@ -773,9 +786,7 @@ static void ap_sta_ps_start(struct sta_info *sta) | |||
773 | 786 | ||
774 | atomic_inc(&sdata->bss->num_sta_ps); | 787 | atomic_inc(&sdata->bss->num_sta_ps); |
775 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); | 788 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); |
776 | if (local->ops->sta_notify) | 789 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_SLEEP, &sta->sta); |
777 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | ||
778 | STA_NOTIFY_SLEEP, &sta->sta); | ||
779 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 790 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
780 | printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", | 791 | printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", |
781 | sdata->dev->name, sta->sta.addr, sta->sta.aid); | 792 | sdata->dev->name, sta->sta.addr, sta->sta.aid); |
@@ -786,15 +797,12 @@ static int ap_sta_ps_end(struct sta_info *sta) | |||
786 | { | 797 | { |
787 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 798 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
788 | struct ieee80211_local *local = sdata->local; | 799 | struct ieee80211_local *local = sdata->local; |
789 | struct sk_buff *skb; | 800 | int sent, buffered; |
790 | int sent = 0; | ||
791 | 801 | ||
792 | atomic_dec(&sdata->bss->num_sta_ps); | 802 | atomic_dec(&sdata->bss->num_sta_ps); |
793 | 803 | ||
794 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); | 804 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); |
795 | if (local->ops->sta_notify) | 805 | drv_sta_notify(local, &sdata->vif, STA_NOTIFY_AWAKE, &sta->sta); |
796 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | ||
797 | STA_NOTIFY_AWAKE, &sta->sta); | ||
798 | 806 | ||
799 | if (!skb_queue_empty(&sta->ps_tx_buf)) | 807 | if (!skb_queue_empty(&sta->ps_tx_buf)) |
800 | sta_info_clear_tim_bit(sta); | 808 | sta_info_clear_tim_bit(sta); |
@@ -805,22 +813,16 @@ static int ap_sta_ps_end(struct sta_info *sta) | |||
805 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 813 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
806 | 814 | ||
807 | /* Send all buffered frames to the station */ | 815 | /* Send all buffered frames to the station */ |
808 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) { | 816 | sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered); |
809 | sent++; | 817 | buffered = ieee80211_add_pending_skbs(local, &sta->ps_tx_buf); |
810 | skb->requeue = 1; | 818 | sent += buffered; |
811 | dev_queue_xmit(skb); | 819 | local->total_ps_buffered -= buffered; |
812 | } | 820 | |
813 | while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { | ||
814 | local->total_ps_buffered--; | ||
815 | sent++; | ||
816 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 821 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
817 | printk(KERN_DEBUG "%s: STA %pM aid %d send PS frame " | 822 | printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames " |
818 | "since STA not sleeping anymore\n", sdata->dev->name, | 823 | "since STA not sleeping anymore\n", sdata->dev->name, |
819 | sta->sta.addr, sta->sta.aid); | 824 | sta->sta.addr, sta->sta.aid, sent - buffered, buffered); |
820 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 825 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
821 | skb->requeue = 1; | ||
822 | dev_queue_xmit(skb); | ||
823 | } | ||
824 | 826 | ||
825 | return sent; | 827 | return sent; |
826 | } | 828 | } |
@@ -1212,109 +1214,38 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) | |||
1212 | /* Drop unencrypted frames if key is set. */ | 1214 | /* Drop unencrypted frames if key is set. */ |
1213 | if (unlikely(!ieee80211_has_protected(fc) && | 1215 | if (unlikely(!ieee80211_has_protected(fc) && |
1214 | !ieee80211_is_nullfunc(fc) && | 1216 | !ieee80211_is_nullfunc(fc) && |
1215 | (!ieee80211_is_mgmt(fc) || | 1217 | ieee80211_is_data(fc) && |
1216 | (ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | ||
1217 | rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP))) && | ||
1218 | (rx->key || rx->sdata->drop_unencrypted))) | ||
1219 | return -EACCES; | ||
1220 | /* BIP does not use Protected field, so need to check MMIE */ | ||
1221 | if (unlikely(rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP) && | ||
1222 | ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && | ||
1223 | ieee80211_get_mmie_keyidx(rx->skb) < 0 && | ||
1224 | (rx->key || rx->sdata->drop_unencrypted))) | 1218 | (rx->key || rx->sdata->drop_unencrypted))) |
1225 | return -EACCES; | 1219 | return -EACCES; |
1220 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { | ||
1221 | if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | ||
1222 | rx->key)) | ||
1223 | return -EACCES; | ||
1224 | /* BIP does not use Protected field, so need to check MMIE */ | ||
1225 | if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) | ||
1226 | && ieee80211_get_mmie_keyidx(rx->skb) < 0 && | ||
1227 | rx->key)) | ||
1228 | return -EACCES; | ||
1229 | /* | ||
1230 | * When using MFP, Action frames are not allowed prior to | ||
1231 | * having configured keys. | ||
1232 | */ | ||
1233 | if (unlikely(ieee80211_is_action(fc) && !rx->key && | ||
1234 | ieee80211_is_robust_mgmt_frame( | ||
1235 | (struct ieee80211_hdr *) rx->skb->data))) | ||
1236 | return -EACCES; | ||
1237 | } | ||
1226 | 1238 | ||
1227 | return 0; | 1239 | return 0; |
1228 | } | 1240 | } |
1229 | 1241 | ||
1230 | static int | 1242 | static int |
1231 | ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | 1243 | __ieee80211_data_to_8023(struct ieee80211_rx_data *rx) |
1232 | { | 1244 | { |
1233 | struct net_device *dev = rx->dev; | 1245 | struct net_device *dev = rx->dev; |
1234 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; | ||
1235 | u16 hdrlen, ethertype; | ||
1236 | u8 *payload; | ||
1237 | u8 dst[ETH_ALEN]; | ||
1238 | u8 src[ETH_ALEN] __aligned(2); | ||
1239 | struct sk_buff *skb = rx->skb; | ||
1240 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1246 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1241 | 1247 | ||
1242 | if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) | 1248 | return ieee80211_data_to_8023(rx->skb, dev->dev_addr, sdata->vif.type); |
1243 | return -1; | ||
1244 | |||
1245 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
1246 | |||
1247 | /* convert IEEE 802.11 header + possible LLC headers into Ethernet | ||
1248 | * header | ||
1249 | * IEEE 802.11 address fields: | ||
1250 | * ToDS FromDS Addr1 Addr2 Addr3 Addr4 | ||
1251 | * 0 0 DA SA BSSID n/a | ||
1252 | * 0 1 DA BSSID SA n/a | ||
1253 | * 1 0 BSSID SA DA n/a | ||
1254 | * 1 1 RA TA DA SA | ||
1255 | */ | ||
1256 | memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN); | ||
1257 | memcpy(src, ieee80211_get_SA(hdr), ETH_ALEN); | ||
1258 | |||
1259 | switch (hdr->frame_control & | ||
1260 | cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { | ||
1261 | case cpu_to_le16(IEEE80211_FCTL_TODS): | ||
1262 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_AP && | ||
1263 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) | ||
1264 | return -1; | ||
1265 | break; | ||
1266 | case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): | ||
1267 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && | ||
1268 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) | ||
1269 | return -1; | ||
1270 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
1271 | struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *) | ||
1272 | (skb->data + hdrlen); | ||
1273 | hdrlen += ieee80211_get_mesh_hdrlen(meshdr); | ||
1274 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { | ||
1275 | memcpy(dst, meshdr->eaddr1, ETH_ALEN); | ||
1276 | memcpy(src, meshdr->eaddr2, ETH_ALEN); | ||
1277 | } | ||
1278 | } | ||
1279 | break; | ||
1280 | case cpu_to_le16(IEEE80211_FCTL_FROMDS): | ||
1281 | if (sdata->vif.type != NL80211_IFTYPE_STATION || | ||
1282 | (is_multicast_ether_addr(dst) && | ||
1283 | !compare_ether_addr(src, dev->dev_addr))) | ||
1284 | return -1; | ||
1285 | break; | ||
1286 | case cpu_to_le16(0): | ||
1287 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) | ||
1288 | return -1; | ||
1289 | break; | ||
1290 | } | ||
1291 | |||
1292 | if (unlikely(skb->len - hdrlen < 8)) | ||
1293 | return -1; | ||
1294 | |||
1295 | payload = skb->data + hdrlen; | ||
1296 | ethertype = (payload[6] << 8) | payload[7]; | ||
1297 | |||
1298 | if (likely((compare_ether_addr(payload, rfc1042_header) == 0 && | ||
1299 | ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || | ||
1300 | compare_ether_addr(payload, bridge_tunnel_header) == 0)) { | ||
1301 | /* remove RFC1042 or Bridge-Tunnel encapsulation and | ||
1302 | * replace EtherType */ | ||
1303 | skb_pull(skb, hdrlen + 6); | ||
1304 | memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); | ||
1305 | memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); | ||
1306 | } else { | ||
1307 | struct ethhdr *ehdr; | ||
1308 | __be16 len; | ||
1309 | |||
1310 | skb_pull(skb, hdrlen); | ||
1311 | len = htons(skb->len); | ||
1312 | ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr)); | ||
1313 | memcpy(ehdr->h_dest, dst, ETH_ALEN); | ||
1314 | memcpy(ehdr->h_source, src, ETH_ALEN); | ||
1315 | ehdr->h_proto = len; | ||
1316 | } | ||
1317 | return 0; | ||
1318 | } | 1249 | } |
1319 | 1250 | ||
1320 | /* | 1251 | /* |
@@ -1397,7 +1328,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1397 | * mac80211. That also explains the __skb_push() | 1328 | * mac80211. That also explains the __skb_push() |
1398 | * below. | 1329 | * below. |
1399 | */ | 1330 | */ |
1400 | align = (unsigned long)skb->data & 3; | 1331 | align = ((unsigned long)(skb->data + sizeof(struct ethhdr))) & 3; |
1401 | if (align) { | 1332 | if (align) { |
1402 | if (WARN_ON(skb_headroom(skb) < 3)) { | 1333 | if (WARN_ON(skb_headroom(skb) < 3)) { |
1403 | dev_kfree_skb(skb); | 1334 | dev_kfree_skb(skb); |
@@ -1453,7 +1384,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | |||
1453 | if (!(rx->flags & IEEE80211_RX_AMSDU)) | 1384 | if (!(rx->flags & IEEE80211_RX_AMSDU)) |
1454 | return RX_CONTINUE; | 1385 | return RX_CONTINUE; |
1455 | 1386 | ||
1456 | err = ieee80211_data_to_8023(rx); | 1387 | err = __ieee80211_data_to_8023(rx); |
1457 | if (unlikely(err)) | 1388 | if (unlikely(err)) |
1458 | return RX_DROP_UNUSABLE; | 1389 | return RX_DROP_UNUSABLE; |
1459 | 1390 | ||
@@ -1639,7 +1570,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | |||
1639 | if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) | 1570 | if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) |
1640 | return RX_DROP_MONITOR; | 1571 | return RX_DROP_MONITOR; |
1641 | 1572 | ||
1642 | err = ieee80211_data_to_8023(rx); | 1573 | err = __ieee80211_data_to_8023(rx); |
1643 | if (unlikely(err)) | 1574 | if (unlikely(err)) |
1644 | return RX_DROP_UNUSABLE; | 1575 | return RX_DROP_UNUSABLE; |
1645 | 1576 | ||
@@ -1827,6 +1758,9 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1827 | sizeof(mgmt->u.action.u.chan_switch))) | 1758 | sizeof(mgmt->u.action.u.chan_switch))) |
1828 | return RX_DROP_MONITOR; | 1759 | return RX_DROP_MONITOR; |
1829 | 1760 | ||
1761 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
1762 | return RX_DROP_MONITOR; | ||
1763 | |||
1830 | if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN)) | 1764 | if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN)) |
1831 | return RX_DROP_MONITOR; | 1765 | return RX_DROP_MONITOR; |
1832 | 1766 | ||
@@ -1837,7 +1771,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1837 | if (!bss) | 1771 | if (!bss) |
1838 | return RX_DROP_MONITOR; | 1772 | return RX_DROP_MONITOR; |
1839 | 1773 | ||
1840 | ieee80211_process_chanswitch(sdata, | 1774 | ieee80211_sta_process_chanswitch(sdata, |
1841 | &mgmt->u.action.u.chan_switch.sw_elem, bss); | 1775 | &mgmt->u.action.u.chan_switch.sw_elem, bss); |
1842 | ieee80211_rx_bss_put(local, bss); | 1776 | ieee80211_rx_bss_put(local, bss); |
1843 | break; | 1777 | break; |
@@ -1932,7 +1866,7 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev, | |||
1932 | !ieee80211_is_auth(hdr->frame_control)) | 1866 | !ieee80211_is_auth(hdr->frame_control)) |
1933 | goto ignore; | 1867 | goto ignore; |
1934 | 1868 | ||
1935 | mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr); | 1869 | mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr, NULL); |
1936 | ignore: | 1870 | ignore: |
1937 | dev_kfree_skb(rx->skb); | 1871 | dev_kfree_skb(rx->skb); |
1938 | rx->skb = NULL; | 1872 | rx->skb = NULL; |
@@ -2287,6 +2221,43 @@ static inline u16 seq_sub(u16 sq1, u16 sq2) | |||
2287 | } | 2221 | } |
2288 | 2222 | ||
2289 | 2223 | ||
2224 | static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw, | ||
2225 | struct tid_ampdu_rx *tid_agg_rx, | ||
2226 | int index) | ||
2227 | { | ||
2228 | struct ieee80211_supported_band *sband; | ||
2229 | struct ieee80211_rate *rate; | ||
2230 | struct ieee80211_rx_status status; | ||
2231 | |||
2232 | if (!tid_agg_rx->reorder_buf[index]) | ||
2233 | goto no_frame; | ||
2234 | |||
2235 | /* release the reordered frames to stack */ | ||
2236 | memcpy(&status, tid_agg_rx->reorder_buf[index]->cb, sizeof(status)); | ||
2237 | sband = hw->wiphy->bands[status.band]; | ||
2238 | if (status.flag & RX_FLAG_HT) | ||
2239 | rate = sband->bitrates; /* TODO: HT rates */ | ||
2240 | else | ||
2241 | rate = &sband->bitrates[status.rate_idx]; | ||
2242 | __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index], | ||
2243 | &status, rate); | ||
2244 | tid_agg_rx->stored_mpdu_num--; | ||
2245 | tid_agg_rx->reorder_buf[index] = NULL; | ||
2246 | |||
2247 | no_frame: | ||
2248 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); | ||
2249 | } | ||
2250 | |||
2251 | |||
2252 | /* | ||
2253 | * Timeout (in jiffies) for skb's that are waiting in the RX reorder buffer. If | ||
2254 | * the skb was added to the buffer longer than this time ago, the earlier | ||
2255 | * frames that have not yet been received are assumed to be lost and the skb | ||
2256 | * can be released for processing. This may also release other skb's from the | ||
2257 | * reorder buffer if there are no additional gaps between the frames. | ||
2258 | */ | ||
2259 | #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) | ||
2260 | |||
2290 | /* | 2261 | /* |
2291 | * As it function blongs to Rx path it must be called with | 2262 | * As it function blongs to Rx path it must be called with |
2292 | * the proper rcu_read_lock protection for its flow. | 2263 | * the proper rcu_read_lock protection for its flow. |
@@ -2298,12 +2269,8 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
2298 | u16 mpdu_seq_num, | 2269 | u16 mpdu_seq_num, |
2299 | int bar_req) | 2270 | int bar_req) |
2300 | { | 2271 | { |
2301 | struct ieee80211_local *local = hw_to_local(hw); | ||
2302 | struct ieee80211_rx_status status; | ||
2303 | u16 head_seq_num, buf_size; | 2272 | u16 head_seq_num, buf_size; |
2304 | int index; | 2273 | int index; |
2305 | struct ieee80211_supported_band *sband; | ||
2306 | struct ieee80211_rate *rate; | ||
2307 | 2274 | ||
2308 | buf_size = tid_agg_rx->buf_size; | 2275 | buf_size = tid_agg_rx->buf_size; |
2309 | head_seq_num = tid_agg_rx->head_seq_num; | 2276 | head_seq_num = tid_agg_rx->head_seq_num; |
@@ -2328,28 +2295,8 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
2328 | index = seq_sub(tid_agg_rx->head_seq_num, | 2295 | index = seq_sub(tid_agg_rx->head_seq_num, |
2329 | tid_agg_rx->ssn) | 2296 | tid_agg_rx->ssn) |
2330 | % tid_agg_rx->buf_size; | 2297 | % tid_agg_rx->buf_size; |
2331 | 2298 | ieee80211_release_reorder_frame(hw, tid_agg_rx, | |
2332 | if (tid_agg_rx->reorder_buf[index]) { | 2299 | index); |
2333 | /* release the reordered frames to stack */ | ||
2334 | memcpy(&status, | ||
2335 | tid_agg_rx->reorder_buf[index]->cb, | ||
2336 | sizeof(status)); | ||
2337 | sband = local->hw.wiphy->bands[status.band]; | ||
2338 | if (status.flag & RX_FLAG_HT) { | ||
2339 | /* TODO: HT rates */ | ||
2340 | rate = sband->bitrates; | ||
2341 | } else { | ||
2342 | rate = &sband->bitrates | ||
2343 | [status.rate_idx]; | ||
2344 | } | ||
2345 | __ieee80211_rx_handle_packet(hw, | ||
2346 | tid_agg_rx->reorder_buf[index], | ||
2347 | &status, rate); | ||
2348 | tid_agg_rx->stored_mpdu_num--; | ||
2349 | tid_agg_rx->reorder_buf[index] = NULL; | ||
2350 | } | ||
2351 | tid_agg_rx->head_seq_num = | ||
2352 | seq_inc(tid_agg_rx->head_seq_num); | ||
2353 | } | 2300 | } |
2354 | if (bar_req) | 2301 | if (bar_req) |
2355 | return 1; | 2302 | return 1; |
@@ -2376,26 +2323,50 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
2376 | 2323 | ||
2377 | /* put the frame in the reordering buffer */ | 2324 | /* put the frame in the reordering buffer */ |
2378 | tid_agg_rx->reorder_buf[index] = skb; | 2325 | tid_agg_rx->reorder_buf[index] = skb; |
2326 | tid_agg_rx->reorder_time[index] = jiffies; | ||
2379 | memcpy(tid_agg_rx->reorder_buf[index]->cb, rxstatus, | 2327 | memcpy(tid_agg_rx->reorder_buf[index]->cb, rxstatus, |
2380 | sizeof(*rxstatus)); | 2328 | sizeof(*rxstatus)); |
2381 | tid_agg_rx->stored_mpdu_num++; | 2329 | tid_agg_rx->stored_mpdu_num++; |
2382 | /* release the buffer until next missing frame */ | 2330 | /* release the buffer until next missing frame */ |
2383 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) | 2331 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) |
2384 | % tid_agg_rx->buf_size; | 2332 | % tid_agg_rx->buf_size; |
2385 | while (tid_agg_rx->reorder_buf[index]) { | 2333 | if (!tid_agg_rx->reorder_buf[index] && |
2386 | /* release the reordered frame back to stack */ | 2334 | tid_agg_rx->stored_mpdu_num > 1) { |
2387 | memcpy(&status, tid_agg_rx->reorder_buf[index]->cb, | 2335 | /* |
2388 | sizeof(status)); | 2336 | * No buffers ready to be released, but check whether any |
2389 | sband = local->hw.wiphy->bands[status.band]; | 2337 | * frames in the reorder buffer have timed out. |
2390 | if (status.flag & RX_FLAG_HT) | 2338 | */ |
2391 | rate = sband->bitrates; /* TODO: HT rates */ | 2339 | int j; |
2392 | else | 2340 | int skipped = 1; |
2393 | rate = &sband->bitrates[status.rate_idx]; | 2341 | for (j = (index + 1) % tid_agg_rx->buf_size; j != index; |
2394 | __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index], | 2342 | j = (j + 1) % tid_agg_rx->buf_size) { |
2395 | &status, rate); | 2343 | if (tid_agg_rx->reorder_buf[j] == NULL) { |
2396 | tid_agg_rx->stored_mpdu_num--; | 2344 | skipped++; |
2397 | tid_agg_rx->reorder_buf[index] = NULL; | 2345 | continue; |
2398 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); | 2346 | } |
2347 | if (!time_after(jiffies, tid_agg_rx->reorder_time[j] + | ||
2348 | HZ / 10)) | ||
2349 | break; | ||
2350 | |||
2351 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
2352 | if (net_ratelimit()) | ||
2353 | printk(KERN_DEBUG "%s: release an RX reorder " | ||
2354 | "frame due to timeout on earlier " | ||
2355 | "frames\n", | ||
2356 | wiphy_name(hw->wiphy)); | ||
2357 | #endif | ||
2358 | ieee80211_release_reorder_frame(hw, tid_agg_rx, j); | ||
2359 | |||
2360 | /* | ||
2361 | * Increment the head seq# also for the skipped slots. | ||
2362 | */ | ||
2363 | tid_agg_rx->head_seq_num = | ||
2364 | (tid_agg_rx->head_seq_num + skipped) & | ||
2365 | SEQ_MASK; | ||
2366 | skipped = 0; | ||
2367 | } | ||
2368 | } else while (tid_agg_rx->reorder_buf[index]) { | ||
2369 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index); | ||
2399 | index = seq_sub(tid_agg_rx->head_seq_num, | 2370 | index = seq_sub(tid_agg_rx->head_seq_num, |
2400 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; | 2371 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; |
2401 | } | 2372 | } |
@@ -2517,6 +2488,18 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2517 | return; | 2488 | return; |
2518 | } | 2489 | } |
2519 | 2490 | ||
2491 | /* | ||
2492 | * In theory, the block ack reordering should happen after duplicate | ||
2493 | * removal (ieee80211_rx_h_check(), which is an RX handler). As such, | ||
2494 | * the call to ieee80211_rx_reorder_ampdu() should really be moved to | ||
2495 | * happen as a new RX handler between ieee80211_rx_h_check and | ||
2496 | * ieee80211_rx_h_decrypt. This cleanup may eventually happen, but for | ||
2497 | * the time being, the call can be here since RX reorder buf processing | ||
2498 | * will implicitly skip duplicates. We could, in theory at least, | ||
2499 | * process frames that ieee80211_rx_h_passive_scan would drop (e.g., | ||
2500 | * frames from other than operational channel), but that should not | ||
2501 | * happen in normal networks. | ||
2502 | */ | ||
2520 | if (!ieee80211_rx_reorder_ampdu(local, skb, status)) | 2503 | if (!ieee80211_rx_reorder_ampdu(local, skb, status)) |
2521 | __ieee80211_rx_handle_packet(hw, skb, status, rate); | 2504 | __ieee80211_rx_handle_packet(hw, skb, status, rate); |
2522 | 2505 | ||