{nl,cfg,mac}80211: Implement RSSI threshold for mesh peering
authorAshok Nagarajan <ashok@cozybit.com>
Wed, 29 Feb 2012 01:04:08 +0000 (17:04 -0800)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 5 Mar 2012 20:23:15 +0000 (15:23 -0500)
Mesh peer links are established only if average rssi of the peer
candidate satisfies the threshold. This is not in 802.11s specification
but was requested by David Fulgham, an open80211s user. This is a way to avoid
marginal peer links with stations that are barely within range.

This patch adds a new mesh configuration parameter, mesh_rssi_threshold. This
feature is supported only for hardwares that report signal in dBm.

Signed-off-by: Ashok Nagarajan <ashok@cozybit.com>
Signed-off-by: Javier Cardona <javier@cozybit.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
include/linux/nl80211.h
include/net/cfg80211.h
net/mac80211/cfg.c
net/mac80211/debugfs_netdev.c
net/mac80211/mesh_plink.c
net/wireless/mesh.c
net/wireless/nl80211.c

index be35a68746a7f7f932acc39b48f10511d47b3393..38fda5ee57f5d879c68a160549c965a70d262c62 100644 (file)
@@ -2112,6 +2112,10 @@ enum nl80211_mntr_flags {
  * @NL80211_MESHCONF_FORWARDING: set Mesh STA as forwarding or non-forwarding
  * or forwarding entity (default is TRUE - forwarding entity)
  *
+ * @NL80211_MESHCONF_RSSI_THRESHOLD: RSSI threshold in dBm. This specifies the
+ * threshold for average signal strength of candidate station to establish
+ * a peer link.
+ *
  * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute
  *
  * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use
@@ -2137,6 +2141,7 @@ enum nl80211_meshconf_params {
        NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
        NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL,
        NL80211_MESHCONF_FORWARDING,
+       NL80211_MESHCONF_RSSI_THRESHOLD,
 
        /* keep last */
        __NL80211_MESHCONF_ATTR_AFTER_LAST,
index 0178c74893736b74dfdd55190e021a8eca6a1132..b4e015c90885cd4b03131f739d23e36c83726798 100644 (file)
@@ -809,6 +809,7 @@ struct mesh_config {
         * Still keeping the same nomenclature to be in sync with the spec. */
        bool  dot11MeshGateAnnouncementProtocol;
        bool dot11MeshForwarding;
+       s32 rssi_threshold;
 };
 
 /**
index 6a77d4c910f9a24b3bdfa95b0a72b1d6949d110a..ab31cc56a2fb62d83fe8b0062b310c305c8a0102 100644 (file)
@@ -1314,6 +1314,14 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
        }
        if (_chg_mesh_attr(NL80211_MESHCONF_FORWARDING, mask))
                conf->dot11MeshForwarding = nconf->dot11MeshForwarding;
+       if (_chg_mesh_attr(NL80211_MESHCONF_RSSI_THRESHOLD, mask)) {
+               /* our RSSI threshold implementation is supported only for
+                * devices that report signal in dBm.
+                */
+               if (!(sdata->local->hw.flags & IEEE80211_HW_SIGNAL_DBM))
+                       return -ENOTSUPP;
+               conf->rssi_threshold = nconf->rssi_threshold;
+       }
        return 0;
 }
 
index 510ed1dab3c7eb1d9b179451f7f7c68a58a91272..9f484d8905fdbfda046d0a217b20f022877e2586 100644 (file)
@@ -443,6 +443,7 @@ IEEE80211_IF_FILE(dot11MeshGateAnnouncementProtocol,
 IEEE80211_IF_FILE(dot11MeshHWMPRannInterval,
                u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC);
 IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC);
+IEEE80211_IF_FILE(rssi_threshold, u.mesh.mshcfg.rssi_threshold, DEC);
 #endif
 
 
@@ -581,6 +582,7 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
        MESHPARAMS_ADD(dot11MeshHWMPRootMode);
        MESHPARAMS_ADD(dot11MeshHWMPRannInterval);
        MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol);
