|
@@ -32,6 +32,16 @@
|
|
#include "wme.h"
|
|
#include "wme.h"
|
|
#include "rate.h"
|
|
#include "rate.h"
|
|
|
|
|
|
|
|
+static inline void ieee80211_rx_stats(struct net_device *dev, u32 len)
|
|
|
|
+{
|
|
|
|
+ struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
|
|
|
|
+
|
|
|
|
+ u64_stats_update_begin(&tstats->syncp);
|
|
|
|
+ tstats->rx_packets++;
|
|
|
|
+ tstats->rx_bytes += len;
|
|
|
|
+ u64_stats_update_end(&tstats->syncp);
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* monitor mode reception
|
|
* monitor mode reception
|
|
*
|
|
*
|
|
@@ -529,8 +539,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
|
|
}
|
|
}
|
|
|
|
|
|
prev_dev = sdata->dev;
|
|
prev_dev = sdata->dev;
|
|
- sdata->dev->stats.rx_packets++;
|
|
|
|
- sdata->dev->stats.rx_bytes += skb->len;
|
|
|
|
|
|
+ ieee80211_rx_stats(sdata->dev, skb->len);
|
|
}
|
|
}
|
|
|
|
|
|
if (prev_dev) {
|
|
if (prev_dev) {
|
|
@@ -981,7 +990,6 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
|
|
struct sk_buff *skb = rx->skb;
|
|
struct sk_buff *skb = rx->skb;
|
|
struct ieee80211_local *local = rx->local;
|
|
struct ieee80211_local *local = rx->local;
|
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
|
- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
|
|
|
struct sta_info *sta = rx->sta;
|
|
struct sta_info *sta = rx->sta;
|
|
struct tid_ampdu_rx *tid_agg_rx;
|
|
struct tid_ampdu_rx *tid_agg_rx;
|
|
u16 sc;
|
|
u16 sc;
|
|
@@ -1016,10 +1024,6 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
|
|
ack_policy != IEEE80211_QOS_CTL_ACK_POLICY_NORMAL)
|
|
ack_policy != IEEE80211_QOS_CTL_ACK_POLICY_NORMAL)
|
|
goto dont_reorder;
|
|
goto dont_reorder;
|
|
|
|
|
|
- /* not actually part of this BA session */
|
|
|
|
- if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
|
|
|
|
- goto dont_reorder;
|
|
|
|
-
|
|
|
|
/* new, potentially un-ordered, ampdu frame - process it */
|
|
/* new, potentially un-ordered, ampdu frame - process it */
|
|
|
|
|
|
/* reset session timer */
|
|
/* reset session timer */
|
|
@@ -1073,10 +1077,8 @@ ieee80211_rx_h_check_dup(struct ieee80211_rx_data *rx)
|
|
if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
|
|
if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
|
|
rx->sta->last_seq_ctrl[rx->seqno_idx] ==
|
|
rx->sta->last_seq_ctrl[rx->seqno_idx] ==
|
|
hdr->seq_ctrl)) {
|
|
hdr->seq_ctrl)) {
|
|
- if (status->rx_flags & IEEE80211_RX_RA_MATCH) {
|
|
|
|
- rx->local->dot11FrameDuplicateCount++;
|
|
|
|
- rx->sta->num_duplicates++;
|
|
|
|
- }
|
|
|
|
|
|
+ I802_DEBUG_INC(rx->local->dot11FrameDuplicateCount);
|
|
|
|
+ rx->sta->num_duplicates++;
|
|
return RX_DROP_UNUSABLE;
|
|
return RX_DROP_UNUSABLE;
|
|
} else if (!(status->flag & RX_FLAG_AMSDU_MORE)) {
|
|
} else if (!(status->flag & RX_FLAG_AMSDU_MORE)) {
|
|
rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl;
|
|
rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl;
|
|
@@ -1200,6 +1202,8 @@ static void sta_ps_start(struct sta_info *sta)
|
|
ps_dbg(sdata, "STA %pM aid %d enters power save mode\n",
|
|
ps_dbg(sdata, "STA %pM aid %d enters power save mode\n",
|
|
sta->sta.addr, sta->sta.aid);
|
|
sta->sta.addr, sta->sta.aid);
|
|
|
|
|
|
|
|
+ ieee80211_clear_fast_xmit(sta);
|
|
|
|
+
|
|
if (!sta->sta.txq[0])
|
|
if (!sta->sta.txq[0])
|
|
return;
|
|
return;
|
|
|
|
|
|
@@ -1265,7 +1269,7 @@ ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx)
|
|
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
|
|
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
|
|
int tid, ac;
|
|
int tid, ac;
|
|
|
|
|
|
- if (!rx->sta || !(status->rx_flags & IEEE80211_RX_RA_MATCH))
|
|
|
|
|
|
+ if (!rx->sta)
|
|
return RX_CONTINUE;
|
|
return RX_CONTINUE;
|
|
|
|
|
|
if (sdata->vif.type != NL80211_IFTYPE_AP &&
|
|
if (sdata->vif.type != NL80211_IFTYPE_AP &&
|
|
@@ -1367,11 +1371,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if (rx->sdata->vif.type == NL80211_IFTYPE_OCB) {
|
|
} else if (rx->sdata->vif.type == NL80211_IFTYPE_OCB) {
|
|
- u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
|
|
|
|
- NL80211_IFTYPE_OCB);
|
|
|
|
- /* OCB uses wild-card BSSID */
|
|
|
|
- if (is_broadcast_ether_addr(bssid))
|
|
|
|
- sta->last_rx = jiffies;
|
|
|
|
|
|
+ sta->last_rx = jiffies;
|
|
} else if (!is_multicast_ether_addr(hdr->addr1)) {
|
|
} else if (!is_multicast_ether_addr(hdr->addr1)) {
|
|
/*
|
|
/*
|
|
* Mesh beacons will update last_rx when if they are found to
|
|
* Mesh beacons will update last_rx when if they are found to
|
|
@@ -1386,9 +1386,6 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
|
|
|
|
- return RX_CONTINUE;
|
|
|
|
-
|
|
|
|
if (rx->sdata->vif.type == NL80211_IFTYPE_STATION)
|
|
if (rx->sdata->vif.type == NL80211_IFTYPE_STATION)
|
|
ieee80211_sta_rx_notify(rx->sdata, hdr);
|
|
ieee80211_sta_rx_notify(rx->sdata, hdr);
|
|
|
|
|
|
@@ -1517,13 +1514,6 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
|
|
* possible.
|
|
* possible.
|
|
*/
|
|
*/
|
|
|
|
|
|
- /*
|
|
|
|
- * No point in finding a key and decrypting if the frame is neither
|
|
|
|
- * addressed to us nor a multicast frame.
|
|
|
|
- */
|
|
|
|
- if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
|
|
|
|
- return RX_CONTINUE;
|
|
|
|
-
|
|
|
|
/* start without a key */
|
|
/* start without a key */
|
|
rx->key = NULL;
|
|
rx->key = NULL;
|
|
fc = hdr->frame_control;
|
|
fc = hdr->frame_control;
|
|
@@ -1795,7 +1785,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
|
frag = sc & IEEE80211_SCTL_FRAG;
|
|
frag = sc & IEEE80211_SCTL_FRAG;
|
|
|
|
|
|
if (is_multicast_ether_addr(hdr->addr1)) {
|
|
if (is_multicast_ether_addr(hdr->addr1)) {
|
|
- rx->local->dot11MulticastReceivedFrameCount++;
|
|
|
|
|
|
+ I802_DEBUG_INC(rx->local->dot11MulticastReceivedFrameCount);
|
|
goto out_no_led;
|
|
goto out_no_led;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1878,7 +1868,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
|
|
|
|
|
rx->skb = __skb_dequeue(&entry->skb_list);
|
|
rx->skb = __skb_dequeue(&entry->skb_list);
|
|
if (skb_tailroom(rx->skb) < entry->extra_len) {
|
|
if (skb_tailroom(rx->skb) < entry->extra_len) {
|
|
- I802_DEBUG_INC(rx->local->rx_expand_skb_head2);
|
|
|
|
|
|
+ I802_DEBUG_INC(rx->local->rx_expand_skb_head_defrag);
|
|
if (unlikely(pskb_expand_head(rx->skb, 0, entry->extra_len,
|
|
if (unlikely(pskb_expand_head(rx->skb, 0, entry->extra_len,
|
|
GFP_ATOMIC))) {
|
|
GFP_ATOMIC))) {
|
|
I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
|
|
I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
|
|
@@ -2054,18 +2044,15 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
|
|
struct sk_buff *skb, *xmit_skb;
|
|
struct sk_buff *skb, *xmit_skb;
|
|
struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
|
|
struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
|
|
struct sta_info *dsta;
|
|
struct sta_info *dsta;
|
|
- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
|
|
|
|
-
|
|
|
|
- dev->stats.rx_packets++;
|
|
|
|
- dev->stats.rx_bytes += rx->skb->len;
|
|
|
|
|
|
|
|
skb = rx->skb;
|
|
skb = rx->skb;
|
|
xmit_skb = NULL;
|
|
xmit_skb = NULL;
|
|
|
|
|
|
|
|
+ ieee80211_rx_stats(dev, skb->len);
|
|
|
|
+
|
|
if ((sdata->vif.type == NL80211_IFTYPE_AP ||
|
|
if ((sdata->vif.type == NL80211_IFTYPE_AP ||
|
|
sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
|
|
sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
|
|
!(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
|
|
!(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
|
|
- (status->rx_flags & IEEE80211_RX_RA_MATCH) &&
|
|
|
|
(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) {
|
|
(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) {
|
|
if (is_multicast_ether_addr(ehdr->h_dest)) {
|
|
if (is_multicast_ether_addr(ehdr->h_dest)) {
|
|
/*
|
|
/*
|
|
@@ -2206,7 +2193,6 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
|
|
struct sk_buff *skb = rx->skb, *fwd_skb;
|
|
struct sk_buff *skb = rx->skb, *fwd_skb;
|
|
struct ieee80211_local *local = rx->local;
|
|
struct ieee80211_local *local = rx->local;
|
|
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
|
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
|
- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
|
|
|
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
|
|
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
|
|
u16 q, hdrlen;
|
|
u16 q, hdrlen;
|
|
|
|
|
|
@@ -2237,8 +2223,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
|
|
mesh_rmc_check(rx->sdata, hdr->addr3, mesh_hdr))
|
|
mesh_rmc_check(rx->sdata, hdr->addr3, mesh_hdr))
|
|
return RX_DROP_MONITOR;
|
|
return RX_DROP_MONITOR;
|
|
|
|
|
|
- if (!ieee80211_is_data(hdr->frame_control) ||
|
|
|
|
- !(status->rx_flags & IEEE80211_RX_RA_MATCH))
|
|
|
|
|
|
+ if (!ieee80211_is_data(hdr->frame_control))
|
|
return RX_CONTINUE;
|
|
return RX_CONTINUE;
|
|
|
|
|
|
if (!mesh_hdr->ttl)
|
|
if (!mesh_hdr->ttl)
|
|
@@ -2329,11 +2314,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
|
|
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames);
|
|
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames);
|
|
ieee80211_add_pending_skb(local, fwd_skb);
|
|
ieee80211_add_pending_skb(local, fwd_skb);
|
|
out:
|
|
out:
|
|
- if (is_multicast_ether_addr(hdr->addr1) ||
|
|
|
|
- sdata->dev->flags & IFF_PROMISC)
|
|
|
|
|
|
+ if (is_multicast_ether_addr(hdr->addr1))
|
|
return RX_CONTINUE;
|
|
return RX_CONTINUE;
|
|
- else
|
|
|
|
- return RX_DROP_MONITOR;
|
|
|
|
|
|
+ return RX_DROP_MONITOR;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
@@ -2444,6 +2427,9 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames)
|
|
struct {
|
|
struct {
|
|
__le16 control, start_seq_num;
|
|
__le16 control, start_seq_num;
|
|
} __packed bar_data;
|
|
} __packed bar_data;
|
|
|
|
+ struct ieee80211_event event = {
|
|
|
|
+ .type = BAR_RX_EVENT,
|
|
|
|
+ };
|
|
|
|
|
|
if (!rx->sta)
|
|
if (!rx->sta)
|
|
return RX_DROP_MONITOR;
|
|
return RX_DROP_MONITOR;
|
|
@@ -2459,6 +2445,9 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames)
|
|
return RX_DROP_MONITOR;
|
|
return RX_DROP_MONITOR;
|
|
|
|
|
|
start_seq_num = le16_to_cpu(bar_data.start_seq_num) >> 4;
|
|
start_seq_num = le16_to_cpu(bar_data.start_seq_num) >> 4;
|
|
|
|
+ event.u.ba.tid = tid;
|
|
|
|
+ event.u.ba.ssn = start_seq_num;
|
|
|
|
+ event.u.ba.sta = &rx->sta->sta;
|
|
|
|
|
|
/* reset session timer */
|
|
/* reset session timer */
|
|
if (tid_agg_rx->timeout)
|
|
if (tid_agg_rx->timeout)
|
|
@@ -2471,6 +2460,8 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames)
|
|
start_seq_num, frames);
|
|
start_seq_num, frames);
|
|
spin_unlock(&tid_agg_rx->reorder_lock);
|
|
spin_unlock(&tid_agg_rx->reorder_lock);
|
|
|
|
|
|
|
|
+ drv_event_callback(rx->local, rx->sdata, &event);
|
|
|
|
+
|
|
kfree_skb(skb);
|
|
kfree_skb(skb);
|
|
return RX_QUEUED;
|
|
return RX_QUEUED;
|
|
}
|
|
}
|
|
@@ -2560,9 +2551,6 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
|
|
rx->flags |= IEEE80211_RX_BEACON_REPORTED;
|
|
rx->flags |= IEEE80211_RX_BEACON_REPORTED;
|
|
}
|
|
}
|
|
|
|
|
|
- if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
|
|
|
|
- return RX_DROP_MONITOR;
|
|
|
|
-
|
|
|
|
if (ieee80211_drop_unencrypted_mgmt(rx))
|
|
if (ieee80211_drop_unencrypted_mgmt(rx))
|
|
return RX_DROP_UNUSABLE;
|
|
return RX_DROP_UNUSABLE;
|
|
|
|
|
|
@@ -2590,9 +2578,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
|
mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT)
|
|
mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT)
|
|
return RX_DROP_UNUSABLE;
|
|
return RX_DROP_UNUSABLE;
|
|
|
|
|
|
- if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
|
|
|
|
- return RX_DROP_UNUSABLE;
|
|
|
|
-
|
|
|
|
switch (mgmt->u.action.category) {
|
|
switch (mgmt->u.action.category) {
|
|
case WLAN_CATEGORY_HT:
|
|
case WLAN_CATEGORY_HT:
|
|
/* reject HT action frames from stations not supporting HT */
|
|
/* reject HT action frames from stations not supporting HT */
|
|
@@ -3076,8 +3061,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
|
|
}
|
|
}
|
|
|
|
|
|
prev_dev = sdata->dev;
|
|
prev_dev = sdata->dev;
|
|
- sdata->dev->stats.rx_packets++;
|
|
|
|
- sdata->dev->stats.rx_bytes += skb->len;
|
|
|
|
|
|
+ ieee80211_rx_stats(sdata->dev, skb->len);
|
|
}
|
|
}
|
|
|
|
|
|
if (prev_dev) {
|
|
if (prev_dev) {
|
|
@@ -3245,16 +3229,25 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
|
|
ieee80211_sta_reorder_release(sta->sdata, tid_agg_rx, &frames);
|
|
ieee80211_sta_reorder_release(sta->sdata, tid_agg_rx, &frames);
|
|
spin_unlock(&tid_agg_rx->reorder_lock);
|
|
spin_unlock(&tid_agg_rx->reorder_lock);
|
|
|
|
|
|
|
|
+ if (!skb_queue_empty(&frames)) {
|
|
|
|
+ struct ieee80211_event event = {
|
|
|
|
+ .type = BA_FRAME_TIMEOUT,
|
|
|
|
+ .u.ba.tid = tid,
|
|
|
|
+ .u.ba.sta = &sta->sta,
|
|
|
|
+ };
|
|
|
|
+ drv_event_callback(rx.local, rx.sdata, &event);
|
|
|
|
+ }
|
|
|
|
+
|
|
ieee80211_rx_handlers(&rx, &frames);
|
|
ieee80211_rx_handlers(&rx, &frames);
|
|
}
|
|
}
|
|
|
|
|
|
/* main receive path */
|
|
/* main receive path */
|
|
|
|
|
|
-static bool prepare_for_handlers(struct ieee80211_rx_data *rx,
|
|
|
|
- struct ieee80211_hdr *hdr)
|
|
|
|
|
|
+static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
|
|
{
|
|
{
|
|
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
|
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
|
struct sk_buff *skb = rx->skb;
|
|
struct sk_buff *skb = rx->skb;
|
|
|
|
+ struct ieee80211_hdr *hdr = (void *)skb->data;
|
|
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
|
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
|
u8 *bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type);
|
|
u8 *bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type);
|
|
int multicast = is_multicast_ether_addr(hdr->addr1);
|
|
int multicast = is_multicast_ether_addr(hdr->addr1);
|
|
@@ -3263,30 +3256,23 @@ static bool prepare_for_handlers(struct ieee80211_rx_data *rx,
|
|
case NL80211_IFTYPE_STATION:
|
|
case NL80211_IFTYPE_STATION:
|
|
if (!bssid && !sdata->u.mgd.use_4addr)
|
|
if (!bssid && !sdata->u.mgd.use_4addr)
|
|
return false;
|
|
return false;
|
|
- if (!multicast &&
|
|
|
|
- !ether_addr_equal(sdata->vif.addr, hdr->addr1)) {
|
|
|
|
- if (!(sdata->dev->flags & IFF_PROMISC) ||
|
|
|
|
- sdata->u.mgd.use_4addr)
|
|
|
|
- return false;
|
|
|
|
- status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
|
|
|
|
- }
|
|
|
|
- break;
|
|
|
|
|
|
+ if (multicast)
|
|
|
|
+ return true;
|
|
|
|
+ return ether_addr_equal(sdata->vif.addr, hdr->addr1);
|
|
case NL80211_IFTYPE_ADHOC:
|
|
case NL80211_IFTYPE_ADHOC:
|
|
if (!bssid)
|
|
if (!bssid)
|
|
return false;
|
|
return false;
|
|
if (ether_addr_equal(sdata->vif.addr, hdr->addr2) ||
|
|
if (ether_addr_equal(sdata->vif.addr, hdr->addr2) ||
|
|
ether_addr_equal(sdata->u.ibss.bssid, hdr->addr2))
|
|
ether_addr_equal(sdata->u.ibss.bssid, hdr->addr2))
|
|
return false;
|
|
return false;
|
|
- if (ieee80211_is_beacon(hdr->frame_control)) {
|
|
|
|
|
|
+ if (ieee80211_is_beacon(hdr->frame_control))
|
|
return true;
|
|
return true;
|
|
- } else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) {
|
|
|
|
|
|
+ if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid))
|
|
return false;
|
|
return false;
|
|
- } else if (!multicast &&
|
|
|
|
- !ether_addr_equal(sdata->vif.addr, hdr->addr1)) {
|
|
|
|
- if (!(sdata->dev->flags & IFF_PROMISC))
|
|
|
|
- return false;
|
|
|
|
- status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
|
|
|
|
- } else if (!rx->sta) {
|
|
|
|
|
|
+ if (!multicast &&
|
|
|
|
+ !ether_addr_equal(sdata->vif.addr, hdr->addr1))
|
|
|
|
+ return false;
|
|
|
|
+ if (!rx->sta) {
|
|
int rate_idx;
|
|
int rate_idx;
|
|
if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT))
|
|
if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT))
|
|
rate_idx = 0; /* TODO: HT/VHT rates */
|
|
rate_idx = 0; /* TODO: HT/VHT rates */
|
|
@@ -3295,25 +3281,18 @@ static bool prepare_for_handlers(struct ieee80211_rx_data *rx,
|
|
ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2,
|
|
ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2,
|
|
BIT(rate_idx));
|
|
BIT(rate_idx));
|
|
}
|
|
}
|
|
- break;
|
|
|
|
|
|
+ return true;
|
|
case NL80211_IFTYPE_OCB:
|
|
case NL80211_IFTYPE_OCB:
|
|
if (!bssid)
|
|
if (!bssid)
|
|
return false;
|
|
return false;
|
|
- if (ieee80211_is_beacon(hdr->frame_control)) {
|
|
|
|
|
|
+ if (ieee80211_is_beacon(hdr->frame_control))
|
|
return false;
|
|
return false;
|
|
- } else if (!is_broadcast_ether_addr(bssid)) {
|
|
|
|
- ocb_dbg(sdata, "BSSID mismatch in OCB mode!\n");
|
|
|
|
|
|
+ if (!is_broadcast_ether_addr(bssid))
|
|
return false;
|
|
return false;
|
|
- } else if (!multicast &&
|
|
|
|
- !ether_addr_equal(sdata->dev->dev_addr,
|
|
|
|
- hdr->addr1)) {
|
|
|
|
- /* if we are in promisc mode we also accept
|
|
|
|
- * packets not destined for us
|
|
|
|
- */
|
|
|
|
- if (!(sdata->dev->flags & IFF_PROMISC))
|
|
|
|
- return false;
|
|
|
|
- rx->flags &= ~IEEE80211_RX_RA_MATCH;
|
|
|
|
- } else if (!rx->sta) {
|
|
|
|
|
|
+ if (!multicast &&
|
|
|
|
+ !ether_addr_equal(sdata->dev->dev_addr, hdr->addr1))
|
|
|
|
+ return false;
|
|
|
|
+ if (!rx->sta) {
|
|
int rate_idx;
|
|
int rate_idx;
|
|
if (status->flag & RX_FLAG_HT)
|
|
if (status->flag & RX_FLAG_HT)
|
|
rate_idx = 0; /* TODO: HT rates */
|
|
rate_idx = 0; /* TODO: HT rates */
|
|
@@ -3322,22 +3301,17 @@ static bool prepare_for_handlers(struct ieee80211_rx_data *rx,
|
|
ieee80211_ocb_rx_no_sta(sdata, bssid, hdr->addr2,
|
|
ieee80211_ocb_rx_no_sta(sdata, bssid, hdr->addr2,
|
|
BIT(rate_idx));
|
|
BIT(rate_idx));
|
|
}
|
|
}
|
|
- break;
|
|
|
|
|
|
+ return true;
|
|
case NL80211_IFTYPE_MESH_POINT:
|
|
case NL80211_IFTYPE_MESH_POINT:
|
|
- if (!multicast &&
|
|
|
|
- !ether_addr_equal(sdata->vif.addr, hdr->addr1)) {
|
|
|
|
- if (!(sdata->dev->flags & IFF_PROMISC))
|
|
|
|
- return false;
|
|
|
|
-
|
|
|
|
- status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
|
|
|
|
- }
|
|
|
|
- break;
|
|
|
|
|
|
+ if (multicast)
|
|
|
|
+ return true;
|
|
|
|
+ return ether_addr_equal(sdata->vif.addr, hdr->addr1);
|
|
case NL80211_IFTYPE_AP_VLAN:
|
|
case NL80211_IFTYPE_AP_VLAN:
|
|
case NL80211_IFTYPE_AP:
|
|
case NL80211_IFTYPE_AP:
|
|
- if (!bssid) {
|
|
|
|
- if (!ether_addr_equal(sdata->vif.addr, hdr->addr1))
|
|
|
|
- return false;
|
|
|
|
- } else if (!ieee80211_bssid_match(bssid, sdata->vif.addr)) {
|
|
|
|
|
|
+ if (!bssid)
|
|
|
|
+ return ether_addr_equal(sdata->vif.addr, hdr->addr1);
|
|
|
|
+
|
|
|
|
+ if (!ieee80211_bssid_match(bssid, sdata->vif.addr)) {
|
|
/*
|
|
/*
|
|
* Accept public action frames even when the
|
|
* Accept public action frames even when the
|
|
* BSSID doesn't match, this is used for P2P
|
|
* BSSID doesn't match, this is used for P2P
|
|
@@ -3349,10 +3323,10 @@ static bool prepare_for_handlers(struct ieee80211_rx_data *rx,
|
|
return false;
|
|
return false;
|
|
if (ieee80211_is_public_action(hdr, skb->len))
|
|
if (ieee80211_is_public_action(hdr, skb->len))
|
|
return true;
|
|
return true;
|
|
- if (!ieee80211_is_beacon(hdr->frame_control))
|
|
|
|
- return false;
|
|
|
|
- status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
|
|
|
|
- } else if (!ieee80211_has_tods(hdr->frame_control)) {
|
|
|
|
|
|
+ return ieee80211_is_beacon(hdr->frame_control);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!ieee80211_has_tods(hdr->frame_control)) {
|
|
/* ignore data frames to TDLS-peers */
|
|
/* ignore data frames to TDLS-peers */
|
|
if (ieee80211_is_data(hdr->frame_control))
|
|
if (ieee80211_is_data(hdr->frame_control))
|
|
return false;
|
|
return false;
|
|
@@ -3361,30 +3335,22 @@ static bool prepare_for_handlers(struct ieee80211_rx_data *rx,
|
|
!ether_addr_equal(bssid, hdr->addr1))
|
|
!ether_addr_equal(bssid, hdr->addr1))
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
- break;
|
|
|
|
|
|
+ return true;
|
|
case NL80211_IFTYPE_WDS:
|
|
case NL80211_IFTYPE_WDS:
|
|
if (bssid || !ieee80211_is_data(hdr->frame_control))
|
|
if (bssid || !ieee80211_is_data(hdr->frame_control))
|
|
return false;
|
|
return false;
|
|
- if (!ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2))
|
|
|
|
- return false;
|
|
|
|
- break;
|
|
|
|
|
|
+ return ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2);
|
|
case NL80211_IFTYPE_P2P_DEVICE:
|
|
case NL80211_IFTYPE_P2P_DEVICE:
|
|
- if (!ieee80211_is_public_action(hdr, skb->len) &&
|
|
|
|
- !ieee80211_is_probe_req(hdr->frame_control) &&
|
|
|
|
- !ieee80211_is_probe_resp(hdr->frame_control) &&
|
|
|
|
- !ieee80211_is_beacon(hdr->frame_control))
|
|
|
|
- return false;
|
|
|
|
- if (!ether_addr_equal(sdata->vif.addr, hdr->addr1) &&
|
|
|
|
- !multicast)
|
|
|
|
- status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
|
|
|
|
- break;
|
|
|
|
|
|
+ return ieee80211_is_public_action(hdr, skb->len) ||
|
|
|
|
+ ieee80211_is_probe_req(hdr->frame_control) ||
|
|
|
|
+ ieee80211_is_probe_resp(hdr->frame_control) ||
|
|
|
|
+ ieee80211_is_beacon(hdr->frame_control);
|
|
default:
|
|
default:
|
|
- /* should never get here */
|
|
|
|
- WARN_ON_ONCE(1);
|
|
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
- return true;
|
|
|
|
|
|
+ WARN_ON_ONCE(1);
|
|
|
|
+ return false;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -3398,13 +3364,10 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
|
|
{
|
|
{
|
|
struct ieee80211_local *local = rx->local;
|
|
struct ieee80211_local *local = rx->local;
|
|
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
|
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
|
- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
|
|
|
- struct ieee80211_hdr *hdr = (void *)skb->data;
|
|
|
|
|
|
|
|
rx->skb = skb;
|
|
rx->skb = skb;
|
|
- status->rx_flags |= IEEE80211_RX_RA_MATCH;
|
|
|
|
|
|
|
|
- if (!prepare_for_handlers(rx, hdr))
|
|
|
|
|
|
+ if (!ieee80211_accept_frame(rx))
|
|
return false;
|
|
return false;
|
|
|
|
|
|
if (!consume) {
|
|
if (!consume) {
|
|
@@ -3447,7 +3410,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
|
|
rx.local = local;
|
|
rx.local = local;
|
|
|
|
|
|
if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
|
|
if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
|
|
- local->dot11ReceivedFragmentCount++;
|
|
|
|
|
|
+ I802_DEBUG_INC(local->dot11ReceivedFragmentCount);
|
|
|
|
|
|
if (ieee80211_is_mgmt(fc)) {
|
|
if (ieee80211_is_mgmt(fc)) {
|
|
/* drop frame if too short for header */
|
|
/* drop frame if too short for header */
|