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.
Unified · Split
| @@ -4527,7 +4527,8 @@ struct cfg80211_pmsr_result { · 4526 unmodified lines | ||
| 4527 | 4527 | * @burst_duration: burst duration. If @trigger_based or @non_trigger_based is |
| 4528 | 4528 | * set, this is the burst duration in milliseconds, and zero means the |
| 4529 | 4529 | * device should pick an appropriate value based on @ftms_per_burst. |
| 4530 | − * @ftms_per_burst: number of FTMs per burst | |
| 4530 | + * @ftms_per_burst: number of FTMs per burst. If set to 0, the firmware or | |
| 4531 | + * driver can automatically select an appropriate value. | |
| 4531 | 4532 | * @ftmr_retries: number of retries for FTM request |
| 4532 | 4533 | * @request_lci: request LCI information |
| 4533 | 4534 | * @request_civicloc: request civic location information |
| @@ -4544,6 +4545,31 @@ struct cfg80211_pmsr_result { · 10 unmodified lines | ||
| 4544 | 4545 | * @bss_color: the bss color of the responder. Optional. Set to zero to |
| 4545 | 4546 | * indicate the driver should set the BSS color. Only valid if |
| 4546 | 4547 | * @non_trigger_based or @trigger_based is set. |
| 4548 | + * @request_type: ranging request type, one of | |
| 4549 | + * &enum nl80211_peer_measurement_ftm_req_type. Defaults to | |
| 4550 | + * %NL80211_PMSR_FTM_REQ_TYPE_INFRA if not specified. | |
| 4551 | + * @min_time_between_measurements: minimum time between two consecutive range | |
| 4552 | + * measurements in units of 100 microseconds, for non-trigger based | |
| 4553 | + * ranging. Should be set as short as possible to minimize turnaround | |
| 4554 | + * time, since two-way ranging with delayed LMR requires two measurements. | |
| 4555 | + * Only valid if @non_trigger_based is set. | |
| 4556 | + * @max_time_between_measurements: maximum time between two consecutive range | |
| 4557 | + * measurements in units of 10 milliseconds, for non-trigger based | |
| 4558 | + * ranging. Acts as a session timeout; if exceeded, the ranging session | |
| 4559 | + * should be terminated. Only valid if @non_trigger_based is set. | |
| 4560 | + * @availability_window: duration of the availability window (AW) in units of | |
| 4561 | + * 1 millisecond (0-255 ms). Only valid if @non_trigger_based is set. | |
| 4562 | + * If set to 0, the firmware or driver can automatically select an | |
| 4563 | + * appropriate value. | |
| 4564 | + * @nominal_time: Nominal duration between adjacent availability windows | |
| 4565 | + * in units of milli seconds. Only valid if @non_trigger_based is set. | |
| 4566 | + * If set to 0, the firmware or driver can automatically select an | |
| 4567 | + * appropriate value. | |
| 4568 | + * @num_measurements: number of Availability Windows (AWs) to schedule | |
| 4569 | + * for non-trigger-based ranging. Each AW may contain multiple FTM | |
| 4570 | + * exchanges as configured by @ftms_per_burst. Only valid if | |
| 4571 | + * @non_trigger_based is set. If set to 0, the firmware or driver | |
| 4572 | + * can automatically select an appropriate value. | |
| 4547 | 4573 | * |
| 4548 | 4574 | * See also nl80211 for the respective attribute documentation. |
| 4549 | 4575 | */ |
| @@ -4563,6 +4589,13 @@ struct cfg80211_pmsr_ftm_request_peer { · 13 unmodified lines | ||
| 4563 | 4589 | u8 ftms_per_burst; |
| 4564 | 4590 | u8 ftmr_retries; |
| 4565 | 4591 | u8 bss_color; |
| 4592 | + | |
| 4593 | + u32 request_type; | |
| 4594 | + u32 min_time_between_measurements; | |
| 4595 | + u32 max_time_between_measurements; | |
| 4596 | + u8 availability_window; | |
| 4597 | + u32 nominal_time; | |
| 4598 | + u32 num_measurements; | |
| 4566 | 4599 | }; |
| 4567 | 4600 | |
| 4568 | 4601 | /** |
| @@ -7991,6 +7991,26 @@ enum nl80211_peer_measurement_resp { · 7990 unmodified lines | ||
| 7991 | 7991 | NL80211_PMSR_RESP_ATTR_MAX = NUM_NL80211_PMSR_RESP_ATTRS - 1 |
| 7992 | 7992 | }; |
| 7993 | 7993 | |
| 7994 | +/** | |
| 7995 | + * enum nl80211_peer_measurement_ftm_req_type - FTM ranging request type, | |
| 7996 | + * used with %NL80211_PMSR_PEER_ATTR_REQ_TYPE | |
| 7997 | + * | |
| 7998 | + * @NL80211_PMSR_FTM_REQ_TYPE_INFRA: infrastructure ranging, i.e. STA-to-AP | |
| 7999 | + * @NL80211_PMSR_FTM_REQ_TYPE_PD: peer-to-peer ranging as defined in the | |
| 8000 | + * Wi-Fi Alliance specification "Proximity Ranging (PR) Implementation | |
| 8001 | + * Consideration Draft 1.9 Rev 1" | |
| 8002 | + * @NUM_NL80211_PMSR_FTM_REQ_TYPE: internal | |
| 8003 | + * @NL80211_PMSR_FTM_REQ_TYPE_MAX: highest request type value | |
| 8004 | + */ | |
| 8005 | +enum nl80211_peer_measurement_ftm_req_type { | |
| 8006 | + NL80211_PMSR_FTM_REQ_TYPE_INFRA, | |
| 8007 | + NL80211_PMSR_FTM_REQ_TYPE_PD, | |
| 8008 | + | |
| 8009 | + /* keep last */ | |
| 8010 | + NUM_NL80211_PMSR_FTM_REQ_TYPE, | |
| 8011 | + NL80211_PMSR_FTM_REQ_TYPE_MAX = NUM_NL80211_PMSR_FTM_REQ_TYPE - 1 | |
| 8012 | +}; | |
| 8013 | + | |
| 7994 | 8014 | /** |
| 7995 | 8015 | * enum nl80211_peer_measurement_peer_attrs - peer attributes for measurement |
| 7996 | 8016 | * @__NL80211_PMSR_PEER_ATTR_INVALID: invalid |
| @@ -8004,6 +8024,9 @@ enum nl80211_peer_measurement_resp { · 7 unmodified lines | ||
| 8004 | 8024 | * @NL80211_PMSR_PEER_ATTR_RESP: This is a nested attribute indexed by |
| 8005 | 8025 | * measurement type, with attributes from the |
| 8006 | 8026 | * &enum nl80211_peer_measurement_resp inside. |
| 8027 | + * @NL80211_PMSR_PEER_ATTR_REQ_TYPE: u32 attribute specifying the ranging | |
| 8028 | + * request type, using values from &enum nl80211_peer_measurement_ftm_req_type. | |
| 8029 | + * If absent, defaults to %NL80211_PMSR_FTM_REQ_TYPE_INFRA. | |
| 8007 | 8030 | * |
| 8008 | 8031 | * @NUM_NL80211_PMSR_PEER_ATTRS: internal |
| 8009 | 8032 | * @NL80211_PMSR_PEER_ATTR_MAX: highest attribute number |
| @@ -8015,6 +8038,7 @@ enum nl80211_peer_measurement_peer_attrs { · 5 unmodified lines | ||
| 8015 | 8038 | NL80211_PMSR_PEER_ATTR_CHAN, |
| 8016 | 8039 | NL80211_PMSR_PEER_ATTR_REQ, |
| 8017 | 8040 | NL80211_PMSR_PEER_ATTR_RESP, |
| 8041 | + NL80211_PMSR_PEER_ATTR_REQ_TYPE, | |
| 8018 | 8042 | |
| 8019 | 8043 | /* keep last */ |
| 8020 | 8044 | NUM_NL80211_PMSR_PEER_ATTRS, |
| @@ -8238,9 +8262,11 @@ enum nl80211_peer_measurement_ftm_type_capa { · 217 unmodified lines | ||
| 8238 | 8262 | * default 15 i.e. "no preference"). For non-EDCA ranging, this is the |
| 8239 | 8263 | * burst duration in milliseconds (optional with default 0, i.e. let the |
| 8240 | 8264 | * device decide). |
| 8241 | − * @NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST: number of successful FTM frames | |
| 8242 | − * requested per burst | |
| 8265 | + * @NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST: (Optional) number of successful | |
| 8266 | + * FTM frames requested per burst | |
| 8243 | 8267 | * (u8, 0-31, optional with default 0 i.e. "no preference") |
| 8268 | + * If the attribute is absent ("no preference"), the driver or firmware can | |
| 8269 | + * choose a suitable value. | |
| 8244 | 8270 | * @NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES: number of FTMR frame retries |
| 8245 | 8271 | * (u8, default 3) |
| 8246 | 8272 | * @NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI: request LCI data (flag) |
| @@ -8274,6 +8300,33 @@ enum nl80211_peer_measurement_ftm_type_capa { · 27 unmodified lines | ||
| 8274 | 8300 | * Only valid if %NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK is set (so the |
| 8275 | 8301 | * RSTA will have the measurement results to report back in the FTM |
| 8276 | 8302 | * response). |
| 8303 | + * @NL80211_PMSR_FTM_REQ_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS: minimum time | |
| 8304 | + * between two consecutive range measurements in units of 100 microseconds, | |
| 8305 | + * for non-trigger based ranging (u32). Should be set as short as possible | |
| 8306 | + * to minimize turnaround time, since two-way ranging with delayed LMR | |
| 8307 | + * requires two measurements. Only valid if | |
| 8308 | + * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set. | |
| 8309 | + * @NL80211_PMSR_FTM_REQ_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS: maximum time | |
| 8310 | + * between two consecutive range measurements in units of 10 milliseconds, | |
| 8311 | + * for non-trigger based ranging (u32). Acts as a session timeout; if | |
| 8312 | + * exceeded, the ranging session should be terminated. Only valid if | |
| 8313 | + * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set. | |
| 8314 | + * @NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME: The nominal time field shall be | |
| 8315 | + * set to the nominal duration between adjacent Availability Windows in | |
| 8316 | + * units of milli seconds (u32). Mandatory if | |
| 8317 | + * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set. | |
| 8318 | + * @NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION: (Optional) The AW duration field | |
| 8319 | + * shall be set to the duration of the AW in units of 1ms (0-255 ms) (u32). | |
| 8320 | + * Only valid if %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set. | |
| 8321 | + * If the attribute is absent ("no preference"), the driver or firmware | |
| 8322 | + * can choose a suitable value. | |
| 8323 | + * @NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS: (Optional) number of | |
| 8324 | + * Availability Windows (AWs) to schedule for non-trigger-based ranging. | |
| 8325 | + * Each AW may contain multiple FTM exchanges as configured by | |
| 8326 | + * %NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST. Only valid if | |
| 8327 | + * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set. | |
| 8328 | + * If the attribute is absent ("no preference"), the driver or firmware | |
| 8329 | + * can choose a suitable value. | |
| 8277 | 8330 | * |
| 8278 | 8331 | * @NUM_NL80211_PMSR_FTM_REQ_ATTR: internal |
| 8279 | 8332 | * @NL80211_PMSR_FTM_REQ_ATTR_MAX: highest attribute number |
| @@ -8295,6 +8348,11 @@ enum nl80211_peer_measurement_ftm_req { · 15 unmodified lines | ||
| 8295 | 8348 | NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK, |
| 8296 | 8349 | NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR, |
| 8297 | 8350 | NL80211_PMSR_FTM_REQ_ATTR_RSTA, |
| 8351 | + NL80211_PMSR_FTM_REQ_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS, | |
| 8352 | + NL80211_PMSR_FTM_REQ_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS, | |
| 8353 | + NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME, | |
| 8354 | + NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION, | |
| 8355 | + NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS, | |
| 8298 | 8356 | |
| 8299 | 8357 | /* keep last */ |
| 8300 | 8358 | NUM_NL80211_PMSR_FTM_REQ_ATTR, |
| @@ -476,6 +476,15 @@ nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = { · 475 unmodified lines | ||
| 476 | 476 | [NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK] = { .type = NLA_FLAG }, |
| 477 | 477 | [NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR] = { .type = NLA_U8 }, |
| 478 | 478 | [NL80211_PMSR_FTM_REQ_ATTR_RSTA] = { .type = NLA_FLAG }, |
| 479 | + [NL80211_PMSR_FTM_REQ_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS] = { | |
| 480 | + .type = NLA_U32 | |
| 481 | + }, | |
| 482 | + [NL80211_PMSR_FTM_REQ_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS] = { | |
| 483 | + .type = NLA_U32 | |
| 484 | + }, | |
| 485 | + [NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME] = { .type = NLA_U32 }, | |
| 486 | + [NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION] = NLA_POLICY_MAX(NLA_U32, 255), | |
| 487 | + [NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS] = { .type = NLA_U32 }, | |
| 479 | 488 | }; |
| 480 | 489 | |
| 481 | 490 | static const struct nla_policy |
| @@ -498,6 +507,8 @@ nl80211_pmsr_peer_attr_policy[NL80211_PMSR_PEER_ATTR_MAX + 1] = { · 16 unmodified lines | ||
| 498 | 507 | [NL80211_PMSR_PEER_ATTR_REQ] = |
| 499 | 508 | NLA_POLICY_NESTED(nl80211_pmsr_req_attr_policy), |
| 500 | 509 | [NL80211_PMSR_PEER_ATTR_RESP] = { .type = NLA_REJECT }, |
| 510 | + [NL80211_PMSR_PEER_ATTR_REQ_TYPE] = | |
| 511 | + NLA_POLICY_MAX(NLA_U32, NL80211_PMSR_FTM_REQ_TYPE_MAX), | |
| 501 | 512 | }; |
| 502 | 513 | |
| 503 | 514 | static const struct nla_policy |
| @@ -91,11 +91,10 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, · 90 unmodified lines | ||
| 91 | 91 | nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST]); |
| 92 | 92 | |
| 93 | 93 | if (capa->ftm.max_ftms_per_burst && |
| 94 | − (out->ftm.ftms_per_burst > capa->ftm.max_ftms_per_burst || | |
| 95 | − out->ftm.ftms_per_burst == 0)) { | |
| 94 | + out->ftm.ftms_per_burst > capa->ftm.max_ftms_per_burst) { | |
| 96 | 95 | NL_SET_ERR_MSG_ATTR(info->extack, |
| 97 | 96 | tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST], |
| 98 | − "FTM: FTMs per burst must be set lower than the device limit but non-zero"); | |
| 97 | + "FTM: FTMs per burst must be set lower than the device limit"); | |
| 99 | 98 | return -EINVAL; |
| 100 | 99 | } |
| 101 | 100 | |
| @@ -128,6 +127,14 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, · 26 unmodified lines | ||
| 128 | 127 | return -EINVAL; |
| 129 | 128 | } |
| 130 | 129 | |
| 130 | + if (out->ftm.request_type == NL80211_PMSR_FTM_REQ_TYPE_PD && | |
| 131 | + out->ftm.trigger_based) { | |
| 132 | + NL_SET_ERR_MSG_ATTR(info->extack, | |
| 133 | + ftmreq, | |
| 134 | + "FTM: TB ranging is not supported for PD request type"); | |
| 135 | + return -EINVAL; | |
| 136 | + } | |
| 137 | + | |
| 131 | 138 | out->ftm.non_trigger_based = |
| 132 | 139 | !!tb[NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED]; |
| 133 | 140 | 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, · 9 unmodified lines | ||
| 143 | 150 | return -EINVAL; |
| 144 | 151 | } |
| 145 | 152 | |
| 153 | + if (out->ftm.request_type == NL80211_PMSR_FTM_REQ_TYPE_PD && | |
| 154 | + out->ftm.non_trigger_based && out->ftm.ftms_per_burst > 4) { | |
| 155 | + NL_SET_ERR_MSG_ATTR(info->extack, | |
| 156 | + tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST], | |
| 157 | + "FTM: FTMs per burst must not exceed 4 for PD NTB ranging"); | |
| 158 | + return -ERANGE; | |
| 159 | + } | |
| 160 | + | |
| 146 | 161 | if (out->ftm.ftms_per_burst > 31 && !out->ftm.non_trigger_based && |
| 147 | 162 | !out->ftm.trigger_based) { |
| 148 | 163 | NL_SET_ERR_MSG_ATTR(info->extack, |
| @@ -222,6 +237,33 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, · 73 unmodified lines | ||
| 222 | 237 | return -EINVAL; |
| 223 | 238 | } |
| 224 | 239 | |
| 240 | + if (out->ftm.non_trigger_based) { | |
| 241 | + if (out->ftm.request_type == NL80211_PMSR_FTM_REQ_TYPE_PD && | |
| 242 | + !tb[NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME]) { | |
| 243 | + NL_SET_ERR_MSG(info->extack, | |
| 244 | + "FTM: nominal time is required for PD NTB ranging"); | |
| 245 | + return -EINVAL; | |
| 246 | + } | |
| 247 | + out->ftm.nominal_time = | |
| 248 | + nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME]); | |
| 249 | + | |
| 250 | + if (tb[NL80211_PMSR_FTM_REQ_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS]) | |
| 251 | + out->ftm.min_time_between_measurements = | |
| 252 | + nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS]); | |
| 253 | + | |
| 254 | + if (tb[NL80211_PMSR_FTM_REQ_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS]) | |
| 255 | + out->ftm.max_time_between_measurements = | |
| 256 | + nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS]); | |
| 257 | + | |
| 258 | + if (tb[NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION]) | |
| 259 | + out->ftm.availability_window = | |
| 260 | + nla_get_u8(tb[NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION]); | |
| 261 | + | |
| 262 | + if (tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS]) | |
| 263 | + out->ftm.num_measurements = | |
| 264 | + nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS]); | |
| 265 | + } | |
| 266 | + | |
| 225 | 267 | return 0; |
| 226 | 268 | } |
| 227 | 269 | |
| @@ -249,6 +291,19 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev, · 21 unmodified lines | ||
| 249 | 291 | |
| 250 | 292 | memcpy(out->addr, nla_data(tb[NL80211_PMSR_PEER_ATTR_ADDR]), ETH_ALEN); |
| 251 | 293 | |
| 294 | + if (tb[NL80211_PMSR_PEER_ATTR_REQ_TYPE]) | |
| 295 | + out->ftm.request_type = | |
| 296 | + nla_get_u32(tb[NL80211_PMSR_PEER_ATTR_REQ_TYPE]); | |
| 297 | + else | |
| 298 | + out->ftm.request_type = NL80211_PMSR_FTM_REQ_TYPE_INFRA; | |
| 299 | + | |
| 300 | + if (out->ftm.request_type == NL80211_PMSR_FTM_REQ_TYPE_PD && | |
| 301 | + !rdev->wiphy.pmsr_capa->ftm.type.pd_support) { | |
| 302 | + NL_SET_ERR_MSG_ATTR(info->extack, | |
| 303 | + tb[NL80211_PMSR_PEER_ATTR_REQ_TYPE], | |
| 304 | + "FTM: PD request type not supported by device"); | |
| 305 | + return -EINVAL; | |
| 306 | + } | |
| 252 | 307 | /* reuse info->attrs */ |
| 253 | 308 | memset(info->attrs, 0, sizeof(*info->attrs) * (NL80211_ATTR_MAX + 1)); |
| 254 | 309 | err = nla_parse_nested_deprecated(info->attrs, NL80211_ATTR_MAX, |