svn commit: r195328 - projects/mesh11s/sys/net80211
Rui Paulo
rpaulo at FreeBSD.org
Fri Jul 3 21:51:45 UTC 2009
Author: rpaulo
Date: Fri Jul 3 21:51:44 2009
New Revision: 195328
URL: http://svn.freebsd.org/changeset/base/195328
Log:
* reuse ibss code to create a mbss
* first steps at implementing mesh scanning
* fill in more state stuff: CAC, CSA
Submited by: sam
Modified:
projects/mesh11s/sys/net80211/ieee80211_mesh.c
projects/mesh11s/sys/net80211/ieee80211_mesh.h
projects/mesh11s/sys/net80211/ieee80211_node.c
projects/mesh11s/sys/net80211/ieee80211_scan_sta.c
Modified: projects/mesh11s/sys/net80211/ieee80211_mesh.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_mesh.c Fri Jul 3 21:45:56 2009 (r195327)
+++ projects/mesh11s/sys/net80211/ieee80211_mesh.c Fri Jul 3 21:51:44 2009 (r195328)
@@ -228,6 +228,9 @@ mesh_newstate(struct ieee80211vap *vap,
case IEEE80211_S_SCAN:
ieee80211_cancel_scan(vap);
break;
+ case IEEE80211_S_CAC:
+ ieee80211_dfs_cac_stop(vap);
+ break;
case IEEE80211_S_RUN:
ieee80211_iterate_nodes(&ic->ic_sta,
mesh_vdetach_peers, NULL);
@@ -250,7 +253,7 @@ mesh_newstate(struct ieee80211vap *vap,
* Already have a channel and a mesh ID; bypass
* the scan and startup immediately.
*/
- ieee80211_create_mbss(vap, vap->iv_des_chan);
+ ieee80211_create_ibss(vap, vap->iv_des_chan);
break;
}
/*
@@ -270,16 +273,76 @@ mesh_newstate(struct ieee80211vap *vap,
vap->iv_flags_ext &= ~IEEE80211_FEXT_SCANREQ;
} else
ieee80211_check_scan_current(vap);
- break;
+ break;
default:
break;
}
- case IEEE80211_S_AUTH:
- case IEEE80211_S_ASSOC:
case IEEE80211_S_CAC:
+ /*
+ * Start CAC on a DFS channel. We come here when starting
+ * a bss on a DFS channel (see ieee80211_create_ibss).
+ */
+ ieee80211_dfs_cac_start(vap);
+ break;
case IEEE80211_S_RUN:
- case IEEE80211_S_CSA:
- case IEEE80211_S_SLEEP:
+ switch (ostate) {
+ case IEEE80211_S_INIT:
+ /*
+ * Already have a channel; bypass the
+ * scan and startup immediately.
+ * Note that ieee80211_create_ibss will call
+ * back to do a RUN->RUN state change.
+ */
+ ieee80211_create_ibss(vap,
+ ieee80211_ht_adjust_channel(ic,
+ ic->ic_curchan, vap->iv_flags_ht));
+ /* NB: iv_bss is changed on return */
+ break;
+ case IEEE80211_S_CAC:
+ /*
+ * NB: This is the normal state change when CAC
+ * expires and no radar was detected; no need to
+ * clear the CAC timer as it's already expired.
+ */
+ /* fall thru... */
+ case IEEE80211_S_CSA:
+#if 0
+ /*
+ * Shorten inactivity timer of associated stations
+ * to weed out sta's that don't follow a CSA.
+ */
+ ieee80211_iterate_nodes(&ic->ic_sta, sta_csa, vap);
+#endif
+ /*
+ * Update bss node channel to reflect where
+ * we landed after CSA.
+ */
+ ieee80211_node_set_chan(vap->iv_bss,
+ ieee80211_ht_adjust_channel(ic, ic->ic_curchan,
+ ieee80211_htchanflags(vap->iv_bss->ni_chan)));
+ /* XXX bypass debug msgs */
+ break;
+ case IEEE80211_S_SCAN:
+ case IEEE80211_S_RUN:
+#ifdef IEEE80211_DEBUG
+ if (ieee80211_msg_debug(vap)) {
+ struct ieee80211_node *ni = vap->iv_bss;
+ ieee80211_note(vap,
+ "synchronized with %s meshid ",
+ ether_sprintf(ni->ni_meshid));
+ ieee80211_print_essid(ni->ni_meshid,
+ ni->ni_meshidlen);
+ /* XXX MCS/HT */
+ printf(" channel %d\n",
+ ieee80211_chan2ieee(ic, ic->ic_curchan));
+ }
+#endif
+ break;
+ default:
+ break;
+ }
+ ieee80211_node_authorize(vap->iv_bss);
+ break;
default:
break;
}
@@ -2025,6 +2088,7 @@ ieee80211_add_meshlmetric(uint8_t *frm,
void
ieee80211_mesh_node_init(struct ieee80211vap *vap, struct ieee80211_node *ni)
{
+ ni->ni_flags |= IEEE80211_NODE_QOS;
callout_init(&ni->ni_mltimer, CALLOUT_MPSAFE);
}
@@ -2034,7 +2098,14 @@ ieee80211_mesh_node_init(struct ieee8021
void
ieee80211_mesh_node_cleanup(struct ieee80211_node *ni)
{
- /* XXX stop/drain timer? */
+ callout_drain(&ni->ni_mltimer);
+}
+
+void
+ieee80211_parse_meshid(struct ieee80211_node *ni, const uint8_t *ie)
+{
+ ni->ni_meshidlen = ie[1];
+ memcpy(ni->ni_meshid, ie + 2, ie[1]);
}
/*
@@ -2045,80 +2116,7 @@ ieee80211_mesh_init_neighbor(struct ieee
const struct ieee80211_frame *wh,
const struct ieee80211_scanparams *sp)
{
- ni->ni_meshidlen = sp->meshid[1];
- memcpy(ni->ni_meshid, sp->meshid + 2, sp->meshid[1]);
-}
-
-void
-ieee80211_create_mbss(struct ieee80211vap *vap, struct ieee80211_channel *chan)
-{
- struct ieee80211com *ic = vap->iv_ic;
- struct ieee80211_mesh_state *ms = vap->iv_mesh;
- struct ieee80211_node *ni;
-
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_MESH,
- "%s: creating MBSS on channel %u\n", __func__,
- ieee80211_chan2ieee(ic, chan));
-
- ni = ieee80211_alloc_node(&ic->ic_sta, vap, vap->iv_myaddr);
- if (ni == NULL) {
- /* XXX recovery? */
- return;
- }
- IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_myaddr);
- ni->ni_meshidlen = ms->ms_idlen;
- memcpy(ni->ni_meshid, ms->ms_id, ni->ni_meshidlen);
- ni->ni_intval = ic->ic_bintval;
- /* NB: mesh nodes must be QoS capable */
- ni->ni_flags |= IEEE80211_NODE_QOS;
- /*
- * Fix the channel and related attributes.
- */
- /* clear DFS CAC state on previous channel */
- if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
- ic->ic_bsschan->ic_freq != chan->ic_freq &&
- IEEE80211_IS_CHAN_CACDONE(ic->ic_bsschan))
- ieee80211_dfs_cac_clear(ic, ic->ic_bsschan);
- ic->ic_bsschan = chan;
- ieee80211_node_set_chan(ni, chan);
- ic->ic_curmode = ieee80211_chan2mode(chan);
- /*
- * Do mode-specific setup.
- */
- if (IEEE80211_IS_CHAN_FULL(chan)) {
- if (IEEE80211_IS_CHAN_ANYG(chan)) {
- /*
- * Use a mixed 11b/11g basic rate set.
- */
- ieee80211_setbasicrates(&ni->ni_rates,
- IEEE80211_MODE_11G);
- if (vap->iv_flags & IEEE80211_F_PUREG) {
- /*
- * Also mark OFDM rates basic so 11b
- * stations do not join (WiFi compliance).
- */
- ieee80211_addbasicrates(&ni->ni_rates,
- IEEE80211_MODE_11A);
- }
- } else if (IEEE80211_IS_CHAN_B(chan)) {
- /*
- * Force pure 11b rate set.
- */
- ieee80211_setbasicrates(&ni->ni_rates,
- IEEE80211_MODE_11B);
- }
- }
- ieee80211_ref_node(ni);
- vap->iv_bss = ni;
- ieee80211_setcurchan(ic, ni->ni_chan);
- /*
- * Set the erp state (mostly the slot time) to deal with
- * the auto-select case; this should be redundant if the
- * mode is locked.
- */
- ieee80211_reset_erp(ic);
- ieee80211_wme_initparams(vap);
- ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
+ ieee80211_parse_meshid(ni, sp->meshid);
}
static int
Modified: projects/mesh11s/sys/net80211/ieee80211_mesh.h
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_mesh.h Fri Jul 3 21:45:56 2009 (r195327)
+++ projects/mesh11s/sys/net80211/ieee80211_mesh.h Fri Jul 3 21:51:44 2009 (r195328)
@@ -409,7 +409,7 @@ struct ieee80211_mesh_state {
};
void ieee80211_mesh_attach(struct ieee80211com *);
void ieee80211_mesh_detach(struct ieee80211com *);
-void ieee80211_parse_meshid(struct ieee80211_node *, const uint8_t *);
+
uint8_t * ieee80211_add_meshpeerver(uint8_t *, struct ieee80211vap *);
uint8_t * ieee80211_add_meshid(uint8_t *, struct ieee80211vap *);
uint8_t * ieee80211_add_meshconf(uint8_t *, struct ieee80211vap *);
@@ -421,11 +421,11 @@ uint8_t * ieee80211_add_meshlmetric(uint
void ieee80211_mesh_node_init(struct ieee80211vap *,
struct ieee80211_node *);
void ieee80211_mesh_node_cleanup(struct ieee80211_node *);
+void ieee80211_parse_meshid(struct ieee80211_node *,
+ const uint8_t *);
struct ieee80211_scanparams;
void ieee80211_mesh_init_neighbor(struct ieee80211_node *,
const struct ieee80211_frame *,
const struct ieee80211_scanparams *);
-void ieee80211_create_mbss(struct ieee80211vap *, struct
- ieee80211_channel *);
#endif /* _KERNEL */
#endif /* !_NET80211_IEEE80211_MESH_H_ */
Modified: projects/mesh11s/sys/net80211/ieee80211_node.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_node.c Fri Jul 3 21:45:56 2009 (r195327)
+++ projects/mesh11s/sys/net80211/ieee80211_node.c Fri Jul 3 21:51:44 2009 (r195328)
@@ -328,7 +328,8 @@ ieee80211_create_ibss(struct ieee80211va
struct ieee80211_node *ni;
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
- "%s: creating ibss on channel %u\n", __func__,
+ "%s: creating %s on channel %u\n", __func__,
+ ieee80211_opmode_name[vap->iv_opmode],
ieee80211_chan2ieee(ic, chan));
ni = ieee80211_alloc_node(&ic->ic_sta, vap, vap->iv_myaddr);
@@ -366,6 +367,9 @@ ieee80211_create_ibss(struct ieee80211va
if ((vap->iv_caps & IEEE80211_C_TDMA) == 0)
#endif
memset(ni->ni_bssid, 0, IEEE80211_ADDR_LEN);
+ } else if (vap->iv_opmode == IEEE80211_M_MBSS) {
+ ni->ni_meshidlen = vap->iv_mesh->ms_idlen;
+ memcpy(ni->ni_meshid, vap->iv_mesh->ms_id, ni->ni_meshidlen);
}
/*
* Fix the channel and related attributes.
@@ -791,6 +795,8 @@ ieee80211_sta_join(struct ieee80211vap *
ieee80211_parse_htcap(ni, ni->ni_ies.htcap_ie);
if (ni->ni_ies.htinfo_ie != NULL)
ieee80211_parse_htinfo(ni, ni->ni_ies.htinfo_ie);
+ if (ni->ni_ies.meshid_ie != NULL)
+ ieee80211_parse_meshid(ni, ni->ni_ies.meshid_ie);
#ifdef IEEE80211_SUPPORT_TDMA
if (ni->ni_ies.tdma_ie != NULL)
ieee80211_parse_tdma(ni, ni->ni_ies.tdma_ie);
Modified: projects/mesh11s/sys/net80211/ieee80211_scan_sta.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_scan_sta.c Fri Jul 3 21:45:56 2009 (r195327)
+++ projects/mesh11s/sys/net80211/ieee80211_scan_sta.c Fri Jul 3 21:51:44 2009 (r195328)
@@ -127,7 +127,8 @@ static void sta_flush_table(struct sta_t
#define MATCH_TDMA_NOSLOT 0x01000 /* all TDMA slots occupied */
#define MATCH_TDMA_LOCAL 0x02000 /* local address */
#define MATCH_TDMA_VERSION 0x04000 /* protocol version mismatch */
-#define MATCH_MESH_ID 0x10000 /* no MESH ID ie */
+#define MATCH_MESH_NOID 0x10000 /* no MESHID ie */
+#define MATCH_MESHID 0x20000 /* meshid mismatch */
static int match_bss(struct ieee80211vap *,
const struct ieee80211_scan_state *, struct sta_entry *, int);
static void adhoc_age(struct ieee80211_scan_state *);
@@ -898,6 +899,12 @@ back:
#undef RV
}
+static __inline int
+match_id(const uint8_t *ie, const uint8_t *val, int len)
+{
+ return (ie[1] == len && memcmp(ie+2, val, len) == 0);
+}
+
static int
match_ssid(const uint8_t *ie,
int nssid, const struct ieee80211_scan_ssid ssids[])
@@ -905,8 +912,7 @@ match_ssid(const uint8_t *ie,
int i;
for (i = 0; i < nssid; i++) {
- if (ie[1] == ssids[i].len &&
- memcmp(ie+2, ssids[i].ssid, ie[1]) == 0)
+ if (match_id(ie, ssids[i].ssid, ssids[i].len))
return 1;
}
return 0;
@@ -990,16 +996,18 @@ match_bss(struct ieee80211vap *vap,
}
#endif /* IEEE80211_SUPPORT_TDMA */
} else if (vap->iv_opmode == IEEE80211_M_MBSS) {
+ const struct ieee80211_mesh_state *ms = vap->iv_mesh;
/*
- * Mesh nodes have IBSS & ESS bits in capinfo turned off.
+ * Mesh nodes have IBSS & ESS bits in capinfo turned off
+ * and two special ie's that must be present.
*/
if (se->se_capinfo & (IEEE80211_CAPINFO_IBSS|IEEE80211_CAPINFO_ESS))
fail |= MATCH_CAPINFO;
-
- if (vap->iv_caps & IEEE80211_C_MBSS) {
- /*const struct ieee80211_meshid_ie *meshid =
- (const struct ieee80211_meshid_ie *)se->se_ies.meshid_ie;*/
- }
+ else if (se->se_meshid == NULL)
+ fail |= MATCH_MESH_NOID;
+ else if (vap->iv_mesh->ms_idlen != 0 &&
+ match_id(se->se_meshid, ms->ms_id, ms->ms_idlen))
+ fail |= MATCH_MESHID;
} else {
if ((se->se_capinfo & IEEE80211_CAPINFO_ESS) == 0)
fail |= MATCH_CAPINFO;
@@ -1084,7 +1092,7 @@ match_bss(struct ieee80211vap *vap,
fail & MATCH_TDMA_NOSLOT ? 'f' :
fail & MATCH_TDMA_LOCAL ? 'l' :
#endif
- fail & MATCH_MESH_ID ? 'm' :
+ fail & MATCH_MESH_NOID ? 'm' :
fail ? '-' : '+', ether_sprintf(se->se_macaddr));
printf(" %s%c", ether_sprintf(se->se_bssid),
fail & MATCH_BSSID ? '!' : ' ');
@@ -1102,7 +1110,7 @@ match_bss(struct ieee80211vap *vap,
"wep" : "no",
fail & MATCH_PRIVACY ? '!' : ' ');
ieee80211_print_essid(se->se_ssid+2, se->se_ssid[1]);
- printf("%s\n", fail & MATCH_SSID ? "!" : "");
+ printf("%s\n", fail & (MATCH_SSID | MATCH_MESHID) ? "!" : "");
}
#endif
return fail;
@@ -1798,6 +1806,90 @@ static const struct ieee80211_scanner ap
.scan_assoc_fail = sta_assoc_fail,
};
+/*
+ * Pick an mbss network to join or find a channel
+ * to use to start an mbss network.
+ */
+static int
+mesh_pick_bss(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
+{
+ struct sta_table *st = ss->ss_priv;
+ struct ieee80211_mesh_state *ms = vap->iv_mesh;
+ struct sta_entry *selbs;
+ struct ieee80211_channel *chan;
+
+ KASSERT(vap->iv_opmode == IEEE80211_M_MBSS,
+ ("wrong opmode %u", vap->iv_opmode));
+
+ if (st->st_newscan) {
+ sta_update_notseen(st);
+ st->st_newscan = 0;
+ }
+ if (ss->ss_flags & IEEE80211_SCAN_NOPICK) {
+ /*
+ * Manual/background scan, don't select+join the
+ * bss, just return. The scanning framework will
+ * handle notification that this has completed.
+ */
+ ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;
+ return 1;
+ }
+ /*
+ * Automatic sequencing; look for a candidate and
+ * if found join the network.
+ */
+ /* NB: unlocked read should be ok */
+ if (TAILQ_FIRST(&st->st_entry) == NULL) {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: no scan candidate\n", __func__);
+ if (ss->ss_flags & IEEE80211_SCAN_NOJOIN)
+ return 0;
+notfound:
+ if (ms->ms_idlen != 0) {
+ /*
+ * No existing mbss network to join and we have
+ * a meshid; start one up. If no channel was
+ * specified, try to select a channel.
+ */
+ if (vap->iv_des_chan == IEEE80211_CHAN_ANYC ||
+ IEEE80211_IS_CHAN_RADAR(vap->iv_des_chan)) {
+ struct ieee80211com *ic = vap->iv_ic;
+
+ chan = adhoc_pick_channel(ss, 0);
+ if (chan != NULL)
+ chan = ieee80211_ht_adjust_channel(ic,
+ chan, vap->iv_flags_ht);
+ } else
+ chan = vap->iv_des_chan;
+ if (chan != NULL) {
+ ieee80211_create_ibss(vap, chan);
+ return 1;
+ }
+ }
+ /*
+ * If nothing suitable was found decrement
+ * the failure counts so entries will be
+ * reconsidered the next time around. We
+ * really want to do this only for sta's
+ * where we've previously had some success.
+ */
+ sta_dec_fails(st);
+ st->st_newscan = 1;
+ return 0; /* restart scan */
+ }
+ selbs = select_bss(ss, vap, IEEE80211_MSG_SCAN);
+ if (ss->ss_flags & IEEE80211_SCAN_NOJOIN)
+ return (selbs != NULL);
+ if (selbs == NULL)
+ goto notfound;
+ chan = selbs->base.se_chan;
+ if (selbs->se_flags & STA_DEMOTE11B)
+ chan = demote11b(vap, chan);
+ if (!ieee80211_sta_join(vap, chan, &selbs->base))
+ goto notfound;
+ return 1; /* terminate scan */
+}
+
static const struct ieee80211_scanner mesh_default = {
.scan_name = "default",
.scan_attach = sta_attach,
@@ -1805,7 +1897,7 @@ static const struct ieee80211_scanner me
.scan_start = adhoc_start,
.scan_restart = sta_restart,
.scan_cancel = sta_cancel,
- .scan_end = adhoc_pick_bss,
+ .scan_end = mesh_pick_bss,
.scan_flush = sta_flush,
.scan_pickchan = adhoc_pick_channel,
.scan_add = sta_add,
More information about the svn-src-projects
mailing list