From: Aditya Sathish <[email protected]>

When a non-AP MLD is getting added or having its capabilities updated,
handle the SMD parameters passed from userspace. Otherwise, drivers will
not be able to identify that the non-AP MLD has negotiated SMD with this
AP MLD during association nor can they support SMD BSS Transition if it
has been requested later by the non-AP MLD.

Signed-off-by: Aditya Sathish <[email protected]>
Co-developed-by: Sidhanta Sahu <[email protected]>
Signed-off-by: Sidhanta Sahu <[email protected]>
Co-developed-by: Pooventhiran G <[email protected]>
Signed-off-by: Pooventhiran G <[email protected]>
---
 include/net/cfg80211.h       | 15 +++++++++++++
 include/net/mac80211.h       |  3 +++
 include/uapi/linux/nl80211.h | 17 ++++++++++++++
 net/mac80211/cfg.c           | 10 +++++++++
 net/mac80211/debugfs_sta.c   |  1 +
 net/mac80211/sta_info.h      |  2 ++
 net/wireless/nl80211.c       | 53 ++++++++++++++++++++++++++++++++++++++------
 7 files changed, 94 insertions(+), 7 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index df85dc804c50..51fb64a837fd 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1897,6 +1897,19 @@ struct cfg80211_ttlm_params {
        u16 ulink[8];
 };
 
