From: vamsi krishna <[email protected]>

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 <[email protected]>
Signed-off-by: Srinivas Dasari <[email protected]>

---
v2:
Per band rssi thresholds were defined as global for all the
matchsets in v1. This version moves them to represent
each matchset.
---
 include/net/cfg80211.h       |  8 ++++++++
 include/uapi/linux/nl80211.h | 13 +++++++++++++
 net/wireless/nl80211.c       | 45 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 66 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7033c90..e151ac9 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1831,11 +1831,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];
 };
 
 /**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index dd4f86e..4a94049 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -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,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index af89e5c..640a812 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -640,6 +640,7 @@ static int validate_ie_attr(const struct nlattr *attr,
                                                 .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] = { .type = NLA_NESTED },
 };
 
 static const struct nla_policy
@@ -7554,6 +7555,41 @@ static int nl80211_abort_scan(struct sk_buff *skb, 
struct genl_info *info)
        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)
@@ -7829,6 +7865,15 @@ static int nl80211_abort_scan(struct sk_buff *skb, 
struct genl_info *info)
                                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++;
                }
-- 
1.9.1

Reply via email to