wifi: mac80211: extend ieee80211_nullfunc_get() for MLO
authorJohannes Berg <johannes.berg@intel.com>
Fri, 2 Sep 2022 14:12:47 +0000 (16:12 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 6 Sep 2022 08:14:24 +0000 (10:14 +0200)
Add a link_id parameter to ieee80211_nullfunc_get() to be
able to obtain a correctly addressed frame.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/ath/ath9k/channel.c
drivers/net/wireless/realtek/rtw88/fw.c
drivers/net/wireless/st/cw1200/sta.c
drivers/net/wireless/ti/wl1251/main.c
drivers/net/wireless/ti/wlcore/cmd.c
include/net/mac80211.h
net/mac80211/mlme.c
net/mac80211/tx.c

index 6cf08752215725fdcf47a16de94241c2132e216a..571062f2e82a7ba39f3bffb569168f3a5007e016 100644 (file)
@@ -1113,7 +1113,7 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp,
                if (!avp->assoc)
                        return false;
 
-               skb = ieee80211_nullfunc_get(sc->hw, vif, false);
+               skb = ieee80211_nullfunc_get(sc->hw, vif, -1, false);
                if (!skb)
                        return false;
 
index babba68a71325fe5b643fe0b7f2f3c071d14b539..7f6fdebae203fe5b85191eae4a11c9fe6d7477fa 100644 (file)
@@ -1082,10 +1082,10 @@ static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw,
                skb_new = ieee80211_proberesp_get(hw, vif);
                break;
        case RSVD_NULL:
-               skb_new = ieee80211_nullfunc_get(hw, vif, false);
+               skb_new = ieee80211_nullfunc_get(hw, vif, -1, false);
                break;
        case RSVD_QOS_NULL:
-               skb_new = ieee80211_nullfunc_get(hw, vif, true);
+               skb_new = ieee80211_nullfunc_get(hw, vif, -1, true);
                break;
        case RSVD_LPS_PG_DPK:
                skb_new = rtw_lps_pg_dpk_get(hw);
index 26d3614519b1f3c1ed892d49902266ef8bab7f03..8ef1d06b9bbddb1808fb6965482fbefdefab4bb2 100644 (file)
@@ -195,7 +195,7 @@ void __cw1200_cqm_bssloss_sm(struct cw1200_common *priv,
 
                priv->bss_loss_state++;
 
-               skb = ieee80211_nullfunc_get(priv->hw, priv->vif, false);
+               skb = ieee80211_nullfunc_get(priv->hw, priv->vif, -1, false);
                WARN_ON(!skb);
                if (skb)
                        cw1200_tx(priv->hw, NULL, skb);
@@ -2263,7 +2263,7 @@ static int cw1200_upload_null(struct cw1200_common *priv)
                .rate = 0xFF,
        };
 
-       frame.skb = ieee80211_nullfunc_get(priv->hw, priv->vif, false);
+       frame.skb = ieee80211_nullfunc_get(priv->hw, priv->vif,-1, false);
        if (!frame.skb)
                return -ENOMEM;
 
index 9144ef5538a8e249a42c2b5074f88c50a5285658..289371689a8deb728039bcfe205374df8829280b 100644 (file)
@@ -546,7 +546,7 @@ static int wl1251_build_null_data(struct wl1251 *wl)
                size = sizeof(struct wl12xx_null_data_template);
                ptr = NULL;
        } else {
-               skb = ieee80211_nullfunc_get(wl->hw, wl->vif, false);
+               skb = ieee80211_nullfunc_get(wl->hw, wl->vif, -1, false);
                if (!skb)
                        goto out;
                size = skb->len;
index 138edd28b0de045238cc6beacb480c8f742210d8..a939fd89a7f5e4f5dbaf07dcb6fc3bcc48c7c55a 100644 (file)
@@ -1065,7 +1065,7 @@ int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif)
        } else {
                skb = ieee80211_nullfunc_get(wl->hw,
                                             wl12xx_wlvif_to_vif(wlvif),
-                                            false);
+                                            -1, false);
                if (!skb)
                        goto out;
                size = skb->len;
@@ -1092,7 +1092,7 @@ int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl,
        struct sk_buff *skb = NULL;
        int ret = -ENOMEM;
 
-       skb = ieee80211_nullfunc_get(wl->hw, vif, false);
+       skb = ieee80211_nullfunc_get(wl->hw, vif,-1, false);
        if (!skb)
                goto out;
 
