summaryrefslogtreecommitdiff
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c66
1 files changed, 43 insertions, 23 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 7b801dd3f569..4d4ff4d4917a 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -231,8 +231,19 @@ static void __ieee80211_queue_skb_to_iface(struct ieee80211_sub_if_data *sdata,
skb_queue_tail(&sdata->skb_queue, skb);
wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work);
- if (sta)
- sta->deflink.rx_stats.packets++;
+ if (sta) {
+ struct link_sta_info *link_sta_info;
+
+ if (link_id >= 0) {
+ link_sta_info = rcu_dereference(sta->link[link_id]);
+ if (!link_sta_info)
+ return;
+ } else {
+ link_sta_info = &sta->deflink;
+ }
+
+ link_sta_info->rx_stats.packets++;
+ }
}
static void ieee80211_queue_skb_to_iface(struct ieee80211_sub_if_data *sdata,
@@ -1521,9 +1532,8 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
}
if (rx->sdata->vif.type == NL80211_IFTYPE_AP &&
- cfg80211_rx_spurious_frame(rx->sdata->dev,
- hdr->addr2,
- GFP_ATOMIC))
+ cfg80211_rx_spurious_frame(rx->sdata->dev, hdr->addr2,
+ rx->link_id, GFP_ATOMIC))
return RX_DROP_U_SPURIOUS;
return RX_DROP;
@@ -1861,7 +1871,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
if (!test_and_set_sta_flag(sta, WLAN_STA_4ADDR_EVENT))
cfg80211_rx_unexpected_4addr_frame(
rx->sdata->dev, sta->sta.addr,
- GFP_ATOMIC);
+ rx->link_id, GFP_ATOMIC);
return RX_DROP_U_UNEXPECTED_4ADDR_FRAME;
}
/*
@@ -3022,7 +3032,6 @@ __ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset)
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
__le16 fc = hdr->frame_control;
struct sk_buff_head frame_list;
- ieee80211_rx_result res;
struct ethhdr ethhdr;
const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source;
@@ -3084,24 +3093,18 @@ __ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset)
while (!skb_queue_empty(&frame_list)) {
rx->skb = __skb_dequeue(&frame_list);
- res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb);
- switch (res) {
+ switch (ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb)) {
case RX_QUEUED:
- continue;
- case RX_CONTINUE:
break;
+ case RX_CONTINUE:
+ if (ieee80211_frame_allowed(rx, fc)) {
+ ieee80211_deliver_skb(rx);
+ break;
+ }
+ fallthrough;
default:
- goto free;
+ dev_kfree_skb(rx->skb);
}
-
- if (!ieee80211_frame_allowed(rx, fc))
- goto free;
-
- ieee80211_deliver_skb(rx);
- continue;
-
-free:
- dev_kfree_skb(rx->skb);
}
return RX_QUEUED;
@@ -3187,7 +3190,8 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
if (rx->sta &&
!test_and_set_sta_flag(rx->sta, WLAN_STA_4ADDR_EVENT))
cfg80211_rx_unexpected_4addr_frame(
- rx->sdata->dev, rx->sta->sta.addr, GFP_ATOMIC);
+ rx->sdata->dev, rx->sta->sta.addr, rx->link_id,
+ GFP_ATOMIC);
return RX_DROP;
}
@@ -5102,8 +5106,24 @@ static bool ieee80211_rx_for_interface(struct ieee80211_rx_data *rx,
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
sta = sta_info_get_bss(rx->sdata, hdr->addr2);
- if (status->link_valid)
+ if (status->link_valid) {
link_id = status->link_id;
+ } else if (ieee80211_vif_is_mld(&rx->sdata->vif) &&
+ status->freq) {
+ struct ieee80211_link_data *link;
+ struct ieee80211_chanctx_conf *conf;
+
+ for_each_link_data_rcu(rx->sdata, link) {
+ conf = rcu_dereference(link->conf->chanctx_conf);
+ if (!conf || !conf->def.chan)
+ continue;
+
+ if (status->freq == conf->def.chan->center_freq) {
+ link_id = link->link_id;
+ break;
+ }
+ }
+ }
}
if (!ieee80211_rx_data_set_sta(rx, sta, link_id))