svn commit: r191967 - projects/mesh11s/sys/net80211

Rui Paulo rpaulo at FreeBSD.org
Sun May 10 18:17:27 UTC 2009


Author: rpaulo
Date: Sun May 10 18:17:26 2009
New Revision: 191967
URL: http://svn.freebsd.org/changeset/base/191967

Log:
  Implement more peer link management. Peering now works more reliably.
  
  Sponsored by:	The FreeBSD Foundation

Modified:
  projects/mesh11s/sys/net80211/ieee80211_mesh.c
  projects/mesh11s/sys/net80211/ieee80211_node.h

Modified: projects/mesh11s/sys/net80211/ieee80211_mesh.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_mesh.c	Sun May 10 18:16:07 2009	(r191966)
+++ projects/mesh11s/sys/net80211/ieee80211_mesh.c	Sun May 10 18:17:26 2009	(r191967)
@@ -69,26 +69,18 @@ static int	mesh_input(struct ieee80211_n
 static void	mesh_recv_mgmt(struct ieee80211_node *, struct mbuf *, int,
 		    int, int, uint32_t);
 static void	mesh_recv_action(struct ieee80211_node *, struct mbuf *);
-static void	mesh_peer_timeout(void *);
+static __inline void	mesh_peer_timeout_setup(struct ieee80211_node *);
+static void		mesh_peer_timeout_backoff(struct ieee80211_node *);
+static void		mesh_peer_timeout_cb(void *);
+static __inline void	mesh_peer_timeout_stop(struct ieee80211_node *);
+static int	mesh_verify_meshid(struct ieee80211vap *,
+		    struct ieee80211_meshid_ie *);
+static int	mesh_verify_meshconf(struct ieee80211vap *,
+		    struct ieee80211_meshconf_ie *);
 
 int	ieee80211_mesh_retrytimeout = 40;	/* 40 miliseconds */
 #define	RETRY_TIMEOUT	msecs_to_ticks(ieee80211_mesh_retrytimeout)
 int	ieee80211_mesh_maxretries = 60;
-#define MESH_SET_TIMEOUT(xni)							\
-do {										\
-	xni->ni_mtimerboff = RETRY_TIMEOUT;					\
-	callout_reset(&xni->ni_mtimer, RETRY_TIMEOUT, mesh_peer_timeout, xni);	\
-} while (0)
-/*
- * Same as above but backoffs timer statisically 50%.
- * XXX: wrong arc4random usage.
- */
-#define MESH_SET_TIMEOUT_BACKOFF(xni)						\
-do {										\
-	xni->ni_mtimerboff = xni->ni_mtimerboff +				\
-	    ((arc4random() & 0xff) % xni->ni_mtimerboff);			\
-	callout_reset(&xni->ni_mtimer, RETRY_TIMEOUT, mesh_peer_timeout, xni);	\
-} while (0)
 
 /* unalligned little endian access */     
 #define LE_READ_2(p)					\
@@ -96,6 +88,16 @@ do {										\
 	 ((((const uint8_t *)(p))[0]      ) |		\
 	  (((const uint8_t *)(p))[1] <<  8)))
 
+
+static const char *nodemeshstates[] = {
+	"IDLE",
+	"OPEN SENT",
+	"OPEN RECEIVED",
+	"CONFIRM RECEIVED",
+	"ESTABLISHED",
+	"HOLDING"
+};
+
 void
 ieee80211_mesh_attach(struct ieee80211com *ic)
 {
@@ -421,14 +423,14 @@ mesh_recv_mgmt(struct ieee80211_node *ni
 			ni->ni_peerstate = IEEE80211_NODE_MESH_OPENSNT;
 			IEEE80211_NOTE(vap,
 			    IEEE80211_MSG_MESH,
-			    ni, "peer link: switching to state %d",
-			    ni->ni_peerstate);
+			    ni, "peer link: switching to state %s",
+			    nodemeshstates[ni->ni_peerstate]);
 			args[0] = ni->ni_plid;
 			ieee80211_send_action(ni,
 			    IEEE80211_ACTION_CAT_MESHPEERING,
 			    IEEE80211_ACTION_MESHPEERING_OPEN, args);
 			ni->ni_mrcount = 0;
-			MESH_SET_TIMEOUT(ni);
+			mesh_peer_timeout_setup(ni);
 		}
 		if (ni != NULL) {
 			IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
@@ -590,7 +592,9 @@ mesh_recv_action(struct ieee80211_node *
 	 * Check if we agree on Mesh ID and Configuration.
 	 * XXX: TBD
 	 */
-	if (!meshid || !meshconf || !meshpeer) {
+	if (mesh_verify_meshid(vap, meshid) ||
+	    mesh_verify_meshconf(vap, meshconf) ||
+	    !meshpeer) {
 		IEEE80211_DISCARD(vap,
 		    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
 		    wh, NULL, "%s", "action frame not for our mesh");
@@ -598,10 +602,10 @@ mesh_recv_action(struct ieee80211_node *
 		return;
 	}
 
-	switch (ia->ia_category) {
 	/*
 	 * Mesh Peer Link Management Finite State Machine handling.
 	 */
+	switch (ia->ia_category) {
 	case IEEE80211_ACTION_CAT_MESHPEERING:
 		switch (ia->ia_action) {
 		case IEEE80211_ACTION_MESHPEERING_OPEN:
@@ -613,8 +617,8 @@ mesh_recv_action(struct ieee80211_node *
 				ni->ni_peerstate = IEEE80211_NODE_MESH_OPENRCV;
 				IEEE80211_NOTE(vap,
 				    IEEE80211_MSG_MESH,
-				    ni, "peer link: switching to state %d",
-				    ni->ni_peerstate);
+				    ni, "peer link: switching to state %s",
+				    nodemeshstates[ni->ni_peerstate]);
 				ni->ni_llid = meshpeer->peer_llinkid;
 				get_random_bytes(&ni->ni_plid, 2);
 				args[0] = ni->ni_plid;
@@ -628,7 +632,7 @@ mesh_recv_action(struct ieee80211_node *
 				ieee80211_send_action(ni,
 				    IEEE80211_ACTION_CAT_MESHPEERING,
 				    IEEE80211_ACTION_MESHPEERING_CONFIRM, args);
-				/* XXX setup timeout1 */
+				mesh_peer_timeout_setup(ni);
 				break;
 			case IEEE80211_NODE_MESH_OPENRCV:
 				/* We received a duplicate open, confirm again. */
@@ -644,28 +648,28 @@ mesh_recv_action(struct ieee80211_node *
 				ni->ni_llid = meshpeer->peer_llinkid;
 				IEEE80211_NOTE(vap,
 				    IEEE80211_MSG_MESH,
-				    ni, "peer link: switching to state %d",
-				    ni->ni_peerstate);
+				    ni, "peer link: switching to state %s",
+				    nodemeshstates[ni->ni_peerstate]);
 				args[0] = ni->ni_plid;
 				args[1] = ni->ni_llid;
 				ieee80211_send_action(ni,
 				    IEEE80211_ACTION_CAT_MESHPEERING,
 				    IEEE80211_ACTION_MESHPEERING_CONFIRM, args);
-				/* XXX setup timeout1 */
+				/* NB: don't setup/clear any timeout */
 				break;
 			case IEEE80211_NODE_MESH_CONFIRMRECV:
 				ni->ni_peerstate = IEEE80211_NODE_MESH_ESTABLISHED;
 				IEEE80211_NOTE(vap,
 				    IEEE80211_MSG_MESH,
-				    ni, "peer link: switching to state %d",
-				    ni->ni_peerstate);
+				    ni, "peer link: switching to state %s",
+				    nodemeshstates[ni->ni_peerstate]);
 				ni->ni_llid = meshpeer->peer_llinkid;
 				args[0] = ni->ni_plid;
 				args[1] = ni->ni_llid;
 				ieee80211_send_action(ni,
 				    IEEE80211_ACTION_CAT_MESHPEERING,
 				    IEEE80211_ACTION_MESHPEERING_CONFIRM, args);
-				/* clear timeoutC */
+				mesh_peer_timeout_stop(ni);
 				break;
 			case IEEE80211_NODE_MESH_ESTABLISHED:
 				args[0] = ni->ni_plid;
@@ -694,15 +698,16 @@ mesh_recv_action(struct ieee80211_node *
 				ni->ni_peerstate = IEEE80211_NODE_MESH_ESTABLISHED;
 				IEEE80211_NOTE(vap,
 				    IEEE80211_MSG_MESH,
-				    ni, "peer link: switching to state %d",
-				    ni->ni_peerstate);
+				    ni, "peer link: switching to state %s",
+				    nodemeshstates[ni->ni_peerstate]);
+				mesh_peer_timeout_stop(ni);
 				break;
 			case IEEE80211_NODE_MESH_OPENSNT:
 				ni->ni_peerstate = IEEE80211_NODE_MESH_CONFIRMRECV;
 				IEEE80211_NOTE(vap,
 				    IEEE80211_MSG_MESH,
-				    ni, "peer link: switching to state %d",
-				    ni->ni_peerstate);
+				    ni, "peer link: switching to state %s",
+				    nodemeshstates[ni->ni_peerstate]);
 				break;
 			case IEEE80211_NODE_MESH_HOLDING:
 				args[0] = ni->ni_llid;
@@ -727,7 +732,7 @@ mesh_recv_action(struct ieee80211_node *
 			switch (ni->ni_peerstate) {
 			case IEEE80211_NODE_MESH_OPENRCV:
 				ni->ni_peerstate = IEEE80211_NODE_MESH_HOLDING;
-				MESH_SET_TIMEOUT(ni);
+				mesh_peer_timeout_setup(ni);
 				break;
 			case IEEE80211_NODE_MESH_OPENSNT:
 				break;
@@ -744,11 +749,38 @@ mesh_recv_action(struct ieee80211_node *
 	}
 }
 
+static __inline void
+mesh_peer_timeout_setup(struct ieee80211_node *ni)
+{
+	ni->ni_mtimerval = RETRY_TIMEOUT;
+	callout_reset(&ni->ni_mtimer, RETRY_TIMEOUT, mesh_peer_timeout_cb, ni);
+}
+
+/*
+ * Same as above but backoffs timer statisically 50%.
+ */
+static void
+mesh_peer_timeout_backoff(struct ieee80211_node *ni)
+{
+	uint32_t r;
+	
+	r = arc4random();
+	ni->ni_mtimerval += r % ni->ni_mtimerval;
+	callout_reset(&ni->ni_mtimer, ni->ni_mtimerval, mesh_peer_timeout_cb,
+	    ni);
+}
+
+static __inline void
+mesh_peer_timeout_stop(struct ieee80211_node *ni)
+{
+	callout_stop(&ni->ni_mtimer);
+}
+
 /*
  * Mesh Peer Link Management FSM timeout handling.
  */
 static void
-mesh_peer_timeout(void *arg)
+mesh_peer_timeout_cb(void *arg)
 {
 	struct ieee80211_node *ni = (struct ieee80211_node *)arg;
 	struct ieee80211vap *vap = ni->ni_vap;
@@ -756,8 +788,8 @@ mesh_peer_timeout(void *arg)
 
 	IEEE80211_NOTE(vap,
 	    IEEE80211_MSG_MESH,
-	    ni, "mesh link timeout, state %d, retry counter %d",
-	    ni->ni_peerstate, ni->ni_mrcount);
+	    ni, "mesh link timeout, state %s, retry counter %d",
+	    nodemeshstates[ni->ni_peerstate], ni->ni_mrcount);
 	
 	switch (ni->ni_peerstate) {
 	case IEEE80211_NODE_MESH_OPENSNT:
@@ -770,24 +802,70 @@ mesh_peer_timeout(void *arg)
 			    IEEE80211_ACTION_MESHPEERING_CLOSE, args);
 			ni->ni_mrcount = 0;
 			ni->ni_peerstate = IEEE80211_NODE_MESH_HOLDING;
-			MESH_SET_TIMEOUT(ni);
+			IEEE80211_NOTE(vap,
+			    IEEE80211_MSG_MESH,
+			    ni, "peer link: switching to state %s",
+			    nodemeshstates[ni->ni_peerstate]);
+			mesh_peer_timeout_setup(ni);
 		} else {
 			args[0] = ni->ni_plid;
 			ieee80211_send_action(ni,
 			    IEEE80211_ACTION_CAT_MESHPEERING,
 			    IEEE80211_ACTION_MESHPEERING_OPEN, args);
 			ni->ni_mrcount++;
-			MESH_SET_TIMEOUT_BACKOFF(ni);
+			mesh_peer_timeout_backoff(ni);
 		}
 		break;
 	case IEEE80211_NODE_MESH_CONFIRMRECV:
-	
+		if (ni->ni_mrcount == ieee80211_mesh_maxretries) {
+			args[0] = ni->ni_plid;
+			args[2] = IEEE80211_REASON_MESH_CONFIRM_TIMEOUT;
+			ieee80211_send_action(ni,
+			    IEEE80211_ACTION_CAT_MESHPEERING,
+			    IEEE80211_ACTION_MESHPEERING_CLOSE, args);
+			ni->ni_mrcount = 0;
+			ni->ni_peerstate = IEEE80211_NODE_MESH_HOLDING;
+			IEEE80211_NOTE(vap,
+			    IEEE80211_MSG_MESH,
+			    ni, "peer link: switching to state %s",
+			    nodemeshstates[ni->ni_peerstate]);
+			mesh_peer_timeout_setup(ni);
+		} else {
+			ni->ni_mrcount++;
+			mesh_peer_timeout_setup(ni);
+		}
 		break;
 	case IEEE80211_NODE_MESH_HOLDING:
+		ni->ni_peerstate = IEEE80211_NODE_MESH_IDLE;
+		IEEE80211_NOTE(vap,
+		    IEEE80211_MSG_MESH,
+		    ni, "peer link: switching to state %s",
+		    nodemeshstates[ni->ni_peerstate]);
 		break;
 	}
 }
 
+static __inline int
+mesh_verify_meshid(struct ieee80211vap *vap,
+    struct ieee80211_meshid_ie *meshid)
+{
+	if (meshid == NULL)
+		return 1;
+
+	return memcmp(vap->iv_meshid, (uint8_t *)&meshid[1], vap->iv_meshidlen);
+}
+
+static __inline int
+mesh_verify_meshconf(struct ieee80211vap *vap,
+    struct ieee80211_meshconf_ie *meshconf)
+{
+	if (meshconf == NULL)
+		return 1;
+
+	/* XXX TBD */
+	return 0;
+}
+
 /*
  * Parse a MESH ID ie on station join.
  */
@@ -844,7 +922,7 @@ ieee80211_add_meshconf(uint8_t *frm, str
 		.conf_cap	= 1,	/* XXX */
 	};
 
-	KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, ("not a mbss vap"));
+	KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, ("not a MBSS vap"));
 	memcpy(frm, &ie, sizeof(ie));
 
 	return frm + sizeof(ie);
@@ -885,8 +963,10 @@ ieee80211_add_meshpeer(uint8_t *frm, uin
 		break;
 	}
 	return frm;
-#undef ADDSHORT	
+#undef ADDSHORT
 }
+
+
 void
 ieee80211_create_mbss(struct ieee80211vap *vap, struct ieee80211_channel *chan)
 {
@@ -894,7 +974,7 @@ ieee80211_create_mbss(struct ieee80211va
 	struct ieee80211_node *ni;
 
 	IEEE80211_DPRINTF(vap, IEEE80211_MSG_MESH,
-	    "%s: creating mbss on channel %u\n", __func__,
+	    "%s: creating MBSS on channel %u\n", __func__,
 	    ieee80211_chan2ieee(ic, chan));
 
 	ni = ieee80211_alloc_node(&ic->ic_sta, vap, vap->iv_myaddr);

Modified: projects/mesh11s/sys/net80211/ieee80211_node.h
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_node.h	Sun May 10 18:16:07 2009	(r191966)
+++ projects/mesh11s/sys/net80211/ieee80211_node.h	Sun May 10 18:17:26 2009	(r191967)
@@ -187,7 +187,7 @@ struct ieee80211_node {
 	uint16_t		ni_plid;	/* peer link ID */
 	struct callout		ni_mtimer;	/* mesh timer */
 	uint8_t			ni_mrcount;	/* mesh retry counter */
-	uint8_t			ni_mtimerboff;	/* mesh timer backoff value */
+	uint8_t			ni_mtimerval;	/* mesh timer value */
 
 	/* 11n state */
 	uint16_t		ni_htcap;	/* HT capabilities */


More information about the svn-src-projects mailing list