aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2022-07-14 23:47:32 +0200
committerJohannes Berg <johannes.berg@intel.com>2022-07-15 11:43:23 +0200
commit42fb9148c078004d07b4c39bd7b1086b6165780c (patch)
tree321eec9a4a49c254f475fcd9c66ae9e3862f5f7b /net/mac80211/rx.c
parentwifi: mac80211: select link when transmitting to non-MLO stations (diff)
downloadlinux-dev-42fb9148c078004d07b4c39bd7b1086b6165780c.tar.xz
linux-dev-42fb9148c078004d07b4c39bd7b1086b6165780c.zip
wifi: mac80211: do link->MLD address translation on RX
In some cases, e.g. with Qualcomm devices and management frames, or in hwsim, frames may be reported from the driver with link addresses, but for decryption and matching needs we really want to have them with MLD addresses. Support the translation on RX. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 9f1ea8c840e9..cad4b2378218 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -4724,6 +4724,9 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
{
struct ieee80211_local *local = rx->local;
struct ieee80211_sub_if_data *sdata = rx->sdata;
+ struct ieee80211_hdr *hdr = (void *)skb->data;
+ struct link_sta_info *link_sta = NULL;
+ struct ieee80211_link_data *link;
rx->skb = skb;
@@ -4745,6 +4748,15 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
if (!ieee80211_accept_frame(rx))
return false;
+ if (unlikely(!is_multicast_ether_addr(hdr->addr1) &&
+ rx->link_id >= 0 && rx->sta && rx->sta->sta.mlo)) {
+ link_sta = rcu_dereference(rx->sta->link[rx->link_id]);
+ link = rcu_dereference(rx->sdata->link[rx->link_id]);
+
+ if (WARN_ON_ONCE(!link_sta || !link))
+ return true;
+ }
+
if (!consume) {
skb = skb_copy(skb, GFP_ATOMIC);
if (!skb) {
@@ -4758,6 +4770,19 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
rx->skb = skb;
}
+ if (unlikely(link_sta)) {
+ /* translate to MLD addresses */
+ if (ether_addr_equal(link->conf->addr, hdr->addr1))
+ ether_addr_copy(hdr->addr1, rx->sdata->vif.addr);
+ if (ether_addr_equal(link_sta->addr, hdr->addr2))
+ ether_addr_copy(hdr->addr2, rx->sta->addr);
+ if (ether_addr_equal(link_sta->addr, hdr->addr3))
+ ether_addr_copy(hdr->addr3, rx->sta->addr);
+ else if (ether_addr_equal(link->conf->addr, hdr->addr3))
+ ether_addr_copy(hdr->addr3, rx->sdata->vif.addr);
+ /* not needed for A4 since it can only carry the SA */
+ }
+
ieee80211_invoke_rx_handlers(rx);
return true;
}