diff options
| author | Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com> | 2026-04-20 14:38:49 +0530 |
|---|---|---|
| committer | Johannes Berg <johannes.berg@intel.com> | 2026-05-05 13:36:30 +0200 |
| commit | 8823a9b0e7af5395cbfa06bf23806197d59cd124 (patch) | |
| tree | 002a9cccc9529bc9c34b4963045668ed8a5b2fad /net/wireless | |
| parent | 18709c618d3b4b2990f202a436784f4c36e2c193 (diff) | |
wifi: cfg80211: add NTB continuous ranging and FTM request type support
Enable NTB continuous ranging with configurable timing and measurement
parameters as per the Wi-Fi Alliance specification "Proximity Ranging
(PR) Implementation Consideration Draft 1.9 Rev 1, section 5.3". Add
new FTM request attributes for min/max time between measurements,
nominal time (mandatory for NTB), AW duration, and total measurement
count.
Add NL80211_PMSR_PEER_ATTR_REQ_TYPE attribute using the new
nl80211_peer_measurement_ftm_req_type enum to allow userspace to
specify the ranging request type per peer:
- NL80211_PMSR_FTM_REQ_TYPE_INFRA: STA-to-AP or AP-to-STA ranging
(default if attribute is absent)
- NL80211_PMSR_FTM_REQ_TYPE_PD: peer-to-peer ranging
Validate the request type against the device TYPE_CAPS capabilities
advertised via NL80211_PMSR_FTM_CAPA_ATTR_TYPE_CAPS. Reject PD
requests if the device does not advertise PD support.
Reject PD requests that set trigger-based ranging, as TB ranging is
not compatible with peer-to-peer proximity detection.
Add ftms_per_burst limit of 4 for PD NTB ranging requests.
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
Link: https://patch.msgid.link/20260420090856.2152905-7-peddolla.reddy@oss.qualcomm.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
| -rw-r--r-- | net/wireless/nl80211.c | 11 | ||||
| -rw-r--r-- | net/wireless/pmsr.c | 61 |
2 files changed, 69 insertions, 3 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 0a87f4f81cd2..61ecf8fceb6a 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -476,6 +476,15 @@ nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = { [NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK] = { .type = NLA_FLAG }, [NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR] = { .type = NLA_U8 }, [NL80211_PMSR_FTM_REQ_ATTR_RSTA] = { .type = NLA_FLAG }, + [NL80211_PMSR_FTM_REQ_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS] = { + .type = NLA_U32 + }, + [NL80211_PMSR_FTM_REQ_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS] = { + .type = NLA_U32 + }, + [NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME] = { .type = NLA_U32 }, + [NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION] = NLA_POLICY_MAX(NLA_U32, 255), + [NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS] = { .type = NLA_U32 }, }; static const struct nla_policy @@ -498,6 +507,8 @@ nl80211_pmsr_peer_attr_policy[NL80211_PMSR_PEER_ATTR_MAX + 1] = { [NL80211_PMSR_PEER_ATTR_REQ] = NLA_POLICY_NESTED(nl80211_pmsr_req_attr_policy), [NL80211_PMSR_PEER_ATTR_RESP] = { .type = NLA_REJECT }, + [NL80211_PMSR_PEER_ATTR_REQ_TYPE] = + NLA_POLICY_MAX(NLA_U32, NL80211_PMSR_FTM_REQ_TYPE_MAX), }; static const struct nla_policy diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c index c21f693fac29..951ba0b96da2 100644 --- a/net/wireless/pmsr.c +++ b/net/wireless/pmsr.c @@ -91,11 +91,10 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST]); if (capa->ftm.max_ftms_per_burst && - (out->ftm.ftms_per_burst > capa->ftm.max_ftms_per_burst || - out->ftm.ftms_per_burst == 0)) { + out->ftm.ftms_per_burst > capa->ftm.max_ftms_per_burst) { NL_SET_ERR_MSG_ATTR(info->extack, tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST], - "FTM: FTMs per burst must be set lower than the device limit but non-zero"); + "FTM: FTMs per burst must be set lower than the device limit"); return -EINVAL; } @@ -128,6 +127,14 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, return -EINVAL; } + if (out->ftm.request_type == NL80211_PMSR_FTM_REQ_TYPE_PD && + out->ftm.trigger_based) { + NL_SET_ERR_MSG_ATTR(info->extack, + ftmreq, + "FTM: TB ranging is not supported for PD request type"); + return -EINVAL; + } + out->ftm.non_trigger_based = !!tb[NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED]; if (out->ftm.non_trigger_based && !capa->ftm.non_trigger_based) { @@ -143,6 +150,14 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, return -EINVAL; } + if (out->ftm.request_type == NL80211_PMSR_FTM_REQ_TYPE_PD && + out->ftm.non_trigger_based && out->ftm.ftms_per_burst > 4) { + NL_SET_ERR_MSG_ATTR(info->extack, + tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST], + "FTM: FTMs per burst must not exceed 4 for PD NTB ranging"); + return -ERANGE; + } + if (out->ftm.ftms_per_burst > 31 && !out->ftm.non_trigger_based && !out->ftm.trigger_based) { NL_SET_ERR_MSG_ATTR(info->extack, @@ -222,6 +237,33 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, return -EINVAL; } + if (out->ftm.non_trigger_based) { + if (out->ftm.request_type == NL80211_PMSR_FTM_REQ_TYPE_PD && + !tb[NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME]) { + NL_SET_ERR_MSG(info->extack, + "FTM: nominal time is required for PD NTB ranging"); + return -EINVAL; + } + out->ftm.nominal_time = + nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME]); + + if (tb[NL80211_PMSR_FTM_REQ_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS]) + out->ftm.min_time_between_measurements = + nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS]); + + if (tb[NL80211_PMSR_FTM_REQ_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS]) + out->ftm.max_time_between_measurements = + nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS]); + + if (tb[NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION]) + out->ftm.availability_window = + nla_get_u8(tb[NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION]); + + if (tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS]) + out->ftm.num_measurements = + nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS]); + } + return 0; } @@ -249,6 +291,19 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, memcpy(out->addr, nla_data(tb[NL80211_PMSR_PEER_ATTR_ADDR]), ETH_ALEN); + if (tb[NL80211_PMSR_PEER_ATTR_REQ_TYPE]) + out->ftm.request_type = + nla_get_u32(tb[NL80211_PMSR_PEER_ATTR_REQ_TYPE]); + else + out->ftm.request_type = NL80211_PMSR_FTM_REQ_TYPE_INFRA; + + if (out->ftm.request_type == NL80211_PMSR_FTM_REQ_TYPE_PD && + !rdev->wiphy.pmsr_capa->ftm.type.pd_support) { + NL_SET_ERR_MSG_ATTR(info->extack, + tb[NL80211_PMSR_PEER_ATTR_REQ_TYPE], + "FTM: PD request type not supported by device"); + return -EINVAL; + } /* reuse info->attrs */ memset(info->attrs, 0, sizeof(*info->attrs) * (NL80211_ATTR_MAX + 1)); err = nla_parse_nested_deprecated(info->attrs, NL80211_ATTR_MAX, |
