wifi: cfg80211: Add support for setting TID to link mapping
authorIlan Peer <ilan.peer@intel.com>
Mon, 11 Dec 2023 07:05:22 +0000 (09:05 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 12 Dec 2023 09:37:00 +0000 (10:37 +0100)
Add support for setting the TID to link mapping for a non-AP MLD
station.

This is useful in cases user space needs to restrict the possible
set of active links, e.g., since it got a BSS Transition Management
request forcing to use only a subset of the valid links etc.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Reviewed-by: Gregory Greenman <gregory.greenman@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20231211085121.da4d56a5f3ff.Iacf88e943326bf9c169c49b728c4a3445fdedc97@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/cfg80211.h
include/uapi/linux/nl80211.h
net/wireless/nl80211.c
net/wireless/rdev-ops.h
net/wireless/trace.h

index cabe57a00eaf57f6ad3788a6c8e9d8c19c0fbe51..4d6b9d801c2fd3992d9fcc39b2d7550ff275947e 100644 (file)
@@ -1673,6 +1673,21 @@ struct link_station_del_parameters {
        u32 link_id;
 };
 
+/**
+ * struct cfg80211_ttlm_params: TID to link mapping parameters
+ *
+ * Used for setting a TID to link mapping.
+ *
+ * @dlink: Downlink TID to link mapping, as defined in section 9.4.2.314
+ *     (TID-To-Link Mapping element) in Draft P802.11be_D4.0.
+ * @ulink: Uplink TID to link mapping, as defined in section 9.4.2.314
+ *     (TID-To-Link Mapping element) in Draft P802.11be_D4.0.
+ */
+struct cfg80211_ttlm_params {
+       u16 dlink[8];
+       u16 ulink[8];
+};
+
 /**
  * struct station_parameters - station parameters
  *
@@ -4523,6 +4538,7 @@ struct mgmt_frame_regs {
  * @del_link_station: Remove a link of a station.
  *
  * @set_hw_timestamp: Enable/disable HW timestamping of TM/FTM frames.
+ * @set_ttlm: set the TID to link mapping.
  */
 struct cfg80211_ops {
        int     (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -4882,6 +4898,8 @@ struct cfg80211_ops {
                                    struct link_station_del_parameters *params);
        int     (*set_hw_timestamp)(struct wiphy *wiphy, struct net_device *dev,
                                    struct cfg80211_set_hw_timestamp *hwts);
+       int     (*set_ttlm)(struct wiphy *wiphy, struct net_device *dev,
+                           struct cfg80211_ttlm_params *params);
 };
 
 /*
index 07fc1fec4b12a299d899a13d0ac126bf57cc6c6c..2d8468cbc457e86ddfc0710ac7504795227eebbe 100644 (file)
  *     Multi-Link reconfiguration. %NL80211_ATTR_MLO_LINKS is used to provide
  *     information about the removed STA MLD setup links.
  *
+ * @NL80211_CMD_SET_TID_TO_LINK_MAPPING: Set the TID to Link Mapping for a
+ *      non-AP MLD station. The %NL80211_ATTR_MLO_TTLM_DLINK and
+ *      %NL80211_ATTR_MLO_TTLM_ULINK attributes are used to specify the
+ *      TID to Link mapping for downlink/uplink traffic.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1583,6 +1588,8 @@ enum nl80211_commands {
 
        NL80211_CMD_LINKS_REMOVED,
 
+       NL80211_CMD_SET_TID_TO_LINK_MAPPING,
+
        /* add new commands above here */
 
        /* used to define NL80211_CMD_MAX below */
@@ -2835,6 +2842,15 @@ enum nl80211_commands {
  *     include BSSes that can only be used in restricted scenarios and/or
  *     cannot be used at all.
  *
+ * @NL80211_ATTR_MLO_TTLM_DLINK: Binary attribute specifying the downlink TID to
+ *      link mapping. The length is 8 * sizeof(u16). For each TID the link
+ *      mapping is as defined in section 9.4.2.314 (TID-To-Link Mapping element)
+ *      in Draft P802.11be_D4.0.
+ * @NL80211_ATTR_MLO_TTLM_ULINK: Binary attribute specifying the uplink TID to
+ *      link mapping. The length is 8 * sizeof(u16). For each TID the link
+ *      mapping is as defined in section 9.4.2.314 (TID-To-Link Mapping element)
+ *      in Draft P802.11be_D4.0.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3375,6 +3391,9 @@ enum nl80211_attrs {
 
        NL80211_ATTR_BSS_DUMP_INCLUDE_USE_DATA,
 
+       NL80211_ATTR_MLO_TTLM_DLINK,
+       NL80211_ATTR_MLO_TTLM_ULINK,
+
        /* add attributes here, update the policy in nl80211.c */
 
        __NL80211_ATTR_AFTER_LAST,
index 2820336511a2b2794fb04e4144bcf5b3304a01db..0dec06cdf2536c5951c03fcdd060dd93faf521b8 100644 (file)
@@ -819,6 +819,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_EMA_RNR_ELEMS] = { .type = NLA_NESTED },
        [NL80211_ATTR_MLO_LINK_DISABLED] = { .type = NLA_FLAG },
        [NL80211_ATTR_BSS_DUMP_INCLUDE_USE_DATA] = { .type = NLA_FLAG },
+       [NL80211_ATTR_MLO_TTLM_DLINK] = NLA_POLICY_EXACT_LEN(sizeof(u16) * 8),
+       [NL80211_ATTR_MLO_TTLM_ULINK] = NLA_POLICY_EXACT_LEN(sizeof(u16) * 8),
 };
 
 /* policy for the key attributes */
@@ -16298,6 +16300,35 @@ static int nl80211_set_hw_timestamp(struct sk_buff *skb,
        return rdev_set_hw_timestamp(rdev, dev, &hwts);
 }
 
+static int
+nl80211_set_ttlm(struct sk_buff *skb, struct genl_info *info)
+{
+       struct cfg80211_ttlm_params params = {};
+       struct cfg80211_registered_device *rdev = info->user_ptr[0];
+       struct net_device *dev = info->user_ptr[1];
+       struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+       if (wdev->iftype != NL80211_IFTYPE_STATION &&
+           wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
+               return -EOPNOTSUPP;
+
+       if (!wdev->connected)
+               return -ENOLINK;
+
+       if (!info->attrs[NL80211_ATTR_MLO_TTLM_DLINK] ||
+           !info->attrs[NL80211_ATTR_MLO_TTLM_ULINK])
+               return -EINVAL;
+
+       nla_memcpy(params.dlink,
+                  info->attrs[NL80211_ATTR_MLO_TTLM_DLINK],
+                  sizeof(params.dlink));
+       nla_memcpy(params.ulink,
+                  info->attrs[NL80211_ATTR_MLO_TTLM_ULINK],
+                  sizeof(params.ulink));
+
+       return rdev_set_ttlm(rdev, dev, &params);
+}
+
 #define NL80211_FLAG_NEED_WIPHY                0x01
 #define NL80211_FLAG_NEED_NETDEV       0x02
 #define NL80211_FLAG_NEED_RTNL         0x04
@@ -17479,6 +17510,12 @@ static const struct genl_small_ops nl80211_small_ops[] = {
                .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
        },
+       {
+               .cmd = NL80211_CMD_SET_TID_TO_LINK_MAPPING,
+               .doit = nl80211_set_ttlm,
+               .flags = GENL_UNS_ADMIN_PERM,
+               .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
+       },
 };
 
 static struct genl_family nl80211_fam __ro_after_init = {
index 2214a90cf1012cb16f1f8ac27d9a4e364c400e2b..2a27a34487599d2d16e073bfc9e818a82e303b4a 100644 (file)
@@ -1524,4 +1524,22 @@ rdev_set_hw_timestamp(struct cfg80211_registered_device *rdev,
 
        return ret;
 }
+
+static inline int
+rdev_set_ttlm(struct cfg80211_registered_device *rdev,
+             struct net_device *dev,
+             struct cfg80211_ttlm_params *params)
+{
+       struct wiphy *wiphy = &rdev->wiphy;
+       int ret;
+
+       if (!rdev->ops->set_ttlm)
+               return -EOPNOTSUPP;
+
+       trace_rdev_set_ttlm(wiphy, dev, params);
+       ret = rdev->ops->set_ttlm(wiphy, dev, params);
+       trace_rdev_return_int(wiphy, ret);
+
+       return ret;
+}
 #endif /* __CFG80211_RDEV_OPS */
index 4de710efa47ee4362f1a79f8b93b32f53f487443..1f374c8a17a505d8d1fa31d0a09ae336dcad704c 100644 (file)
@@ -3979,6 +3979,26 @@ TRACE_EVENT(cfg80211_links_removed,
                  __entry->link_mask)
 );
 
+TRACE_EVENT(rdev_set_ttlm,
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                struct cfg80211_ttlm_params *params),
+       TP_ARGS(wiphy, netdev, params),
+       TP_STRUCT__entry(
+               WIPHY_ENTRY
+               NETDEV_ENTRY
+               __array(u8, dlink, sizeof(u16) * 8)
+               __array(u8, ulink, sizeof(u16) * 8)
+       ),
+       TP_fast_assign(
+               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
+               memcpy(__entry->dlink, params->dlink, sizeof(params->dlink));
+               memcpy(__entry->ulink, params->ulink, sizeof(params->ulink));
+       ),
+       TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT,
+                 WIPHY_PR_ARG, NETDEV_PR_ARG)
+);
+
 #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
 
 #undef TRACE_INCLUDE_PATH