+       MESHPARAMS_ADD(rssi_threshold);
 #undef MESHPARAMS_ADD
 }
 #endif
index 8806e5ef8ffecebb799504a16c338a2f496991a0..80ce5277253828dfac0af6d1b6b93e1ec267a74f 100644 (file)
 #define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout)
 #define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks)
 
+#define sta_meets_rssi_threshold(sta, sdata) \
+               (sdata->u.mesh.mshcfg.rssi_threshold == 0 ||\
+               (s8) -ewma_read(&sta->avg_signal) > \
+               sdata->u.mesh.mshcfg.rssi_threshold)
+
 enum plink_event {
        PLINK_UNDEFINED,
        OPN_ACPT,
@@ -301,7 +306,8 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates,
        if (mesh_peer_accepts_plinks(elems) &&
                        sta->plink_state == NL80211_PLINK_LISTEN &&
                        sdata->u.mesh.accepting_plinks &&
-                       sdata->u.mesh.mshcfg.auto_open_plinks)
+                       sdata->u.mesh.mshcfg.auto_open_plinks &&
+                       sta_meets_rssi_threshold(sta, sdata))
                mesh_plink_open(sta);
 
        rcu_read_unlock();
@@ -531,6 +537,14 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
                return;
        }
 
+       if (ftype == WLAN_SP_MESH_PEERING_OPEN &&
+           !sta_meets_rssi_threshold(sta, sdata)) {
+               mpl_dbg("Mesh plink: %pM does not meet rssi threshold\n",
+                       sta->sta.addr);
+               rcu_read_unlock();
+               return;
+       }
+
        if (sta && !test_sta_flag(sta, WLAN_STA_AUTH)) {
                mpl_dbg("Mesh plink: Action frame from non-authed peer\n");
                rcu_read_unlock();
index 9d3e3b6bfcf4c20f6a0e484dd097319a3a63eefa..ba21ab22187bef366394743d9d94d6ee33d72b6a 100644 (file)
@@ -23,6 +23,8 @@
 #define MESH_PERR_MIN_INT      100
 #define MESH_DIAM_TRAVERSAL_TIME 50
 
+#define MESH_RSSI_THRESHOLD    0
+
 /*
  * A path will be refreshed if it is used PATH_REFRESH_TIME milliseconds
  * before timing out.  This way it will remain ACTIVE and no data frames
@@ -56,6 +58,7 @@ const struct mesh_config default_mesh_config = {
        .dot11MeshHWMPRannInterval = MESH_RANN_INTERVAL,
        .dot11MeshGateAnnouncementProtocol = false,
        .dot11MeshForwarding = true,
+       .rssi_threshold = MESH_RSSI_THRESHOLD,
 };
 
 const struct mesh_setup default_mesh_setup = {
index 1998c3682774094c23c4102385c7923e610a2102..25a470abd21d63d75b5832895f7f6cf45b1282fa 100644 (file)
@@ -3290,6 +3290,8 @@ static int nl80211_get_mesh_config(struct sk_buff *skb,
                        cur_params.dot11MeshGateAnnouncementProtocol);
        NLA_PUT_U8(msg, NL80211_MESHCONF_FORWARDING,
                        cur_params.dot11MeshForwarding);
+       NLA_PUT_U32(msg, NL80211_MESHCONF_RSSI_THRESHOLD,
+                       cur_params.rssi_threshold);
        nla_nest_end(msg, pinfoattr);
        genlmsg_end(msg, hdr);
        return genlmsg_reply(msg, info);
@@ -3322,6 +3324,7 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A
        [NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 },
        [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 },
        [NL80211_MESHCONF_FORWARDING] = { .type = NLA_U8 },
+       [NL80211_MESHCONF_RSSI_THRESHOLD] = { .type = NLA_U32},
 };
 
 static const struct nla_policy
@@ -3413,6 +3416,8 @@ do {\
                        nla_get_u8);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding,
                        mask, NL80211_MESHCONF_FORWARDING, nla_get_u8);
+       FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold,
+                       mask, NL80211_MESHCONF_RSSI_THRESHOLD, nla_get_u32);
        if (mask_out)
                *mask_out = mask;