summaryrefslogtreecommitdiff
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/tx.c')
-rw-r--r--net/mac80211/tx.c44
1 files changed, 31 insertions, 13 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 7e2d68e0d79f..7fe7280e8437 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -845,7 +845,7 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
/* SNS11 from 802.11be 10.3.2.14 */
if (unlikely(is_multicast_ether_addr(hdr->addr1) &&
- info->control.vif->valid_links &&
+ ieee80211_vif_is_mld(info->control.vif) &&
info->control.vif->type == NL80211_IFTYPE_AP)) {
if (info->control.flags & IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX)
tx->sdata->mld_mcast_seq += 0x10;
@@ -2611,7 +2611,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
ethertype = (skb->data[12] << 8) | skb->data[13];
fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
- if (!sdata->vif.valid_links)
+ if (!ieee80211_vif_is_mld(&sdata->vif))
chanctx_conf =
rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
@@ -2628,7 +2628,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
wme_sta = sta->sta.wme;
}
- if (!sdata->vif.valid_links) {
+ if (!ieee80211_vif_is_mld(&sdata->vif)) {
struct ieee80211_sub_if_data *ap_sdata;
/* override chanctx_conf from AP (we don't have one) */
@@ -2646,7 +2646,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
/* DA BSSID SA */
memcpy(hdr.addr1, skb->data, ETH_ALEN);
- if (sdata->vif.valid_links && sta && !sta->sta.mlo) {
+ if (ieee80211_vif_is_mld(&sdata->vif) && sta && !sta->sta.mlo) {
struct ieee80211_link_data *link;
link_id = sta->deflink.link_id;
@@ -2754,10 +2754,20 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
tdls_peer = test_sta_flag(sta, WLAN_STA_TDLS_PEER);
if (tdls_peer) {
+ /* For TDLS only one link can be valid with peer STA */
+ int tdls_link_id = sta->sta.valid_links ?
+ __ffs(sta->sta.valid_links) : 0;
+ struct ieee80211_link_data *link;
+
/* DA SA BSSID */
memcpy(hdr.addr1, skb->data, ETH_ALEN);
memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
- memcpy(hdr.addr3, sdata->deflink.u.mgd.bssid, ETH_ALEN);
+ link = rcu_dereference(sdata->link[tdls_link_id]);
+ if (WARN_ON_ONCE(!link)) {
+ ret = -EINVAL;
+ goto free;
+ }
+ memcpy(hdr.addr3, link->u.mgd.bssid, ETH_ALEN);
hdrlen = 24;
} else if (sdata->u.mgd.use_4addr &&
cpu_to_be16(ethertype) != sdata->control_port_protocol) {
@@ -2798,7 +2808,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
}
if (!chanctx_conf) {
- if (!sdata->vif.valid_links) {
+ if (!ieee80211_vif_is_mld(&sdata->vif)) {
ret = -ENOTCONN;
goto free;
}
@@ -3040,7 +3050,7 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG))
goto out;
- if (!sdata->vif.valid_links) {
+ if (!ieee80211_vif_is_mld(&sdata->vif)) {
rcu_read_lock();
chanctx_conf =
rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
@@ -3067,10 +3077,18 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
break;
case NL80211_IFTYPE_STATION:
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
+ /* For TDLS only one link can be valid with peer STA */
+ int tdls_link_id = sta->sta.valid_links ?
+ __ffs(sta->sta.valid_links) : 0;
+ struct ieee80211_link_data *link;
+
/* DA SA BSSID */
build.da_offs = offsetof(struct ieee80211_hdr, addr1);
build.sa_offs = offsetof(struct ieee80211_hdr, addr2);
- memcpy(hdr->addr3, sdata->deflink.u.mgd.bssid, ETH_ALEN);
+ link = rcu_dereference(sdata->link[tdls_link_id]);
+ if (WARN_ON_ONCE(!link))
+ break;
+ memcpy(hdr->addr3, link->u.mgd.bssid, ETH_ALEN);
build.hdr_len = 24;
break;
}
@@ -3111,7 +3129,7 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
/* DA BSSID SA */
build.da_offs = offsetof(struct ieee80211_hdr, addr1);
- if (sta->sta.mlo || !sdata->vif.valid_links) {
+ if (sta->sta.mlo || !ieee80211_vif_is_mld(&sdata->vif)) {
memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
} else {
unsigned int link_id = sta->deflink.link_id;
@@ -4480,7 +4498,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
__ieee80211_subif_start_xmit(skb, dev, 0,
IEEE80211_TX_CTRL_MLO_LINK_UNSPEC,
NULL);
- } else if (sdata->vif.valid_links &&
+ } else if (ieee80211_vif_is_mld(&sdata->vif) &&
sdata->vif.type == NL80211_IFTYPE_AP &&
!ieee80211_hw_check(&sdata->local->hw, MLO_MCAST_MULTI_LINK_TX)) {
ieee80211_mlo_multicast_tx(dev, skb);
@@ -4756,7 +4774,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
if (info->control.flags & IEEE80211_TX_INTCFL_NEED_TXPROCESSING) {
/* update band only for non-MLD */
- if (!sdata->vif.valid_links) {
+ if (!ieee80211_vif_is_mld(&sdata->vif)) {
chanctx_conf =
rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
if (unlikely(!chanctx_conf)) {
@@ -6003,7 +6021,7 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
BUILD_BUG_ON(!FIELD_FIT(IEEE80211_TX_CTRL_MLO_LINK,
IEEE80211_LINK_UNSPECIFIED));
- if (!sdata->vif.valid_links) {
+ if (!ieee80211_vif_is_mld(&sdata->vif)) {
link = 0;
} else if (link_id >= 0) {
link = link_id;
@@ -6049,7 +6067,7 @@ void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
enum nl80211_band band;
rcu_read_lock();
- if (!sdata->vif.valid_links) {
+ if (!ieee80211_vif_is_mld(&sdata->vif)) {
WARN_ON(link_id >= 0);
chanctx_conf =
rcu_dereference(sdata->vif.bss_conf.chanctx_conf);