]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
{nl,mac}80211: add rssi to mesh candidates
authorBob Copeland <me@bobcopeland.com>
Fri, 26 Oct 2018 14:03:50 +0000 (10:03 -0400)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 9 Nov 2018 10:41:20 +0000 (11:41 +0100)
When peering is in userspace, some implementations may want to control
which peers are accepted based on RSSI in addition to the information
elements being sent today.  Add signal level so that info is available
to clients.

Signed-off-by: Bob Copeland <bobcopeland@fb.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/cfg80211.h
net/mac80211/mesh.c
net/mac80211/mesh.h
net/mac80211/mesh_plink.c
net/wireless/nl80211.c

index 16d595b93ba39713a8707b7b6d962b66423dccd7..ede7fcd68348ce0c840245dfcadfe916255c21cd 100644 (file)
@@ -5574,7 +5574,8 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
  * cfg80211 then sends a notification to userspace.
  */
 void cfg80211_notify_new_peer_candidate(struct net_device *dev,
-               const u8 *macaddr, const u8 *ie, u8 ie_len, gfp_t gfp);
+               const u8 *macaddr, const u8 *ie, u8 ie_len,
+               int sig_dbm, gfp_t gfp);
 
 /**
  * DOC: RFkill integration
index 4869280a64137d97b6dfdd56420d70e0d83f8c72..c90452aa0c4241557e29473a4cfbc26be6ca3470 100644 (file)
@@ -1194,7 +1194,8 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
                if (!sdata->u.mesh.user_mpm ||
                    sdata->u.mesh.mshcfg.rssi_threshold == 0 ||
                    sdata->u.mesh.mshcfg.rssi_threshold < rx_status->signal)
-                       mesh_neighbour_update(sdata, mgmt->sa, &elems);
+                       mesh_neighbour_update(sdata, mgmt->sa, &elems,
+                                             rx_status);
        }
 
        if (ifmsh->sync_ops)
index 21526630bf6559fed1ecd1894a4796db5216fd56..cad6592c52a11dcabb7f3fd09878a3515a64095d 100644 (file)
@@ -273,7 +273,8 @@ int mesh_gate_num(struct ieee80211_sub_if_data *sdata);
 
 /* Mesh plinks */
 void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
-                          u8 *hw_addr, struct ieee802_11_elems *ie);
+                          u8 *hw_addr, struct ieee802_11_elems *ie,
+                          struct ieee80211_rx_status *rx_status);
 bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie);
 u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata);
 void mesh_plink_timer(struct timer_list *t);
index 5f45a2b273df52c7d927f8d4fd69fe64bd546676..33055c8ed37ec8c2fbd2d6904c91b2c8b71ee949 100644 (file)
@@ -513,7 +513,8 @@ __mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *hw_addr)
 
 static struct sta_info *
 mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *addr,
-                   struct ieee802_11_elems *elems)
+                   struct ieee802_11_elems *elems,
+                   struct ieee80211_rx_status *rx_status)
 {
        struct sta_info *sta = NULL;
 
@@ -521,11 +522,17 @@ mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *addr,
        if (sdata->u.mesh.user_mpm ||
            sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) {
                if (mesh_peer_accepts_plinks(elems) &&
-                   mesh_plink_availables(sdata))
+                   mesh_plink_availables(sdata)) {
+                       int sig = 0;
+
+                       if (ieee80211_hw_check(&sdata->local->hw, SIGNAL_DBM))
+                               sig = rx_status->signal;
+
                        cfg80211_notify_new_peer_candidate(sdata->dev, addr,
                                                           elems->ie_start,
                                                           elems->total_len,
-                                                          GFP_KERNEL);
+                                                          sig, GFP_KERNEL);
+               }
        } else
                sta = __mesh_sta_info_alloc(sdata, addr);
 
@@ -538,13 +545,15 @@ mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *addr,
  * @sdata: local meshif
  * @addr: peer's address
  * @elems: IEs from beacon or mesh peering frame.
+ * @rx_status: rx status for the frame for signal reporting
  *
  * Return existing or newly allocated sta_info under RCU read lock.
  * (re)initialize with given IEs.
  */
 static struct sta_info *
 mesh_sta_info_get(struct ieee80211_sub_if_data *sdata,
-                 u8 *addr, struct ieee802_11_elems *elems) __acquires(RCU)
+                 u8 *addr, struct ieee802_11_elems *elems,
+                 struct ieee80211_rx_status *rx_status) __acquires(RCU)
 {
        struct sta_info *sta = NULL;
 
@@ -555,7 +564,7 @@ mesh_sta_info_get(struct ieee80211_sub_if_data *sdata,
        } else {
                rcu_read_unlock();
                /* can't run atomic */
-               sta = mesh_sta_info_alloc(sdata, addr, elems);
+               sta = mesh_sta_info_alloc(sdata, addr, elems, rx_status);
                if (!sta) {
                        rcu_read_lock();
                        return NULL;
@@ -576,17 +585,19 @@ mesh_sta_info_get(struct ieee80211_sub_if_data *sdata,
  * @sdata: local meshif
  * @addr: peer's address
  * @elems: IEs from beacon or mesh peering frame
+ * @rx_status: rx status for the frame for signal reporting
  *
  * Initiates peering if appropriate.
  */
 void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
                           u8 *hw_addr,
-                          struct ieee802_11_elems *elems)
+                          struct ieee802_11_elems *elems,
+                          struct ieee80211_rx_status *rx_status)
 {
        struct sta_info *sta;
        u32 changed = 0;
 
-       sta = mesh_sta_info_get(sdata, hw_addr, elems);
+       sta = mesh_sta_info_get(sdata, hw_addr, elems, rx_status);
        if (!sta)
                goto out;
 
@@ -1072,7 +1083,8 @@ out:
 static void
 mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata,
                         struct ieee80211_mgmt *mgmt,
-                        struct ieee802_11_elems *elems)
+                        struct ieee802_11_elems *elems,
+                        struct ieee80211_rx_status *rx_status)
 {
 
        struct sta_info *sta;
@@ -1137,7 +1149,7 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata,
        if (event == OPN_ACPT) {
                rcu_read_unlock();
                /* allocate sta entry if necessary and update info */
-               sta = mesh_sta_info_get(sdata, mgmt->sa, elems);
+               sta = mesh_sta_info_get(sdata, mgmt->sa, elems, rx_status);
                if (!sta) {
                        mpl_dbg(sdata, "Mesh plink: failed to init peer!\n");
                        goto unlock_rcu;
@@ -1203,5 +1215,5 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
                        return;
        }
        ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems);
-       mesh_process_plink_frame(sdata, mgmt, &elems);
+       mesh_process_plink_frame(sdata, mgmt, &elems, rx_status);
 }
index d5f0ffd076b2ef7c7a40f920215bacf8f81d5e86..e20329b348401151dcb8f61bde25efbf4ed20359 100644 (file)
@@ -14735,7 +14735,8 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
 }
 
 void cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr,
-                                       const u8* ie, u8 ie_len, gfp_t gfp)
+                                       const u8 *ie, u8 ie_len,
+                                       int sig_dbm, gfp_t gfp)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
@@ -14761,7 +14762,9 @@ void cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr,
            nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
            nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
            (ie_len && ie &&
-            nla_put(msg, NL80211_ATTR_IE, ie_len , ie)))
+            nla_put(msg, NL80211_ATTR_IE, ie_len, ie)) ||
+           (sig_dbm &&
+            nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)))
                goto nla_put_failure;
 
        genlmsg_end(msg, hdr);