Date: Fri, 3 Jul 2009 21:51:44 +0000 (UTC) From: Rui Paulo <rpaulo@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r195328 - projects/mesh11s/sys/net80211 Message-ID: <200907032151.n63Lpi9h089429@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200907032151.n63Lpi9h089429>