Search Linux Wireless

[PATCH] mac80211: close peer link after consecutive beacon misses

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Currently the mesh code relies on on a graceful peer link close with a
Mesh Peering Close frame. That causes peer links to stay in established
state after a node just silently disappeared.

This commit adds a timeout that is triggered when a defined number of beacons
from a peer have been missed. In this case the link is closed, just as it
would be in case of a received Mesh Peering Close frame.
To calculate the timeout the peer's beacon interval is used.

Signed-off-by: Marco Porsch <marco.porsch@xxxxxxxxxxxxxxxxxxx>
---
 net/mac80211/mesh.c       |    2 +-
 net/mac80211/mesh.h       |    5 ++++-
 net/mac80211/mesh_plink.c |   19 +++++++++++++++++--
 net/mac80211/sta_info.h   |    2 ++
 4 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index ff0296c..6d41e5d 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -696,7 +696,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
 
 	if (elems.mesh_id && elems.mesh_config &&
 	    mesh_matches_local(sdata, &elems))
-		mesh_neighbour_update(sdata, mgmt->sa, &elems);
+		mesh_neighbour_update(sdata, mgmt, &elems);
 
 	if (ifmsh->sync_ops)
 		ifmsh->sync_ops->rx_bcn_presp(sdata,
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 25d0f17..7ce9203 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -209,6 +209,9 @@ struct mesh_rmc {
 
 #define MESH_PATH_EXPIRE (600 * HZ)
 
+/* maximum number of missed beacons before peer link is closed */
+#define MESH_MAX_BEACON_MISS	14
+
 /* Default maximum number of plinks per interface */
 #define MESH_MAX_PLINKS		256
 
@@ -282,7 +285,7 @@ int mesh_path_send_to_gates(struct mesh_path *mpath);
 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 ieee80211_mgmt *mgmt,
 			   struct ieee802_11_elems *ie);
 bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie);
 u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata);
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 3ab34d8..3a12707 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -372,6 +372,8 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
 	spin_lock_bh(&sta->lock);
 	sta->last_rx = jiffies;
 	if (sta->plink_state == NL80211_PLINK_ESTAB) {
+		mod_plink_timer(sta, TU_TO_JIFFIES(sta->beacon_interval *
+						   MESH_MAX_BEACON_MISS));
 		spin_unlock_bh(&sta->lock);
 		return sta;
 	}
@@ -404,13 +406,13 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
 }
 
 void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
-			   u8 *hw_addr,
+			   struct ieee80211_mgmt *mgmt,
 			   struct ieee802_11_elems *elems)
 {
 	struct sta_info *sta;
 
 	rcu_read_lock();
-	sta = mesh_peer_init(sdata, hw_addr, elems);
+	sta = mesh_peer_init(sdata, mgmt->sa, elems);
 	if (!sta)
 		goto out;
 
@@ -421,6 +423,7 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
 	    rssi_threshold_check(sta, sdata))
 		mesh_plink_open(sta);
 
+	sta->beacon_interval = le16_to_cpu(mgmt->u.beacon.beacon_int);
 out:
 	rcu_read_unlock();
 }
@@ -430,6 +433,7 @@ static void mesh_plink_timer(unsigned long data)
 	struct sta_info *sta;
 	__le16 llid, plid, reason;
 	struct ieee80211_sub_if_data *sdata;
+	u32 changed = 0;
 
 	/*
 	 * This STA is valid because sta_info_destroy() will
@@ -495,6 +499,17 @@ static void mesh_plink_timer(unsigned long data)
 		mesh_plink_fsm_restart(sta);
 		spin_unlock_bh(&sta->lock);
 		break;
+	case NL80211_PLINK_ESTAB:
+		/* beacon loss timer */
+		mpl_dbg(sta->sdata, "Mesh plink for %pM beacon loss\n",
+			sta->sta.addr);
+		changed |= __mesh_plink_deactivate(sta);
+		sta->plink_state = NL80211_PLINK_HOLDING;
+		mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
+		spin_unlock_bh(&sta->lock);
+		changed |= mesh_set_ht_prot_mode(sdata);
+		ieee80211_bss_info_change_notify(sdata, changed);
+		break;
 	default:
 		spin_unlock_bh(&sta->lock);
 		break;
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index c88f161f..45eae7e 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -274,6 +274,7 @@ struct sta_ampdu_mlme {
  * @t_offset_setpoint: reference timing offset of this sta to be used when
  * 	calculating clockdrift
  * @ch_type: peer's channel type
+ * @beacon_interval: beacon interval of this station
  * @debugfs: debug filesystem info
  * @dead: set to true when sta is unlinked
  * @uploaded: set to true when sta is uploaded to the driver
@@ -370,6 +371,7 @@ struct sta_info {
 	s64 t_offset;
 	s64 t_offset_setpoint;
 	enum nl80211_channel_type ch_type;
+	u16 beacon_interval;
 #endif
 
 #ifdef CONFIG_MAC80211_DEBUGFS
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux