svn commit: r191901 - projects/mesh11s/sys/net80211
Rui Paulo
rpaulo at FreeBSD.org
Thu May 7 20:39:24 UTC 2009
Author: rpaulo
Date: Thu May 7 20:39:23 2009
New Revision: 191901
URL: http://svn.freebsd.org/changeset/base/191901
Log:
Checkpoint mesh peer link handling.
Sponsored by: The FreeBSD Foundation
Modified:
projects/mesh11s/sys/net80211/ieee80211_mesh.c
projects/mesh11s/sys/net80211/ieee80211_node.c
projects/mesh11s/sys/net80211/ieee80211_node.h
projects/mesh11s/sys/net80211/ieee80211_output.c
Modified: projects/mesh11s/sys/net80211/ieee80211_mesh.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_mesh.c Thu May 7 20:28:06 2009 (r191900)
+++ projects/mesh11s/sys/net80211/ieee80211_mesh.c Thu May 7 20:39:23 2009 (r191901)
@@ -69,6 +69,32 @@ 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 *);
+
+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) \
+ ((uint16_t) \
+ ((((const uint8_t *)(p))[0] ) | \
+ (((const uint8_t *)(p))[1] << 8)))
void
ieee80211_mesh_attach(struct ieee80211com *ic)
@@ -383,31 +409,14 @@ mesh_recv_mgmt(struct ieee80211_node *ni
if ((scan.capinfo & (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) == 0 &&
!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr) &&
IEEE80211_ADDR_EQ(wh->i_addr3, zerobssid)) {
+ uint16_t args[4];
/*
* Create a new entry in the neighbor table.
*/
ni = ieee80211_add_neighbor(vap, wh, &scan);
- } else {
/*
- * Record tsf for potential resync.
+ * Try to peer with this node.
*/
- memcpy(ni->ni_tstamp.data, scan.tstamp,
- sizeof(ni->ni_tstamp));
- }
- if (ni != NULL) {
- IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
- ni->ni_noise = noise;
- ni->ni_rstamp = rstamp;
- }
-
- /*
- * If it's a beacon for our mesh and we haven't already
- * peered with this node, send him a mgmt frame with
- * peer link IE.
- */
- if (ni->ni_peerstate == IEEE80211_NODE_MESH_IDLE) {
- uint16_t args[4];
-
get_random_bytes(&ni->ni_plid, 2);
ni->ni_peerstate = IEEE80211_NODE_MESH_OPENSNT;
IEEE80211_NOTE(vap,
@@ -418,8 +427,15 @@ mesh_recv_mgmt(struct ieee80211_node *ni
ieee80211_send_action(ni,
IEEE80211_ACTION_CAT_MESHPEERING,
IEEE80211_ACTION_MESHPEERING_OPEN, args);
- /* XXX setup timeout1 */
+ ni->ni_mrcount = 0;
+ MESH_SET_TIMEOUT(ni);
}
+ if (ni != NULL) {
+ IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
+ ni->ni_noise = noise;
+ ni->ni_rstamp = rstamp;
+ }
+
break;
}
case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
@@ -441,13 +457,12 @@ mesh_recv_mgmt(struct ieee80211_node *ni
vap->iv_stats.is_rx_mgtdiscard++; /* XXX stat */
return;
}
-
/*
* prreq frame format
* [tlv] ssid
* [tlv] supported rates
* [tlv] extended supported rates
- * [tlv] Mesh ID
+ * [tlv] mesh id
*/
ssid = meshid = rates = xrates = NULL;
sfrm = frm;
@@ -522,6 +537,7 @@ mesh_recv_mgmt(struct ieee80211_node *ni
break;
}
}
+
static void
mesh_recv_action(struct ieee80211_node *ni, struct mbuf *m0)
{
@@ -540,7 +556,15 @@ mesh_recv_action(struct ieee80211_node *
frm += sizeof(ia);
efrm = mtod(m0, uint8_t *) + m0->m_len;
- /* XXX explain frame format */
+ /*
+ * We received an action for an unknown neighbor.
+ * XXX: wait for it to beacon or create ieee80211_node?
+ */
+ if (ni == vap->iv_bss) {
+ return;
+ }
+
+
meshid = NULL;
meshpeer = NULL;
meshconf = NULL;
@@ -555,6 +579,9 @@ mesh_recv_action(struct ieee80211_node *
break;
case IEEE80211_ELEMID_MESHPEER:
meshpeer = (struct ieee80211_meshpeer_ie *) frm;
+ meshpeer->peer_llinkid = LE_READ_2(&meshpeer->peer_llinkid);
+ meshpeer->peer_linkid = LE_READ_2(&meshpeer->peer_linkid);
+ meshpeer->peer_rcode = LE_READ_2(&meshpeer->peer_rcode);
break;
}
frm += frm[1] + 2;
@@ -570,15 +597,19 @@ mesh_recv_action(struct ieee80211_node *
vap->iv_stats.is_rx_mgtdiscard++;
return;
}
+
switch (ia->ia_category) {
+ /*
+ * Mesh Peer Link Management Finite State Machine handling.
+ */
case IEEE80211_ACTION_CAT_MESHPEERING:
switch (ia->ia_action) {
case IEEE80211_ACTION_MESHPEERING_OPEN:
IEEE80211_NOTE(vap,
IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
- "%s", "recv PEER OPEN");
+ "recv PEER OPEN, lid 0x%x", meshpeer->peer_llinkid);
switch (ni->ni_peerstate) {
- case IEEE80211_NODE_MESH_IDLE:
+ case IEEE80211_NODE_MESH_IDLE:
ni->ni_peerstate = IEEE80211_NODE_MESH_OPENRCV;
IEEE80211_NOTE(vap,
IEEE80211_MSG_MESH,
@@ -591,7 +622,7 @@ mesh_recv_action(struct ieee80211_node *
ieee80211_send_action(ni,
IEEE80211_ACTION_CAT_MESHPEERING,
IEEE80211_ACTION_MESHPEERING_OPEN, args);
- /* ... and confirm the link. */
+ /* ...and confirm the link. */
args[0] = ni->ni_plid;
args[1] = ni->ni_llid;
ieee80211_send_action(ni,
@@ -610,6 +641,7 @@ mesh_recv_action(struct ieee80211_node *
break;
case IEEE80211_NODE_MESH_OPENSNT:
ni->ni_peerstate = IEEE80211_NODE_MESH_OPENRCV;
+ ni->ni_llid = meshpeer->peer_llinkid;
IEEE80211_NOTE(vap,
IEEE80211_MSG_MESH,
ni, "peer link: switching to state %d",
@@ -635,12 +667,28 @@ mesh_recv_action(struct ieee80211_node *
IEEE80211_ACTION_MESHPEERING_CONFIRM, args);
/* clear timeoutC */
break;
+ case IEEE80211_NODE_MESH_ESTABLISHED:
+ args[0] = ni->ni_plid;
+ args[1] = ni->ni_llid;
+ ieee80211_send_action(ni,
+ IEEE80211_ACTION_CAT_MESHPEERING,
+ IEEE80211_ACTION_MESHPEERING_CONFIRM, args);
+ break;
+ case IEEE80211_NODE_MESH_HOLDING:
+ args[0] = ni->ni_llid;
+ args[1] = ni->ni_plid;
+ args[2] = IEEE80211_REASON_MESH_MAX_RETRIES;
+ ieee80211_send_action(ni,
+ IEEE80211_ACTION_CAT_MESHPEERING,
+ IEEE80211_ACTION_MESHPEERING_CLOSE, args);
+ break;
}
break;
case IEEE80211_ACTION_MESHPEERING_CONFIRM:
IEEE80211_NOTE(vap,
IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
- "%s", "recv PEER CONFIRM");
+ "recv PEER CONFIRM, local id 0x%x, peer id 0x%x",
+ meshpeer->peer_llinkid, meshpeer->peer_linkid);
switch (ni->ni_peerstate) {
case IEEE80211_NODE_MESH_OPENRCV:
ni->ni_peerstate = IEEE80211_NODE_MESH_ESTABLISHED;
@@ -648,7 +696,6 @@ mesh_recv_action(struct ieee80211_node *
IEEE80211_MSG_MESH,
ni, "peer link: switching to state %d",
ni->ni_peerstate);
- /* clear timeoutR */
break;
case IEEE80211_NODE_MESH_OPENSNT:
ni->ni_peerstate = IEEE80211_NODE_MESH_CONFIRMRECV;
@@ -657,14 +704,37 @@ mesh_recv_action(struct ieee80211_node *
ni, "peer link: switching to state %d",
ni->ni_peerstate);
break;
+ case IEEE80211_NODE_MESH_HOLDING:
+ args[0] = ni->ni_llid;
+ args[1] = ni->ni_plid;
+ args[2] = IEEE80211_REASON_MESH_MAX_RETRIES;
+ ieee80211_send_action(ni,
+ IEEE80211_ACTION_CAT_MESHPEERING,
+ IEEE80211_ACTION_MESHPEERING_CLOSE, args);
+ break;
default:
-
IEEE80211_DISCARD(vap,
IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
wh, NULL, "received confirm in invalid "
"state %d", ni->ni_peerstate);
vap->iv_stats.is_rx_mgtdiscard++;
}
+ break;
+ case IEEE80211_ACTION_MESHPEERING_CLOSE:
+ IEEE80211_NOTE(vap,
+ IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
+ "%s", "recv PEER CLOSE");
+ switch (ni->ni_peerstate) {
+ case IEEE80211_NODE_MESH_OPENRCV:
+ ni->ni_peerstate = IEEE80211_NODE_MESH_HOLDING;
+ MESH_SET_TIMEOUT(ni);
+ break;
+ case IEEE80211_NODE_MESH_OPENSNT:
+ break;
+ case IEEE80211_NODE_MESH_HOLDING:
+ break;
+ }
+ break;
}
break;
default:
@@ -675,6 +745,50 @@ mesh_recv_action(struct ieee80211_node *
}
/*
+ * Mesh Peer Link Management FSM timeout handling.
+ */
+static void
+mesh_peer_timeout(void *arg)
+{
+ struct ieee80211_node *ni = (struct ieee80211_node *)arg;
+ struct ieee80211vap *vap = ni->ni_vap;
+ uint16_t args[4];
+
+ IEEE80211_NOTE(vap,
+ IEEE80211_MSG_MESH,
+ ni, "mesh link timeout, state %d, retry counter %d",
+ ni->ni_peerstate, ni->ni_mrcount);
+
+ switch (ni->ni_peerstate) {
+ case IEEE80211_NODE_MESH_OPENSNT:
+ case IEEE80211_NODE_MESH_OPENRCV:
+ if (ni->ni_mrcount == ieee80211_mesh_maxretries) {
+ args[0] = ni->ni_plid;
+ args[2] = IEEE80211_REASON_MESH_MAX_RETRIES;
+ ieee80211_send_action(ni,
+ IEEE80211_ACTION_CAT_MESHPEERING,
+ IEEE80211_ACTION_MESHPEERING_CLOSE, args);
+ ni->ni_mrcount = 0;
+ ni->ni_peerstate = IEEE80211_NODE_MESH_HOLDING;
+ MESH_SET_TIMEOUT(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);
+ }
+ break;
+ case IEEE80211_NODE_MESH_CONFIRMRECV:
+
+ break;
+ case IEEE80211_NODE_MESH_HOLDING:
+ break;
+ }
+}
+
+/*
* Parse a MESH ID ie on station join.
*/
void
Modified: projects/mesh11s/sys/net80211/ieee80211_node.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_node.c Thu May 7 20:28:06 2009 (r191900)
+++ projects/mesh11s/sys/net80211/ieee80211_node.c Thu May 7 20:39:23 2009 (r191901)
@@ -1384,6 +1384,8 @@ ieee80211_init_neighbor(struct ieee80211
const struct ieee80211_frame *wh,
const struct ieee80211_scanparams *sp)
{
+ struct ieee80211vap *vap = ni->ni_vap;
+
ni->ni_esslen = sp->ssid[1];
memcpy(ni->ni_essid, sp->ssid + 2, sp->ssid[1]);
IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
@@ -1395,6 +1397,11 @@ ieee80211_init_neighbor(struct ieee80211
ni->ni_fhindex = sp->fhindex;
ni->ni_erp = sp->erp;
ni->ni_timoff = sp->timoff;
+ if (vap->iv_opmode == IEEE80211_M_MBSS) {
+ ni->ni_meshidlen = sp->meshid[1];
+ memcpy(ni->ni_meshid, sp->meshid + 2, sp->meshid[1]);
+ callout_init(&ni->ni_mtimer, CALLOUT_MPSAFE);
+ }
if (ieee80211_ies_init(&ni->ni_ies, sp->ies, sp->ies_len)) {
ieee80211_ies_expand(&ni->ni_ies);
Modified: projects/mesh11s/sys/net80211/ieee80211_node.h
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_node.h Thu May 7 20:28:06 2009 (r191900)
+++ projects/mesh11s/sys/net80211/ieee80211_node.h Thu May 7 20:39:23 2009 (r191901)
@@ -185,6 +185,9 @@ struct ieee80211_node {
int8_t ni_peerstate; /* Mesh Peering state */
uint16_t ni_llid; /* local link ID */
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 */
/* 11n state */
uint16_t ni_htcap; /* HT capabilities */
Modified: projects/mesh11s/sys/net80211/ieee80211_output.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_output.c Thu May 7 20:28:06 2009 (r191900)
+++ projects/mesh11s/sys/net80211/ieee80211_output.c Thu May 7 20:39:23 2009 (r191901)
@@ -663,6 +663,17 @@ ieee80211_send_action(struct ieee80211_n
case IEEE80211_ACTION_CAT_MESHPEERING:
rs = ieee80211_get_suprates(ic, ic->ic_curchan);
switch (action) {
+ /*
+ * mesh peer open action frame format:
+ * [1] action
+ * [1] category
+ * [2] capabilities
+ * [tlv] rates
+ * [tlv] xrates
+ * [tlv] mesh id
+ * [tlv] mesh conf
+ * [tlv] mesh peer link mgmt
+ */
case IEEE80211_ACTION_MESHPEERING_OPEN:
IEEE80211_NOTE(vap,
IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
@@ -675,6 +686,19 @@ ieee80211_send_action(struct ieee80211_n
frm = ieee80211_add_meshpeer(frm,
IEEE80211_MESH_PEER_LINK_OPEN, args[0], 0, 0);
break;
+ /*
+ * mesh peer confirm action frame format:
+ * [1] action
+ * [1] category
+ * [2] capabilities
+ * [2] status code
+ * [2] association id (0)
+ * [tlv] rates
+ * [tlv] xrates
+ * [tlv] mesh id
+ * [tlv] mesh conf
+ * [tlv] mesh peer link mgmt
+ */
case IEEE80211_ACTION_MESHPEERING_CONFIRM:
IEEE80211_NOTE(vap,
IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
@@ -691,6 +715,14 @@ ieee80211_send_action(struct ieee80211_n
IEEE80211_MESH_PEER_LINK_CONFIRM, args[0], args[1],
0);
break;
+ /*
+ * mesh peer close action frame format:
+ * [1] action
+ * [1] category
+ * [2] reason code
+ * [tlv] mesh id
+ * [tlv] mesh peer link mgmt
+ */
case IEEE80211_ACTION_MESHPEERING_CLOSE:
IEEE80211_NOTE(vap,
IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
More information about the svn-src-projects
mailing list