On 9-1-2017 18:53, Jouni Malinen wrote:
> From: vamsi krishna <[email protected]>
>
> Enhance sched scan to support option of finding a better BSS while in
> connected state. Firmware scans the medium and reports when it finds a
> known BSS which has better RSSI than the current connected BSS. New
> attributes to specify the relative RSSI (compared to the current BSS)
> are added to the sched scan to implement this.
>
> Signed-off-by: vamsi krishna <[email protected]>
> Signed-off-by: Jouni Malinen <[email protected]>
> ---
> include/net/cfg80211.h | 36 ++++++++++++++++++++++----------
> include/uapi/linux/nl80211.h | 29 ++++++++++++++++++++++++++
> net/wireless/nl80211.c | 49
> ++++++++++++++++++++++++++++++++++++++++++--
> 3 files changed, 101 insertions(+), 13 deletions(-)
>
> v3:
> - use struct cfg80211_bss_select_adjust as the data structure for
> specifying band preference (instead of attr hardcoded for 5 GHz)
> - add relative_rssi_set boolean to have a robust mechanism for
> determining whether the NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI
> attribute was included
>
> diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
> index cb13789..9dc11d3 100644
> --- a/include/net/cfg80211.h
> +++ b/include/net/cfg80211.h
> @@ -1620,6 +1620,17 @@ struct cfg80211_sched_scan_plan {
> };
>
> /**
> + * struct cfg80211_bss_select_adjust - BSS selection with RSSI adjustment.
> + *
> + * @band: band of BSS which should match for RSSI level adjustment.
> + * @delta: value of RSSI level adjustment.
> + */
> +struct cfg80211_bss_select_adjust {
> + enum nl80211_band band;
> + s8 delta;
> +};
> +
> +/**
> * struct cfg80211_sched_scan_request - scheduled scan request description
> *
> * @ssids: SSIDs to scan for (passed in the probe_reqs in active scans)
> @@ -1654,6 +1665,16 @@ struct cfg80211_sched_scan_plan {
> * cycle. The driver may ignore this parameter and start
> * immediately (or at any other time), if this feature is not
> * supported.
> + * @relative_rssi_set: Indicates whether @relative_rssi is set or not.
So you see a use-case for doing a scan with @relative_rssi being zero,
right?
> + * @relative_rssi: Relative RSSI threshold in dB to restrict scan result
> + * reporting in connected state to cases where a matching BSS is determined
> + * to have better RSSI than the current connected BSS. The relative RSSI
> + * threshold values are ignored in disconnected state.
The description says "better RSSI" so I suppose it could be typed as u8.
The last sentence is intended driver behavior
> + * @rssi_adjust: delta dB of RSSI preference to be given to the BSSs that
> belong
> + * to the specified band while deciding whether a better BSS is reported
> + * using @relative_rssi. If delta is a negative number, the BSSs that
> + * belong to the specified band will be penalized by delta dB in relative
> + * comparisions.
> */
> struct cfg80211_sched_scan_request {
> struct cfg80211_ssid *ssids;
> @@ -1673,6 +1694,10 @@ struct cfg80211_sched_scan_request {
> u8 mac_addr[ETH_ALEN] __aligned(2);
> u8 mac_addr_mask[ETH_ALEN] __aligned(2);
>
> + bool relative_rssi_set;
> + s8 relative_rssi;
> + struct cfg80211_bss_select_adjust rssi_adjust;
> +
> /* internal */
> struct wiphy *wiphy;
> struct net_device *dev;
> @@ -1981,17 +2006,6 @@ struct cfg80211_ibss_params {
> };
>
> /**
> - * struct cfg80211_bss_select_adjust - BSS selection with RSSI adjustment.
> - *
> - * @band: band of BSS which should match for RSSI level adjustment.
> - * @delta: value of RSSI level adjustment.
> - */
> -struct cfg80211_bss_select_adjust {
> - enum nl80211_band band;
> - s8 delta;
> -};
> -
> -/**
> * struct cfg80211_bss_selection - connection parameters for BSS selection.
> *
> * @behaviour: requested BSS selection behaviour.
> diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
> index 174f4b3..4e8bf28 100644
> --- a/include/uapi/linux/nl80211.h
> +++ b/include/uapi/linux/nl80211.h
> @@ -1982,6 +1982,19 @@ enum nl80211_commands {
> * @NL80211_ATTR_BSSID: The BSSID of the AP. Note that %NL80211_ATTR_MAC is
> also
> * used in various commands/events for specifying the BSSID.
> *
> + * @NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI: Relative RSSI threshold by which
> + * other BSSs has to be better than the current connected BSS so that they
> + * get reported to user space. This will give an opportunity to userspace
> + * to consider connecting to other matching BSSs which have better RSSI
> + * than the current connected BSS by using an offloaded operation to avoid
> + * unnecessary wakeups.
> + *
> + * @NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST: When present the RSSI level for
> BSSs in
> + * the specified band is to be adjusted before doing
> + * %NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI based comparision to figure out
> + * better BSSs. The attribute value is a packed structure
> + * value as specified by &struct nl80211_bss_select_rssi_adjust.
> + *
> * @NUM_NL80211_ATTR: total number of nl80211_attrs available
> * @NL80211_ATTR_MAX: highest attribute number currently defined
> * @__NL80211_ATTR_AFTER_LAST: internal use
> @@ -2388,6 +2401,9 @@ enum nl80211_attrs {
>
> NL80211_ATTR_BSSID,
>
> + NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI,
> + NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST,
> +
> /* add attributes here, update the policy in nl80211.c */
>
> __NL80211_ATTR_AFTER_LAST,
> @@ -3080,6 +3096,13 @@ enum nl80211_reg_rule_attr {
> * how this API was implemented in the past. Also, due to the same problem,
> * the only way to create a matchset with only an RSSI filter (with this
> * attribute) is if there's only a single matchset with the RSSI attribute.
> + * @NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI: Flag indicating whether
> + * %NL80211_SCHED_SCAN_MATCH_ATTR_RSSI to be used as absolute RSSI or
> + * relative to current bss's RSSI.
> + * @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST: When present the RSSI level
> for
> + * BSS-es in the specified band is to be adjusted before doing
> + * RSSI-based BSS selection. The attribute value is a packed structure
> + * value as specified by &struct nl80211_bss_select_rssi_adjust.
> * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
> * attribute number currently defined
> * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
> @@ -3089,6 +3112,8 @@ enum nl80211_sched_scan_match_attr {
>
> NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
> NL80211_SCHED_SCAN_MATCH_ATTR_RSSI,
> + NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI,
> + NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST,
>
> /* keep last */
> __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST,
> @@ -4699,6 +4724,9 @@ enum nl80211_feature_flags {
> * configuration (AP/mesh) with VHT rates.
> * @NL80211_EXT_FEATURE_FILS_STA: This driver supports Fast Initial Link
> Setup
> * with user space SME (NL80211_CMD_AUTHENTICATE) in station mode.
> + * @NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI: The driver supports
> sched_scan
> + * for reporting BSSs with better RSSI than the current connected BSS
> + * (%NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI).
> *
> * @NUM_NL80211_EXT_FEATURES: number of extended features.
> * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
> @@ -4714,6 +4742,7 @@ enum nl80211_ext_feature_index {
> NL80211_EXT_FEATURE_BEACON_RATE_HT,
> NL80211_EXT_FEATURE_BEACON_RATE_VHT,
> NL80211_EXT_FEATURE_FILS_STA,
> + NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI,
>
> /* add new features before the definition below */
> NUM_NL80211_EXT_FEATURES,
> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> index b378d0a..bb3f04a 100644
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c
> @@ -405,6 +405,10 @@ static const struct nla_policy
> nl80211_policy[NUM_NL80211_ATTR] = {
> [NL80211_ATTR_FILS_NONCES] = { .len = 2 * FILS_NONCE_LEN },
> [NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_FLAG, },
> [NL80211_ATTR_BSSID] = { .len = ETH_ALEN },
> + [NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] = { .type = NLA_S8 },
> + [NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST] = {
> + .len = sizeof(struct nl80211_bss_select_rssi_adjust)
> + },
> };
>
> /* policy for the key attributes */
> @@ -6950,6 +6954,12 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct
> wireless_dev *wdev,
> if (!n_plans || n_plans > wiphy->max_sched_scan_plans)
> return ERR_PTR(-EINVAL);
>
> + if (!wiphy_ext_feature_isset(
> + wiphy, NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI) &&
> + (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI] ||
> + attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]))
> + return ERR_PTR(-EINVAL);
> +
> request = kzalloc(sizeof(*request)
> + sizeof(*request->ssids) * n_ssids
> + sizeof(*request->match_sets) * n_match_sets
> @@ -7156,6 +7166,25 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct
> wireless_dev *wdev,
> request->delay =
> nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_DELAY]);
>
> + if (attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]) {
> + request->relative_rssi = nla_get_s8(
> + attrs[NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI]);
> + request->relative_rssi_set = true;
> + }
> +
> + if (attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]) {
Maybe I misread but I thought this attribute to be applicable only if
request->relative_rssi_set is true.
> + struct nl80211_bss_select_rssi_adjust *rssi_adjust;
> +
> + rssi_adjust = nla_data(
> + attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]);
> + request->rssi_adjust.band = rssi_adjust->band;
> + request->rssi_adjust.delta = rssi_adjust->delta;
> + if (!is_band_valid(wiphy, request->rssi_adjust.band)) {
> + err = -EINVAL;
> + goto out_free;
> + }
> + }
> +
> err = nl80211_parse_sched_scan_plans(wiphy, n_plans, request, attrs);
> if (err)
> goto out_free;
> @@ -9671,7 +9700,8 @@ static int nl80211_send_wowlan_tcp(struct sk_buff *msg,
> return 0;
> }
>
> -static int nl80211_send_wowlan_nd(struct sk_buff *msg,
> +static int nl80211_send_wowlan_nd(struct wiphy *wiphy,
This seems to be unrelated change. At least I do not see any reference
to wiphy variable in the added code below.
> + struct sk_buff *msg,
> struct cfg80211_sched_scan_request *req)
> {
> struct nlattr *nd, *freqs, *matches, *match, *scan_plans, *scan_plan;
> @@ -9692,6 +9722,21 @@ static int nl80211_send_wowlan_nd(struct sk_buff *msg,
> if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_DELAY, req->delay))
> return -ENOBUFS;
>
> + if (req->relative_rssi_set &&
> + nla_put_s8(msg, NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI,
> + req->relative_rssi))
> + return -ENOBUFS;
> +
> + if (req->rssi_adjust.band != __NL80211_BAND_ATTR_INVALID) {
> + struct nl80211_bss_select_rssi_adjust rssi_adjust;
> +
> + rssi_adjust.band = req->rssi_adjust.band;
> + rssi_adjust.delta = req->rssi_adjust.delta;
> + if (nla_put(msg, NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST,
> + sizeof(rssi_adjust), &rssi_adjust))
> + return -ENOBUFS;
> + }
> +
> freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
> if (!freqs)
> return -ENOBUFS;
> @@ -9805,7 +9850,7 @@ static int nl80211_get_wowlan(struct sk_buff *skb,
> struct genl_info *info)
> goto nla_put_failure;
>
> if (nl80211_send_wowlan_nd(
> - msg,
> + &rdev->wiphy, msg,
> rdev->wiphy.wowlan_config->nd_config))
> goto nla_put_failure;
>
>
Regards,
Arend