index 954cc029a9f9d1c0b35cf139515e0baf0da99601..bfa6a1625c5c7c2045b32c041cb638d3134c4431 100644 (file)
@@ -5298,6 +5298,9 @@ struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
  * ieee80211_nullfunc_get - retrieve a nullfunc template
  * @hw: pointer obtained from ieee80211_alloc_hw().
  * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @link_id: If the vif is an MLD, get a frame with the link addresses
+ *     for the given link ID. For a link_id < 0 you get a frame with
+ *     MLD addresses, however useful that might be.
  * @qos_ok: QoS NDP is acceptable to the caller, this should be set
  *     if at all possible
  *
@@ -5315,7 +5318,7 @@ struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
  */
 struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
                                       struct ieee80211_vif *vif,
-                                      bool qos_ok);
+                                      int link_id, bool qos_ok);
 
 /**
  * ieee80211_probereq_get - retrieve a Probe Request template
index 609584493ce0410624d748e5dc4332ec6325384e..8e8607bf27dcc1c1db90487001c58e74045f608f 100644 (file)
@@ -1546,8 +1546,9 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local,
        struct ieee80211_hdr_3addr *nullfunc;
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
-       skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif,
-               !ieee80211_hw_check(&local->hw, DOESNT_SUPPORT_QOS_NDP));
+       skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif, -1,
+                                    !ieee80211_hw_check(&local->hw,
+                                                        DOESNT_SUPPORT_QOS_NDP));
        if (!skb)
                return;
 
index 1be8c9d83d6ae40f3ab0f981bc1ce6b2e5584863..a0967311756511b4756e1eae104ca115ef5eeda3 100644 (file)
@@ -5469,33 +5469,39 @@ EXPORT_SYMBOL(ieee80211_pspoll_get);
 
 struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
                                       struct ieee80211_vif *vif,
-                                      bool qos_ok)
+                                      int link_id, bool qos_ok)
 {
+       struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_link_data *link = NULL;
        struct ieee80211_hdr_3addr *nullfunc;
-       struct ieee80211_sub_if_data *sdata;
-       struct ieee80211_local *local;
        struct sk_buff *skb;
        bool qos = false;
 
        if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
                return NULL;
 
-       sdata = vif_to_sdata(vif);
-       local = sdata->local;
+       skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+                           sizeof(*nullfunc) + 2);
+       if (!skb)
+               return NULL;
 
+       rcu_read_lock();
        if (qos_ok) {
                struct sta_info *sta;
 
-               rcu_read_lock();
-               sta = sta_info_get(sdata, sdata->deflink.u.mgd.bssid);
+               sta = sta_info_get(sdata, vif->cfg.ap_addr);
                qos = sta && sta->sta.wme;
-               rcu_read_unlock();
        }
 
-       skb = dev_alloc_skb(local->hw.extra_tx_headroom +
-                           sizeof(*nullfunc) + 2);
-       if (!skb)
-               return NULL;
+       if (link_id >= 0) {
+               link = rcu_dereference(sdata->link[link_id]);
+               if (WARN_ON_ONCE(!link)) {
+                       rcu_read_unlock();
+                       kfree_skb(skb);
+                       return NULL;
+               }
+       }
 
        skb_reserve(skb, local->hw.extra_tx_headroom);
 
@@ -5516,9 +5522,16 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
                skb_put_data(skb, &qoshdr, sizeof(qoshdr));
        }
 
-       memcpy(nullfunc->addr1, sdata->deflink.u.mgd.bssid, ETH_ALEN);
-       memcpy(nullfunc->addr2, vif->addr, ETH_ALEN);
-       memcpy(nullfunc->addr3, sdata->deflink.u.mgd.bssid, ETH_ALEN);
+       if (link) {
+               memcpy(nullfunc->addr1, link->conf->bssid, ETH_ALEN);
+               memcpy(nullfunc->addr2, link->conf->addr, ETH_ALEN);
+               memcpy(nullfunc->addr3, link->conf->bssid, ETH_ALEN);
+       } else {
+               memcpy(nullfunc->addr1, vif->cfg.ap_addr, ETH_ALEN);
+               memcpy(nullfunc->addr2, vif->addr, ETH_ALEN);
+               memcpy(nullfunc->addr3, vif->cfg.ap_addr, ETH_ALEN);
+       }
+       rcu_read_unlock();
 
        return skb;
 }