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