nl80211/cfg80211: Specify band specific min RSSI thresholds with sched scan
authorvamsi krishna <vamsin@codeaurora.org>
Fri, 1 Feb 2019 13:04:51 +0000 (18:34 +0530)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 8 Apr 2019 11:44:40 +0000 (13:44 +0200)
This commit adds the support to specify the RSSI thresholds per
band for each match set. This enhances the current behavior which
specifies a single rssi_threshold across all the bands by
introducing the rssi_threshold_per_band. These per band rssi
thresholds are referred through NL80211_BAND_* (enum nl80211_band)
variables  as attribute types. Such attributes/values per each
band are nested through NL80211_ATTR_SCHED_SCAN_MIN_RSSI.
These band specific rssi thresholds shall take precedence over
the current rssi_thold per match set.
Drivers indicate this support through
%NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD.
These per band rssi attributes/values does not specify
"default RSSI filter" as done by
NL80211_SCHED_SCAN_MATCH_ATTR_RSSI to stay backward compatible.
That said, these per band rssi values have to be specified for
the corresponding matchset.

Signed-off-by: vamsi krishna <vamsin@codeaurora.org>
Signed-off-by: Srinivas Dasari <dasaris@codeaurora.org>
[rebase on refactoring, add policy]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/cfg80211.h
include/uapi/linux/nl80211.h
net/wireless/nl80211.c

index bb307a11ee636b7194bbe7d31c83f3d798b3379a..b13234a486e77d4553f94c9d33306183f82193b6 100644 (file)
@@ -1832,11 +1832,19 @@ static inline void get_random_mask_addr(u8 *buf, const u8 *addr, const u8 *mask)
  * @bssid: BSSID to be matched; may be all-zero BSSID in case of SSID match
  *     or no match (RSSI only)
  * @rssi_thold: don't report scan results below this threshold (in s32 dBm)
+ * @per_band_rssi_thold: Minimum rssi threshold for each band to be applied
+ *     for filtering out scan results received. Drivers advertize this support
+ *     of band specific rssi based filtering through the feature capability
+ *     %NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD. These band
+ *     specific rssi thresholds take precedence over rssi_thold, if specified.
+ *     If not specified for any band, it will be assigned with rssi_thold of
+ *     corresponding matchset.
  */
 struct cfg80211_match_set {
        struct cfg80211_ssid ssid;
        u8 bssid[ETH_ALEN];
        s32 rssi_thold;
+       s32 per_band_rssi_thold[NUM_NL80211_BANDS];
 };
 
 /**
index dd4f86ee286ec052a9ec2f4bb5d1f39bce55589b..4a9404958fbe8529d7abc867fd163498f7c7d2de 100644 (file)
@@ -3638,6 +3638,14 @@ enum nl80211_reg_rule_attr {
  *     value as specified by &struct nl80211_bss_select_rssi_adjust.
  * @NL80211_SCHED_SCAN_MATCH_ATTR_BSSID: BSSID to be used for matching
  *     (this cannot be used together with SSID).
+ * @NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI: Nested attribute that carries the
+ *     band specific minimum rssi thresholds for the bands defined in
+ *     enum nl80211_band. The minimum rssi threshold value(s32) specific to a
+ *     band shall be encapsulated in attribute with type value equals to one
+ *     of the NL80211_BAND_* defined in enum nl80211_band. For example, the
+ *     minimum rssi threshold value for 2.4GHZ band shall be encapsulated
+ *     within an attribute of type NL80211_BAND_2GHZ. And one or more of such
+ *     attributes will be nested within this attribute.
  * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
  *     attribute number currently defined
  * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
@@ -3650,6 +3658,7 @@ enum nl80211_sched_scan_match_attr {
        NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI,
        NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST,
        NL80211_SCHED_SCAN_MATCH_ATTR_BSSID,
+       NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI,
 
        /* keep last */
        __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST,