+/**
+ * struct cfg80211_sta_smd_params - SMD parameters for an added station
+ *
+ * @smd_sta: SMD-negotiated STA
+ * @smd_identifier: SMD Identifier
+ * @dl_data_fwd: MSDU forwarding supported
+ */
+struct cfg80211_sta_smd_params {
+       bool smd_sta;
+       u8 smd_identifier[ETH_ALEN];
+       bool dl_data_fwd;
+};
+
 /**
  * struct station_parameters - station parameters
  *
@@ -1937,6 +1950,7 @@ struct cfg80211_ttlm_params {
  * @link_sta_params: link related params.
  * @epp_peer: EPP peer indication
  * @nmi_mac: MAC address of the NMI station of the NAN peer
+ * @smd_params: SMD params for this station
  */
 struct station_parameters {
        struct net_device *vlan;
@@ -1965,6 +1979,7 @@ struct station_parameters {
        struct link_station_parameters link_sta_params;
        bool epp_peer;
        const u8 *nmi_mac;
+       struct cfg80211_sta_smd_params smd_params;
 };
 
 /**
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 3a5011945eed..39d67c054ae6 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2726,6 +2726,7 @@ struct ieee80211_link_sta {
  * @nan_sched: NAN peer schedule for this station. Valid only for NMI stations.
  * @ext_mld_capa_ops: the MLD's extended MLD capabilities and operations
  *     NOTE: currently only tracked for AP STAs
+ * @smd_params: SMD parameters of the STA
  */
 struct ieee80211_sta {
        u8 addr[ETH_ALEN] __aligned(2);
@@ -2760,6 +2761,8 @@ struct ieee80211_sta {
        /* should only be accessed with the wiphy mutex held */
        struct ieee80211_nan_peer_sched *nan_sched;
 
+       struct cfg80211_sta_smd_params smd_params;
+
        /* must be last */
        u8 drv_priv[] __aligned(sizeof(void *));
 };
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 1177a511c8cb..265c5883e6cf 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3196,6 +3196,17 @@ enum nl80211_commands {
  *     %NL80211_EXT_FEATURE_SMD.
  *     Used with %NL80211_CMD_START_AP. See &enum nl80211_smd_params_attrs.
  *
+ * @NL80211_ATTR_PEER_SMD_ENABLED: Flag indicating a peer STA has SMD enabled.
+ *     Used with %NL80211_CMD_NEW_STATION and %NL80211_CMD_SET_STATION.
+ *
+ * @NL80211_ATTR_PEER_SMD_MAC_ADDR: Binary attribute with the 6-byte MAC
+ *     address of the SMD-capable peer STA.
+ *     Used with %NL80211_CMD_NEW_STATION and %NL80211_CMD_SET_STATION.
+ *
+ * @NL80211_ATTR_PEER_SMD_DL_DATA_FORWARDING: Flag indicating the peer STA
+ *     supports DL data forwarding within the SMD domain.
+ *     Used with %NL80211_CMD_NEW_STATION and %NL80211_CMD_SET_STATION.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3800,6 +3811,10 @@ enum nl80211_attrs {
 
        NL80211_ATTR_SMD_PARAMS,
 
+       NL80211_ATTR_PEER_SMD_ENABLED,
+       NL80211_ATTR_PEER_SMD_MAC_ADDR,
+       NL80211_ATTR_PEER_SMD_DL_DATA_FORWARDING,
+
        /* add attributes here, update the policy in nl80211.c */
 
        __NL80211_ATTR_AFTER_LAST,
@@ -3950,6 +3965,7 @@ enum nl80211_iftype {
  *     that support %NL80211_FEATURE_FULL_AP_CLIENT_STATE to transition a
  *     previously added station into associated state
  * @NL80211_STA_FLAG_SPP_AMSDU: station supports SPP A-MSDUs
+ * @NL80211_STA_FLAG_SMD: station has negotiated SMD.
  * @NL80211_STA_FLAG_MAX: highest station flag number currently defined
  * @__NL80211_STA_FLAG_AFTER_LAST: internal use
  */
@@ -3963,6 +3979,7 @@ enum nl80211_sta_flags {
        NL80211_STA_FLAG_TDLS_PEER,
        NL80211_STA_FLAG_ASSOCIATED,
        NL80211_STA_FLAG_SPP_AMSDU,
+       NL80211_STA_FLAG_SMD,
 
        /* keep last */
        __NL80211_STA_FLAG_AFTER_LAST,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index b4b42790c5d7..138b67f4bda4 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2528,6 +2528,16 @@ static int sta_apply_parameters(struct ieee80211_local 
*local,
        if (mask & BIT(NL80211_STA_FLAG_SPP_AMSDU))
                sta->sta.spp_amsdu = set & BIT(NL80211_STA_FLAG_SPP_AMSDU);
 
+       if (mask & BIT(NL80211_STA_FLAG_SMD)) {
+               if (set & BIT(NL80211_STA_FLAG_SMD))
+                       set_sta_flag(sta, WLAN_STA_SMD);
+               else if (test_sta_flag(sta, WLAN_STA_SMD))
+                       clear_sta_flag(sta, WLAN_STA_SMD);
+       }
+
+       if (params->smd_params.smd_sta)
+               sta->sta.smd_params = params->smd_params;
+
        /* mark TDLS channel switch support, if the AP allows it */
        if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
            !sdata->deflink.u.mgd.tdls_chan_switch_prohibited &&
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index ef75255d47d5..d7e7c9c578e4 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -78,6 +78,7 @@ static const char * const sta_flag_names[] = {
        FLAG(PS_DELIVER),
        FLAG(USES_ENCRYPTION),
        FLAG(DECAP_OFFLOAD),
+       FLAG(SMD),
 #undef FLAG
 };
 
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index ee0d32877c5b..506aeb241a6d 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -72,6 +72,7 @@
  * @WLAN_STA_USES_ENCRYPTION: This station was configured for encryption,
  *     so drop all packets without a key later.
  * @WLAN_STA_DECAP_OFFLOAD: This station uses rx decap offload
+ * @WLAN_STA_SMD: this station is associated to an SMD-ME.
  *
  * @NUM_WLAN_STA_FLAGS: number of defined flags
  */
@@ -104,6 +105,7 @@ enum ieee80211_sta_info_flags {
        WLAN_STA_PS_DELIVER,
        WLAN_STA_USES_ENCRYPTION,
        WLAN_STA_DECAP_OFFLOAD,
+       WLAN_STA_SMD,
 
        NUM_WLAN_STA_FLAGS,
 };
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b4ff784d131b..76fb83f61b89 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1115,6 +1115,9 @@ static const struct nla_policy 
nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_FRAME_NO_STA] = { .type = NLA_FLAG },
        [NL80211_ATTR_SMD_PARAMS] =
                NLA_POLICY_NESTED(nl80211_smd_params_policy),
+       [NL80211_ATTR_PEER_SMD_ENABLED] = { .type = NLA_FLAG },
+       [NL80211_ATTR_PEER_SMD_MAC_ADDR] = NLA_POLICY_ETH_ADDR,
+       [NL80211_ATTR_PEER_SMD_DL_DATA_FORWARDING] = { .type = NLA_FLAG },
 };
 
 /* policy for the key attributes */
@@ -7703,6 +7706,7 @@ static const struct nla_policy 
sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
        [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG },
        [NL80211_STA_FLAG_AUTHENTICATED] = { .type = NLA_FLAG },
        [NL80211_STA_FLAG_TDLS_PEER] = { .type = NLA_FLAG },
+       [NL80211_STA_FLAG_SMD] = { .type = NLA_FLAG },
 };
 
 static int parse_station_flags(struct genl_info *info,
@@ -7769,11 +7773,13 @@ static int parse_station_flags(struct genl_info *info,
        switch (iftype) {
        case NL80211_IFTYPE_AP:
        case NL80211_IFTYPE_AP_VLAN:
+               params->sta_flags_mask = BIT(NL80211_STA_FLAG_SMD);
+               fallthrough;
        case NL80211_IFTYPE_P2P_GO:
-               params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
-                                        BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
-                                        BIT(NL80211_STA_FLAG_WME) |
-                                        BIT(NL80211_STA_FLAG_MFP);
+               params->sta_flags_mask |= BIT(NL80211_STA_FLAG_AUTHORIZED) |
+                                         BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
+                                         BIT(NL80211_STA_FLAG_WME) |
+                                         BIT(NL80211_STA_FLAG_MFP);
                break;
        case NL80211_IFTYPE_P2P_CLIENT:
        case NL80211_IFTYPE_STATION:
@@ -8914,7 +8920,7 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
                return -EINVAL;
 
        /* When you run into this, adjust the code below for the new flag */
-       BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 8);
+       BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 9);
 
        switch (statype) {
        case CFG80211_STA_MESH_PEER_KERNEL:
@@ -9008,7 +9014,8 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
                                  BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
                                  BIT(NL80211_STA_FLAG_WME) |
                                  BIT(NL80211_STA_FLAG_MFP) |
-                                 BIT(NL80211_STA_FLAG_SPP_AMSDU)))
+                                 BIT(NL80211_STA_FLAG_SPP_AMSDU) |
+                                 BIT(NL80211_STA_FLAG_SMD)))
                        return -EINVAL;
 
                /* but authenticated/associated only if driver handles it */
@@ -9262,6 +9269,30 @@ static int nl80211_parse_sta_txpower_setting(struct 
genl_info *info,
        return 0;
 }
 
+static int nl80211_set_station_smd(struct genl_info *info,
+                                  struct station_parameters *params)
+{
+       struct nlattr *smd_mac;
+
+       params->smd_params.smd_sta =
+               !!info->attrs[NL80211_ATTR_PEER_SMD_ENABLED];
+
+       if (!params->smd_params.smd_sta)
+               return 0;
+
+       smd_mac = info->attrs[NL80211_ATTR_PEER_SMD_MAC_ADDR];
+
+       if (!info->attrs[NL80211_ATTR_MLD_ADDR] || !smd_mac)
+               return -EINVAL;
+
+       nla_memcpy(params->smd_params.smd_identifier, smd_mac, ETH_ALEN);
+
+       params->smd_params.dl_data_fwd =
+               !!info->attrs[NL80211_ATTR_PEER_SMD_DL_DATA_FORWARDING];
+
+       return 0;
+}
+
 static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
 {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -9400,6 +9431,10 @@ static int nl80211_set_station(struct sk_buff *skb, 
struct genl_info *info)
        if (err)
                return err;
 
+       err = nl80211_set_station_smd(info, &params);
+       if (err)
+               return err;
+
        /* Include parameters for TDLS peer (will check later) */
        err = nl80211_set_station_tdls(info, &params);
        if (err)
@@ -9628,6 +9663,10 @@ static int nl80211_new_station(struct sk_buff *skb, 
struct genl_info *info)
        if (parse_station_flags(info, wdev->iftype, &params))
                return -EINVAL;
 
+       err = nl80211_set_station_smd(info, &params);
+       if (err)
+               return err;
+
        /* HT/VHT requires QoS, but if we don't have that just ignore HT/VHT
         * as userspace might just pass through the capabilities from the IEs
         * directly, rather than enforcing this restriction and returning an
@@ -9661,7 +9700,7 @@ static int nl80211_new_station(struct sk_buff *skb, 
struct genl_info *info)
                return -EINVAL;
 
        /* When you run into this, adjust the code below for the new flag */
-       BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 8);
+       BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 9);
 
        switch (wdev->iftype) {
        case NL80211_IFTYPE_AP:

-- 
2.34.1


Reply via email to