Date: Sun, 10 May 2009 18:17:26 +0000 (UTC) From: Rui Paulo <rpaulo@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r191967 - projects/mesh11s/sys/net80211 Message-ID: <200905101817.n4AIHQ8v064781@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200905101817.n4AIHQ8v064781>