@@ -5343,6 +5352,9 @@ enum nl80211_feature_flags {
  * @NL80211_EXT_FEATURE_AP_PMKSA_CACHING: Driver/device supports PMKSA caching
  *     (set/del PMKSA operations) in AP mode.
  *
+ * @NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD: Driver supports
+ *     filtering of sched scan results using band specific RSSI thresholds.
+ *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
  */
@@ -5384,6 +5396,7 @@ enum nl80211_ext_feature_index {
        NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER,
        NL80211_EXT_FEATURE_AIRTIME_FAIRNESS,
        NL80211_EXT_FEATURE_AP_PMKSA_CACHING,
+       NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD,
 
        /* add new features before the definition below */
        NUM_NL80211_EXT_FEATURES,
index 5c49d11fc4774f0cbd1093404d43f4480355dbf4..62f96d6c02f02cc1bfd435571f3b2917c7ab1f64 100644 (file)
@@ -617,12 +617,21 @@ nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
        [NL80211_REKEY_DATA_REPLAY_CTR] = { .len = NL80211_REPLAY_CTR_LEN },
 };
 
+static const struct nla_policy
+nl80211_match_band_rssi_policy[NUM_NL80211_BANDS] = {
+       [NL80211_BAND_2GHZ] = { .type = NLA_S32 },
+       [NL80211_BAND_5GHZ] = { .type = NLA_S32 },
+       [NL80211_BAND_60GHZ] = { .type = NLA_S32 },
+};
+
 static const struct nla_policy
 nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = {
        [NL80211_SCHED_SCAN_MATCH_ATTR_SSID] = { .type = NLA_BINARY,
                                                 .len = IEEE80211_MAX_SSID_LEN },
        [NL80211_SCHED_SCAN_MATCH_ATTR_BSSID] = { .len = ETH_ALEN },
        [NL80211_SCHED_SCAN_MATCH_ATTR_RSSI] = { .type = NLA_U32 },
+       [NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI] =
+               NLA_POLICY_NESTED(nl80211_match_band_rssi_policy),
 };
 
 static const struct nla_policy
@@ -7537,6 +7546,41 @@ nl80211_parse_sched_scan_plans(struct wiphy *wiphy, int n_plans,
        return 0;
 }
 
+static int
+nl80211_parse_sched_scan_per_band_rssi(struct wiphy *wiphy,
+                                      struct cfg80211_match_set *match_sets,
+                                      struct nlattr *tb_band_rssi,
+                                      s32 rssi_thold)
+{
+       struct nlattr *attr;
+       int i, tmp, ret = 0;
+
+       if (!wiphy_ext_feature_isset(wiphy,
+                   NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD)) {
+               if (tb_band_rssi)
+                       ret = -EOPNOTSUPP;
+               else
+                       for (i = 0; i < NUM_NL80211_BANDS; i++)
+                               match_sets->per_band_rssi_thold[i] =
+                                       NL80211_SCAN_RSSI_THOLD_OFF;
+               return ret;
+       }
+
+       for (i = 0; i < NUM_NL80211_BANDS; i++)
+               match_sets->per_band_rssi_thold[i] = rssi_thold;
+
+       nla_for_each_nested(attr, tb_band_rssi, tmp) {
+               enum nl80211_band band = nla_type(attr);
+
+               if (band < 0 || band >= NUM_NL80211_BANDS)
+                       return -EINVAL;
+
+               match_sets->per_band_rssi_thold[band] = nla_get_s32(attr);
+       }
+
+       return 0;
+}
+
 static struct cfg80211_sched_scan_request *
 nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
                         struct nlattr **attrs, int max_match_sets)
@@ -7816,6 +7860,15 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
                        if (rssi)
                                request->match_sets[i].rssi_thold =
                                        nla_get_s32(rssi);
+
+                       /* Parse per band RSSI attribute */
+                       err = nl80211_parse_sched_scan_per_band_rssi(wiphy,
+                               &request->match_sets[i],
+                               tb[NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI],
+                               request->match_sets[i].rssi_thold);
+                       if (err)
+                               goto out_free;
+
                        i++;
                }