|
@@ -957,7 +957,7 @@ static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
|
|
|
return decrypt_out;
|
|
|
}
|
|
|
|
|
|
-static void iwl_handle_data_packet(struct iwl_priv *priv, int is_data,
|
|
|
+static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
|
|
|
int include_phy,
|
|
|
struct iwl_rx_mem_buffer *rxb,
|
|
|
struct ieee80211_rx_status *stats)
|
|
@@ -999,12 +999,6 @@ static void iwl_handle_data_packet(struct iwl_priv *priv, int is_data,
|
|
|
rx_start->byte_count = amsdu->byte_count;
|
|
|
rx_end = (__le32 *) (((u8 *) hdr) + len);
|
|
|
}
|
|
|
- /* In monitor mode allow 802.11 ACk frames (10 bytes) */
|
|
|
- if (len > priv->hw_params.max_pkt_size ||
|
|
|
- len < ((priv->iw_mode == IEEE80211_IF_TYPE_MNTR) ? 10 : 16)) {
|
|
|
- IWL_WARNING("byte count out of range [16,4K] : %d\n", len);
|
|
|
- return;
|
|
|
- }
|
|
|
|
|
|
ampdu_status = le32_to_cpu(*rx_end);
|
|
|
skblen = ((u8 *) rx_end - (u8 *) &pkt->u.raw[0]) + sizeof(u32);
|
|
@@ -1110,73 +1104,7 @@ static void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-#define IWL_PACKET_RETRY_TIME HZ
|
|
|
-
|
|
|
-static int iwl_is_duplicate_packet(struct iwl_priv *priv,
|
|
|
- struct ieee80211_hdr *header)
|
|
|
-{
|
|
|
- u16 sc = le16_to_cpu(header->seq_ctrl);
|
|
|
- u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
|
|
|
- u16 frag = sc & IEEE80211_SCTL_FRAG;
|
|
|
- u16 *last_seq, *last_frag;
|
|
|
- unsigned long *last_time;
|
|
|
-
|
|
|
- switch (priv->iw_mode) {
|
|
|
- case IEEE80211_IF_TYPE_IBSS:{
|
|
|
- struct list_head *p;
|
|
|
- struct iwl4965_ibss_seq *entry = NULL;
|
|
|
- u8 *mac = header->addr2;
|
|
|
- int index = mac[5] & (IWL_IBSS_MAC_HASH_SIZE - 1);
|
|
|
-
|
|
|
- __list_for_each(p, &priv->ibss_mac_hash[index]) {
|
|
|
- entry = list_entry(p, struct iwl4965_ibss_seq, list);
|
|
|
- if (!compare_ether_addr(entry->mac, mac))
|
|
|
- break;
|
|
|
- }
|
|
|
- if (p == &priv->ibss_mac_hash[index]) {
|
|
|
- entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
|
|
|
- if (!entry) {
|
|
|
- IWL_ERROR("Cannot malloc new mac entry\n");
|
|
|
- return 0;
|
|
|
- }
|
|
|
- memcpy(entry->mac, mac, ETH_ALEN);
|
|
|
- entry->seq_num = seq;
|
|
|
- entry->frag_num = frag;
|
|
|
- entry->packet_time = jiffies;
|
|
|
- list_add(&entry->list, &priv->ibss_mac_hash[index]);
|
|
|
- return 0;
|
|
|
- }
|
|
|
- last_seq = &entry->seq_num;
|
|
|
- last_frag = &entry->frag_num;
|
|
|
- last_time = &entry->packet_time;
|
|
|
- break;
|
|
|
- }
|
|
|
- case IEEE80211_IF_TYPE_STA:
|
|
|
- last_seq = &priv->last_seq_num;
|
|
|
- last_frag = &priv->last_frag_num;
|
|
|
- last_time = &priv->last_packet_time;
|
|
|
- break;
|
|
|
- default:
|
|
|
- return 0;
|
|
|
- }
|
|
|
- if ((*last_seq == seq) &&
|
|
|
- time_after(*last_time + IWL_PACKET_RETRY_TIME, jiffies)) {
|
|
|
- if (*last_frag == frag)
|
|
|
- goto drop;
|
|
|
- if (*last_frag + 1 != frag)
|
|
|
- /* out-of-order fragment */
|
|
|
- goto drop;
|
|
|
- } else
|
|
|
- *last_seq = seq;
|
|
|
-
|
|
|
- *last_frag = frag;
|
|
|
- *last_time = jiffies;
|
|
|
- return 0;
|
|
|
-
|
|
|
- drop:
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
+/* This is necessary only for a number of statistics, see the caller. */
|
|
|
static int iwl_is_network_packet(struct iwl_priv *priv,
|
|
|
struct ieee80211_hdr *header)
|
|
|
{
|
|
@@ -1184,28 +1112,14 @@ static int iwl_is_network_packet(struct iwl_priv *priv,
|
|
|
* this network, discarding packets coming from ourselves */
|
|
|
switch (priv->iw_mode) {
|
|
|
case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source | BSSID */
|
|
|
- /* packets from our adapter are dropped (echo) */
|
|
|
- if (!compare_ether_addr(header->addr2, priv->mac_addr))
|
|
|
- return 0;
|
|
|
- /* {broad,multi}cast packets to our IBSS go through */
|
|
|
- if (is_multicast_ether_addr(header->addr1))
|
|
|
- return !compare_ether_addr(header->addr3, priv->bssid);
|
|
|
- /* packets to our adapter go through */
|
|
|
- return !compare_ether_addr(header->addr1, priv->mac_addr);
|
|
|
+ /* packets to our IBSS update information */
|
|
|
+ return !compare_ether_addr(header->addr3, priv->bssid);
|
|
|
case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */
|
|
|
- /* packets from our adapter are dropped (echo) */
|
|
|
- if (!compare_ether_addr(header->addr3, priv->mac_addr))
|
|
|
- return 0;
|
|
|
- /* {broad,multi}cast packets to our BSS go through */
|
|
|
- if (is_multicast_ether_addr(header->addr1))
|
|
|
- return !compare_ether_addr(header->addr2, priv->bssid);
|
|
|
- /* packets to our adapter go through */
|
|
|
- return !compare_ether_addr(header->addr1, priv->mac_addr);
|
|
|
+ /* packets to our IBSS update information */
|
|
|
+ return !compare_ether_addr(header->addr2, priv->bssid);
|
|
|
default:
|
|
|
- break;
|
|
|
+ return 1;
|
|
|
}
|
|
|
-
|
|
|
- return 1;
|
|
|
}
|
|
|
|
|
|
/* Called for REPLY_RX (legacy ABG frames), or
|
|
@@ -1316,9 +1230,9 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
|
|
|
rx_status.signal, rx_status.noise, rx_status.signal,
|
|
|
(unsigned long long)rx_status.mactime);
|
|
|
|
|
|
-
|
|
|
+ /* Take shortcut when only in monitor mode */
|
|
|
if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
|
|
|
- iwl_handle_data_packet(priv, 1, include_phy,
|
|
|
+ iwl_pass_packet_to_mac80211(priv, include_phy,
|
|
|
rxb, &rx_status);
|
|
|
return;
|
|
|
}
|
|
@@ -1333,50 +1247,14 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
|
|
|
fc = le16_to_cpu(header->frame_control);
|
|
|
switch (fc & IEEE80211_FCTL_FTYPE) {
|
|
|
case IEEE80211_FTYPE_MGMT:
|
|
|
+ case IEEE80211_FTYPE_DATA:
|
|
|
if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
|
|
|
iwl_update_ps_mode(priv, fc & IEEE80211_FCTL_PM,
|
|
|
header->addr2);
|
|
|
- iwl_handle_data_packet(priv, 0, include_phy, rxb, &rx_status);
|
|
|
- break;
|
|
|
-
|
|
|
- case IEEE80211_FTYPE_CTL:
|
|
|
- switch (fc & IEEE80211_FCTL_STYPE) {
|
|
|
- case IEEE80211_STYPE_BACK_REQ:
|
|
|
- IWL_DEBUG_HT("IEEE80211_STYPE_BACK_REQ arrived\n");
|
|
|
- iwl_handle_data_packet(priv, 0, include_phy,
|
|
|
- rxb, &rx_status);
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
- case IEEE80211_FTYPE_DATA: {
|
|
|
- DECLARE_MAC_BUF(mac1);
|
|
|
- DECLARE_MAC_BUF(mac2);
|
|
|
- DECLARE_MAC_BUF(mac3);
|
|
|
-
|
|
|
- if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
|
|
|
- iwl_update_ps_mode(priv, fc & IEEE80211_FCTL_PM,
|
|
|
- header->addr2);
|
|
|
-
|
|
|
- if (unlikely(!network_packet))
|
|
|
- IWL_DEBUG_DROP("Dropping (non network): "
|
|
|
- "%s, %s, %s\n",
|
|
|
- print_mac(mac1, header->addr1),
|
|
|
- print_mac(mac2, header->addr2),
|
|
|
- print_mac(mac3, header->addr3));
|
|
|
- else if (unlikely(iwl_is_duplicate_packet(priv, header)))
|
|
|
- IWL_DEBUG_DROP("Dropping (dup): %s, %s, %s\n",
|
|
|
- print_mac(mac1, header->addr1),
|
|
|
- print_mac(mac2, header->addr2),
|
|
|
- print_mac(mac3, header->addr3));
|
|
|
- else
|
|
|
- iwl_handle_data_packet(priv, 1, include_phy, rxb,
|
|
|
- &rx_status);
|
|
|
- break;
|
|
|
- }
|
|
|
+ /* fall through */
|
|
|
default:
|
|
|
+ iwl_pass_packet_to_mac80211(priv, include_phy, rxb,
|
|
|
+ &rx_status);
|
|
|
break;
|
|
|
|
|
|
}
|