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