From: Kavita Kavita Introduce support for continuous ranging and advanced timing parameters in the FTM request, response, and capability paths. This enables more flexible ranging scenarios with improved control over measurement timing and session management. Co-developed-by: Peddolla Harshavardhan Reddy Signed-off-by: Peddolla Harshavardhan Reddy Signed-off-by: Kavita Kavita --- drivers/net/wireless/virtual/mac80211_hwsim.c | 217 ++++++++++++++++++ 1 file changed, 217 insertions(+) diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c index 1fcf5d0d2e13..a06bb22dbdf0 100644 --- a/drivers/net/wireless/virtual/mac80211_hwsim.c +++ b/drivers/net/wireless/virtual/mac80211_hwsim.c @@ -848,6 +848,17 @@ hwsim_ftm_result_policy[NL80211_PMSR_FTM_RESP_ATTR_MAX + 1] = { [NL80211_PMSR_FTM_RESP_ATTR_DIST_SPREAD] = { .type = NLA_U64 }, [NL80211_PMSR_FTM_RESP_ATTR_LCI] = { .type = NLA_STRING }, [NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC] = { .type = NLA_STRING }, + [NL80211_PMSR_FTM_RESP_ATTR_TX_LTF_REPETITION_COUNT] = { .type = NLA_U32 }, + [NL80211_PMSR_FTM_RESP_ATTR_RX_LTF_REPETITION_COUNT] = { .type = NLA_U32 }, + [NL80211_PMSR_FTM_RESP_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS] = { .type = NLA_U32 }, + [NL80211_PMSR_FTM_RESP_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS] = { .type = NLA_U32 }, + [NL80211_PMSR_FTM_RESP_ATTR_NUM_TX_SPATIAL_STREAMS] = { .type = NLA_U8 }, + [NL80211_PMSR_FTM_RESP_ATTR_NUM_RX_SPATIAL_STREAMS] = { .type = NLA_U8 }, + [NL80211_PMSR_FTM_RESP_ATTR_NOMINAL_TIME] = { .type = NLA_U32 }, + [NL80211_PMSR_FTM_RESP_ATTR_AVAILABILITY_WINDOW] = { .type = NLA_U32 }, + [NL80211_PMSR_FTM_RESP_ATTR_CHANNEL_WIDTH] = { .type = NLA_U32 }, + [NL80211_PMSR_FTM_RESP_ATTR_PREAMBLE] = { .type = NLA_U32 }, + [NL80211_PMSR_FTM_RESP_ATTR_IS_DELAYED_LMR] = { .type = NLA_FLAG }, }; static const struct nla_policy @@ -881,6 +892,19 @@ hwsim_pmsr_peers_result_policy[NL80211_PMSR_ATTR_MAX + 1] = { [NL80211_PMSR_ATTR_PEERS] = NLA_POLICY_NESTED_ARRAY(hwsim_pmsr_peer_result_policy), }; +static const struct nla_policy +hwsim_ftm_role_capa_policy[NL80211_PMSR_FTM_CAPA_ATTR_MAX + 1] = { + [NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_NTB] = { .type = NLA_FLAG }, + [NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_TB] = { .type = NLA_FLAG }, + [NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_EDCA] = { .type = NLA_FLAG }, +}; + +static const struct nla_policy +hwsim_ftm_type_capa_policy[NL80211_PMSR_FTM_TYPE_CAPA_ATTR_MAX + 1] = { + [NL80211_PMSR_FTM_TYPE_CAPA_ATTR_INFRA_SUPPORT] = { .type = NLA_FLAG }, + [NL80211_PMSR_FTM_TYPE_CAPA_ATTR_PD_SUPPORT] = { .type = NLA_FLAG }, +}; + static const struct nla_policy hwsim_ftm_capa_policy[NL80211_PMSR_FTM_CAPA_ATTR_MAX + 1] = { [NL80211_PMSR_FTM_CAPA_ATTR_ASAP] = { .type = NLA_FLAG }, @@ -893,6 +917,19 @@ hwsim_ftm_capa_policy[NL80211_PMSR_FTM_CAPA_ATTR_MAX + 1] = { [NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST] = NLA_POLICY_MAX(NLA_U8, 31), [NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED] = { .type = NLA_FLAG }, [NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED] = { .type = NLA_FLAG }, + [NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_TX_ANTENNAS] = { .type = NLA_U8 }, + [NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_RX_ANTENNAS] = { .type = NLA_U8 }, + [NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_EDCA] = { .type = NLA_U32 }, + [NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_NTB] = { .type = NLA_U32 }, + [NL80211_PMSR_FTM_CAPA_ATTR_PD_PREAMBLES] = { .type = NLA_U32 }, + [NL80211_PMSR_FTM_CAPA_ATTR_PD_BANDWIDTHS] = { .type = NLA_U32 }, + [NL80211_PMSR_FTM_CAPA_ATTR_ISTA_CAPS] = + NLA_POLICY_NESTED(hwsim_ftm_role_capa_policy), + [NL80211_PMSR_FTM_CAPA_ATTR_RSTA_CAPS] = + NLA_POLICY_NESTED(hwsim_ftm_role_capa_policy), + [NL80211_PMSR_FTM_CAPA_ATTR_TYPE_CAPS] = + NLA_POLICY_NESTED(hwsim_ftm_type_capa_policy), + [NL80211_PMSR_FTM_CAPA_ATTR_CONCURRENT_ISTA_RSTA_SUPPORT] = { .type = NLA_FLAG }, }; static const struct nla_policy @@ -3623,6 +3660,47 @@ static int mac80211_hwsim_send_pmsr_ftm_request_peer(struct sk_buff *msg, if (nla_put_u8(msg, NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR, request->bss_color)) return -ENOBUFS; + if (request->min_time_between_measurements && + nla_put_u32(msg, NL80211_PMSR_FTM_REQ_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS, + request->min_time_between_measurements)) + return -ENOBUFS; + + if (request->max_time_between_measurements && + nla_put_u32(msg, NL80211_PMSR_FTM_REQ_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS, + request->max_time_between_measurements)) + return -ENOBUFS; + + if (request->availability_window && + nla_put_u8(msg, NL80211_PMSR_FTM_REQ_ATTR_AW_DURATION, + request->availability_window)) + return -ENOBUFS; + + if (request->nominal_time && + nla_put_u32(msg, NL80211_PMSR_FTM_REQ_ATTR_NOMINAL_TIME, + request->nominal_time)) + return -ENOBUFS; + + if (request->num_measurements && + nla_put_u32(msg, NL80211_PMSR_FTM_REQ_ATTR_NUM_MEASUREMENTS, + request->num_measurements)) + return -ENOBUFS; + + if (request->ingress_distancemm && + nla_put_u64_64bit(msg, NL80211_PMSR_FTM_REQ_ATTR_INGRESS, + request->ingress_distancemm, + NL80211_PMSR_FTM_REQ_ATTR_PAD)) + return -ENOBUFS; + + if (request->egress_distancemm && + nla_put_u64_64bit(msg, NL80211_PMSR_FTM_REQ_ATTR_EGRESS, + request->egress_distancemm, + NL80211_PMSR_FTM_REQ_ATTR_PAD)) + return -ENOBUFS; + + if (request->pd_suppress_range_results && + nla_put_flag(msg, NL80211_PMSR_FTM_REQ_ATTR_PD_SUPPRESS_RESULTS)) + return -ENOBUFS; + nla_nest_end(msg, ftm); return 0; @@ -3992,6 +4070,69 @@ static int mac80211_hwsim_parse_ftm_result(struct nlattr *ftm, result->civicloc_len = nla_len(tb[NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC]); } + if (tb[NL80211_PMSR_FTM_RESP_ATTR_TX_LTF_REPETITION_COUNT]) { + result->tx_ltf_repetition_count_valid = 1; + result->tx_ltf_repetition_count = + nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_TX_LTF_REPETITION_COUNT]); + } + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_RX_LTF_REPETITION_COUNT]) { + result->rx_ltf_repetition_count_valid = 1; + result->rx_ltf_repetition_count = + nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_RX_LTF_REPETITION_COUNT]); + } + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS]) { + result->max_time_between_measurements_valid = 1; + result->max_time_between_measurements = + nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_MAX_TIME_BETWEEN_MEASUREMENTS]); + } + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS]) { + result->min_time_between_measurements_valid = 1; + result->min_time_between_measurements = + nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_MIN_TIME_BETWEEN_MEASUREMENTS]); + } + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_TX_SPATIAL_STREAMS]) { + result->num_tx_spatial_streams_valid = 1; + result->num_tx_spatial_streams = + nla_get_u8(tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_TX_SPATIAL_STREAMS]); + } + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_RX_SPATIAL_STREAMS]) { + result->num_rx_spatial_streams_valid = 1; + result->num_rx_spatial_streams = + nla_get_u8(tb[NL80211_PMSR_FTM_RESP_ATTR_NUM_RX_SPATIAL_STREAMS]); + } + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_NOMINAL_TIME]) { + result->nominal_time_valid = 1; + result->nominal_time = + nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_NOMINAL_TIME]); + } + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_AVAILABILITY_WINDOW]) { + result->availability_window_valid = 1; + result->availability_window = + nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_AVAILABILITY_WINDOW]); + } + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_CHANNEL_WIDTH]) { + result->chan_width_valid = 1; + result->chan_width = + nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_CHANNEL_WIDTH]); + } + + if (tb[NL80211_PMSR_FTM_RESP_ATTR_PREAMBLE]) { + result->preamble_valid = 1; + result->preamble = + nla_get_u32(tb[NL80211_PMSR_FTM_RESP_ATTR_PREAMBLE]); + } + + result->is_delayed_lmr = + nla_get_flag(tb[NL80211_PMSR_FTM_RESP_ATTR_IS_DELAYED_LMR]); + return 0; } @@ -6532,6 +6673,82 @@ static int parse_ftm_capa(const struct nlattr *ftm_capa, struct cfg80211_pmsr_ca out->ftm.trigger_based = !!tb[NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED]; out->ftm.non_trigger_based = !!tb[NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED]; + if (tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_TX_ANTENNAS]) + out->ftm.max_no_of_tx_antennas = + nla_get_u8(tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_TX_ANTENNAS]); + + if (tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_RX_ANTENNAS]) + out->ftm.max_no_of_rx_antennas = + nla_get_u8(tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX_NUM_RX_ANTENNAS]); + + if (tb[NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_EDCA]) + out->ftm.min_allowed_ranging_interval_edca = + nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_EDCA]); + + if (tb[NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_NTB]) + out->ftm.min_allowed_ranging_interval_ntb = + nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_MIN_INTERVAL_NTB]); + + if (tb[NL80211_PMSR_FTM_CAPA_ATTR_PD_PREAMBLES]) + out->ftm.pd_preambles = + nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_PD_PREAMBLES]); + + if (tb[NL80211_PMSR_FTM_CAPA_ATTR_PD_BANDWIDTHS]) + out->ftm.pd_bandwidths = + nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_PD_BANDWIDTHS]); + + if (tb[NL80211_PMSR_FTM_CAPA_ATTR_ISTA_CAPS]) { + struct nlattr *ista_tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX + 1]; + + if (!nla_parse_nested(ista_tb, NL80211_PMSR_FTM_CAPA_ATTR_MAX, + tb[NL80211_PMSR_FTM_CAPA_ATTR_ISTA_CAPS], + hwsim_ftm_role_capa_policy, NULL)) { + out->ftm.ista.support_ntb = + !!ista_tb[NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_NTB]; + out->ftm.ista.support_tb = + !!ista_tb[NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_TB]; + out->ftm.ista.support_edca = + !!ista_tb[NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_EDCA]; + if (ista_tb[NL80211_PMSR_ATTR_MAX_PEER_ISTA_ROLE]) + out->ftm.ista.max_peers = + nla_get_u32(ista_tb[NL80211_PMSR_ATTR_MAX_PEER_ISTA_ROLE]); + } + } + + if (tb[NL80211_PMSR_FTM_CAPA_ATTR_RSTA_CAPS]) { + struct nlattr *rsta_tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX + 1]; + + if (!nla_parse_nested(rsta_tb, NL80211_PMSR_FTM_CAPA_ATTR_MAX, + tb[NL80211_PMSR_FTM_CAPA_ATTR_RSTA_CAPS], + hwsim_ftm_role_capa_policy, NULL)) { + out->ftm.rsta.support_ntb = + !!rsta_tb[NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_NTB]; + out->ftm.rsta.support_tb = + !!rsta_tb[NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_TB]; + out->ftm.rsta.support_edca = + !!rsta_tb[NL80211_PMSR_FTM_CAPA_ATTR_SUPPORT_EDCA]; + if (rsta_tb[NL80211_PMSR_ATTR_MAX_PEER_RSTA_ROLE]) + out->ftm.rsta.max_peers = + nla_get_u32(rsta_tb[NL80211_PMSR_ATTR_MAX_PEER_RSTA_ROLE]); + } + } + + if (tb[NL80211_PMSR_FTM_CAPA_ATTR_TYPE_CAPS]) { + struct nlattr *type_tb[NL80211_PMSR_FTM_TYPE_CAPA_ATTR_MAX + 1]; + + if (!nla_parse_nested(type_tb, NL80211_PMSR_FTM_TYPE_CAPA_ATTR_MAX, + tb[NL80211_PMSR_FTM_CAPA_ATTR_TYPE_CAPS], + hwsim_ftm_type_capa_policy, NULL)) { + out->ftm.type.infra_support = + !!type_tb[NL80211_PMSR_FTM_TYPE_CAPA_ATTR_INFRA_SUPPORT]; + out->ftm.type.pd_support = + !!type_tb[NL80211_PMSR_FTM_TYPE_CAPA_ATTR_PD_SUPPORT]; + } + } + + out->ftm.concurrent_ista_rsta_support = + !!tb[NL80211_PMSR_FTM_CAPA_ATTR_CONCURRENT_ISTA_RSTA_SUPPORT]; + return 0; } -- 2.34.1