Peer measurement capabilities currently advertise a single maximum peer count regardless of device role for proximity detection (PD). Some devices support different peer limits when operating as PD initiator versus PD responder. Introduce separate peer limit capabilities for each PD role. When a device supports concurrent initiator and responder operation, enforce the sum of both limits to prevent resource oversubscription. Signed-off-by: Peddolla Harshavardhan Reddy --- include/net/cfg80211.h | 12 ++++++++++++ include/uapi/linux/nl80211.h | 16 ++++++++++++++++ net/wireless/nl80211.c | 12 ++++++++++++ net/wireless/pmsr.c | 32 ++++++++++++++++++++++++++++---- 4 files changed, 68 insertions(+), 4 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index febd7bf50d88..8bbca2a98ac1 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -5776,6 +5776,16 @@ cfg80211_get_iftype_ext_capa(struct wiphy *wiphy, enum nl80211_iftype type); * multi-peer request this will indicate if the device can act * simultaneously as initiator and a responder. Only valid if @pd_support * is set. + * @pd_max_peer_ista_role: Maximum number of peers allowed for a device + * operating in the ISTA role under proximity detection. Only valid if + * @pd_support is set. Sum of both @pd_max_peer_ista_role and + * @pd_max_peer_rsta_role is considered to enforce the max peers supported + * in case the request is of peer-to-peer PD type. + * @pd_max_peer_rsta_role: Maximum number of peers allowed for a device + * operating in the RSTA role under proximity detection. Only valid if + * @pd_support is set. Sum of both @pd_max_peer_ista_role and + * @pd_max_peer_rsta_role is considered to enforce the max peers supported + * in case the request is of peer-to-peer PD type * @ftm: FTM measurement data * @ftm.supported: FTM measurement is supported * @ftm.asap: ASAP-mode is supported @@ -5820,6 +5830,8 @@ struct cfg80211_pmsr_capabilities { randomize_mac_addr:1, pd_support:1, pd_concurrent_ista_rsta_support:1; + u32 pd_max_peer_ista_role; + u32 pd_max_peer_rsta_role; struct { u32 preambles; diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 67cc1ce6d2a1..83d2a822c770 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -7841,6 +7841,20 @@ enum nl80211_peer_measurement_peer_attrs { * multi-peer request, the device can act simultaneously as initiator and * a responder, where the multiple requests are being processed * simultaneously + * @NL80211_PMSR_ATTR_PD_MAX_PEER_ISTA_ROLE: u32 attribute indicating the + * maximum number of peers allowed for a device operating in the ISTA + * (Initiator STA) role under proximity detection. Only valid if + * %NL80211_PMSR_ATTR_PD_SUPPORT is set. Sum of both + * %NL80211_PMSR_ATTR_PD_MAX_PEER_ISTA_ROLE and + * %NL80211_PMSR_ATTR_PD_MAX_PEER_RSTA_ROLE is considered to enforce the + * max peers supported in case the request is of peer-to-peer PD type + * @NL80211_PMSR_ATTR_PD_MAX_PEER_RSTA_ROLE: u32 attribute indicating the + * maximum number of peers allowed for a device operating in the RSTA + * (Responder STA) role under proximity detection. Only valid if + * %NL80211_PMSR_ATTR_PD_SUPPORT is set. Sum of both + * %NL80211_PMSR_ATTR_PD_MAX_PEER_ISTA_ROLE and + * %NL80211_PMSR_ATTR_PD_MAX_PEER_RSTA_ROLE is considered to enforce the + * max peers supported in case the request is of peer-to-peer PD type * * @NUM_NL80211_PMSR_ATTR: internal * @NL80211_PMSR_ATTR_MAX: highest attribute number @@ -7855,6 +7869,8 @@ enum nl80211_peer_measurement_attrs { NL80211_PMSR_ATTR_PEERS, NL80211_PMSR_ATTR_PD_SUPPORT, NL80211_PMSR_ATTR_PD_CONCURRENT_ISTA_RSTA_SUPPORT, + NL80211_PMSR_ATTR_PD_MAX_PEER_ISTA_ROLE, + NL80211_PMSR_ATTR_PD_MAX_PEER_RSTA_ROLE, /* keep last */ NUM_NL80211_PMSR_ATTR, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 2b7de56c466f..5222ac8e8471 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -418,6 +418,8 @@ nl80211_pmsr_attr_policy[NL80211_PMSR_ATTR_MAX + 1] = { [NL80211_PMSR_ATTR_PD_CONCURRENT_ISTA_RSTA_SUPPORT] = { .type = NLA_REJECT }, + [NL80211_PMSR_ATTR_PD_MAX_PEER_ISTA_ROLE] = { .type = NLA_REJECT }, + [NL80211_PMSR_ATTR_PD_MAX_PEER_RSTA_ROLE] = { .type = NLA_REJECT }, }; static const struct nla_policy @@ -2450,6 +2452,16 @@ static int nl80211_send_pmsr_capa(struct cfg80211_registered_device *rdev, nla_put_flag(msg, NL80211_PMSR_ATTR_PD_CONCURRENT_ISTA_RSTA_SUPPORT)) return -ENOBUFS; + + if (cap->pd_max_peer_ista_role && + nla_put_u32(msg, NL80211_PMSR_ATTR_PD_MAX_PEER_ISTA_ROLE, + cap->pd_max_peer_ista_role)) + return -ENOBUFS; + + if (cap->pd_max_peer_rsta_role && + nla_put_u32(msg, NL80211_PMSR_ATTR_PD_MAX_PEER_RSTA_ROLE, + cap->pd_max_peer_rsta_role)) + return -ENOBUFS; } caps = nla_nest_start_noflag(msg, NL80211_PMSR_ATTR_TYPE_CAPA); if (!caps) diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c index a230bb95f5e3..3ca0e589d7cc 100644 --- a/net/wireless/pmsr.c +++ b/net/wireless/pmsr.c @@ -317,12 +317,15 @@ int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info) { struct nlattr *reqattr = info->attrs[NL80211_ATTR_PEER_MEASUREMENTS]; struct cfg80211_registered_device *rdev = info->user_ptr[0]; + int count, rem, err, idx, pd_count, max_pd_peers; struct wireless_dev *wdev = info->user_ptr[1]; + const struct cfg80211_pmsr_capabilities *capa; struct cfg80211_pmsr_request *req; struct nlattr *peers, *peer; - int count, rem, err, idx; - if (!rdev->wiphy.pmsr_capa) + capa = rdev->wiphy.pmsr_capa; + + if (!capa) return -EOPNOTSUPP; if (!reqattr) @@ -337,7 +340,7 @@ int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info) nla_for_each_nested(peer, peers, rem) { count++; - if (count > rdev->wiphy.pmsr_capa->max_peers) { + if (count > capa->max_peers) { NL_SET_ERR_MSG_ATTR(info->extack, peer, "Too many peers used"); return -EINVAL; @@ -353,7 +356,7 @@ int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info) req->timeout = nla_get_u32(info->attrs[NL80211_ATTR_TIMEOUT]); if (info->attrs[NL80211_ATTR_MAC]) { - if (!rdev->wiphy.pmsr_capa->randomize_mac_addr) { + if (!capa->randomize_mac_addr) { NL_SET_ERR_MSG_ATTR(info->extack, info->attrs[NL80211_ATTR_MAC], "device cannot randomize MAC address"); @@ -378,6 +381,27 @@ int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info) goto out_err; idx++; } + + /* Count PD requests and validate against PD peer limits */ + if (capa->pd_support) { + pd_count = 0; + + max_pd_peers = capa->pd_max_peer_ista_role + + capa->pd_max_peer_rsta_role; + + for (idx = 0; idx < req->n_peers; idx++) { + if (req->peers[idx].pd_request) { + pd_count++; + + if (pd_count > max_pd_peers) { + NL_SET_ERR_MSG(info->extack, + "Too many PD peers used"); + err = -EINVAL; + goto out_err; + } + } + } + } req->cookie = cfg80211_assign_cookie(rdev); req->nl_portid = info->snd_portid; -- 2.34.1