svn commit: r189980 - in head/sys: dev/ath net80211

Sam Leffler sam at FreeBSD.org
Wed Mar 18 12:28:18 PDT 2009


Author: sam
Date: Wed Mar 18 19:28:17 2009
New Revision: 189980
URL: http://svn.freebsd.org/changeset/base/189980

Log:
  Minor cleanups of tdma protocol handling:
  o break out version-related code to simplify rev'ing the protocol
  o add parameter validation macros so checks that appear multiple places
    are consistent (and easy to change)
  o add protocol version check when looking for a scan candidate
  o improve scan debug output format
  o rewrite beacon update handling to calculate a bitmask of changed values
    and pass that down through the driver callback so drivers can optimize work
  o do slot bounds check before use when parsing received beacons

Modified:
  head/sys/dev/ath/if_ath.c
  head/sys/net80211/ieee80211.h
  head/sys/net80211/ieee80211_scan_sta.c
  head/sys/net80211/ieee80211_tdma.c
  head/sys/net80211/ieee80211_tdma.h
  head/sys/net80211/ieee80211_var.h

Modified: head/sys/dev/ath/if_ath.c
==============================================================================
--- head/sys/dev/ath/if_ath.c	Wed Mar 18 18:46:50 2009	(r189979)
+++ head/sys/dev/ath/if_ath.c	Wed Mar 18 19:28:17 2009	(r189980)
@@ -225,7 +225,7 @@ static void	ath_tdma_bintvalsetup(struct
 		    const struct ieee80211_tdma_state *tdma);
 static void	ath_tdma_config(struct ath_softc *sc, struct ieee80211vap *vap);
 static void	ath_tdma_update(struct ieee80211_node *ni,
-		    const struct ieee80211_tdma_param *tdma);
+		    const struct ieee80211_tdma_param *tdma, int);
 static void	ath_tdma_beacon_send(struct ath_softc *sc,
 		    struct ieee80211vap *vap);
 
@@ -7477,7 +7477,7 @@ ath_tdma_config(struct ath_softc *sc, st
  */
 static void
 ath_tdma_update(struct ieee80211_node *ni,
-	const struct ieee80211_tdma_param *tdma)
+	const struct ieee80211_tdma_param *tdma, int changed)
 {
 #define	TSF_TO_TU(_h,_l) \
 	((((u_int32_t)(_h)) << 22) | (((u_int32_t)(_l)) >> 10))
@@ -7498,7 +7498,7 @@ ath_tdma_update(struct ieee80211_node *n
 	/*
 	 * Check for and adopt configuration changes.
 	 */
-	if (isset(ATH_VAP(vap)->av_boff.bo_flags, IEEE80211_BEACON_TDMA)) {
+	if (changed != 0) {
 		const struct ieee80211_tdma_state *ts = vap->iv_tdma;
 
 		ath_tdma_bintvalsetup(sc, ts);

Modified: head/sys/net80211/ieee80211.h
==============================================================================
--- head/sys/net80211/ieee80211.h	Wed Mar 18 18:46:50 2009	(r189979)
+++ head/sys/net80211/ieee80211.h	Wed Mar 18 19:28:17 2009	(r189980)
@@ -1077,15 +1077,27 @@ struct ieee80211_duration {
 #define	ATH_FF_SNAP_ORGCODE_1	0x03
 #define	ATH_FF_SNAP_ORGCODE_2	0x7f
 
+/* NB: Atheros allocated the OUI for this purpose ~2005 but beware ... */
+#define	TDMA_OUI		ATH_OUI
+#define	TDMA_OUI_TYPE		0x02
+#define	TDMA_VERSION_V2		2
+#define	TDMA_VERSION		TDMA_VERSION_V2
+
+/* NB: we only support 2 right now but protocol handles up to 8 */
+#define	TDMA_MAXSLOTS		2	/* max slots/sta's */
+
+#define	TDMA_PARAM_LEN_V2	sizeof(struct ieee80211_tdma_param)
+
 struct ieee80211_tdma_param {
 	u_int8_t	tdma_id;	/* IEEE80211_ELEMID_VENDOR */
 	u_int8_t	tdma_len;
 	u_int8_t	tdma_oui[3];	/* 0x00, 0x03, 0x7f */
 	u_int8_t	tdma_type;	/* OUI type */
 	u_int8_t	tdma_subtype;	/* OUI subtype */
+#define	TDMA_SUBTYPE_PARAM	0x01
 	u_int8_t	tdma_version;	/* spec revision */
-	u_int8_t	tdma_slot;	/* station slot # */
-	u_int8_t	tdma_slotcnt;	/* bss slot count */
+	u_int8_t	tdma_slot;	/* station slot # [0..7] */
+	u_int8_t	tdma_slotcnt;	/* bss slot count [1..8] */
 	u_int16_t	tdma_slotlen;	/* bss slot len (100us) */
 	u_int8_t	tdma_bintval;	/* beacon interval (superframes) */
 	u_int8_t	tdma_inuse[1];	/* slot occupancy map */
@@ -1093,10 +1105,14 @@ struct ieee80211_tdma_param {
 	u_int8_t	tdma_tstamp[8];	/* timestamp from last beacon */
 } __packed;
 
-/* NB: Atheros allocated the OUI for this purpose ~3 years ago but beware ... */
-#define	TDMA_OUI		ATH_OUI
-#define	TDMA_OUI_TYPE		0x02
-#define	TDMA_SUBTYPE_PARAM	0x01
-#define	TDMA_VERSION		2
+#define	TDMA_VERSION_VALID(_version) \
+	(TDMA_VERSION_V2 <= (_version) && (_version) <= TDMA_VERSION)
+#define	TDMA_SLOTCNT_VALID(_slotcnt) \
+	(2 <= (_slotcnt) && (_slotcnt) <= TDMA_MAXSLOTS)
+/* XXX magic constants */
+#define	TDMA_SLOTLEN_VALID(_slotlen) \
+	(2*100 <= (_slotlen) && (unsigned)(_slotlen) <= 0xfffff)
+/* XXX probably should set a max */
+#define	TDMA_BINTVAL_VALID(_bintval)	(1 <= (_bintval))
 
 #endif /* _NET80211_IEEE80211_H_ */

Modified: head/sys/net80211/ieee80211_scan_sta.c
==============================================================================
--- head/sys/net80211/ieee80211_scan_sta.c	Wed Mar 18 18:46:50 2009	(r189979)
+++ head/sys/net80211/ieee80211_scan_sta.c	Wed Mar 18 19:28:17 2009	(r189980)
@@ -126,6 +126,7 @@ static void sta_flush_table(struct sta_t
 #define	MATCH_TDMA_NOTMASTER	0x0800	/* not TDMA master */
 #define	MATCH_TDMA_NOSLOT	0x1000	/* all TDMA slots occupied */
 #define	MATCH_TDMA_LOCAL	0x2000	/* local address */
+#define	MATCH_TDMA_VERSION	0x4000	/* protocol version mismatch */
 static int match_bss(struct ieee80211vap *,
 	const struct ieee80211_scan_state *, struct sta_entry *, int);
 static void adhoc_age(struct ieee80211_scan_state *);
@@ -970,9 +971,12 @@ match_bss(struct ieee80211vap *vap,
 		if (vap->iv_caps & IEEE80211_C_TDMA) {
 			const struct ieee80211_tdma_param *tdma =
 			    (const struct ieee80211_tdma_param *)se->se_ies.tdma_ie;
+			const struct ieee80211_tdma_state *ts = vap->iv_tdma;
 
 			if (tdma == NULL)
 				fail |= MATCH_TDMA_NOIE;
+			else if (tdma->tdma_version != ts->tdma_version)
+				fail |= MATCH_TDMA_VERSION;
 			else if (tdma->tdma_slot != 0)
 				fail |= MATCH_TDMA_NOTMASTER;
 			else if (tdma_isfull(tdma))
@@ -1062,9 +1066,10 @@ match_bss(struct ieee80211vap *vap,
 		    fail & MATCH_CC ? '$' :
 #ifdef IEEE80211_SUPPORT_TDMA
 		    fail & MATCH_TDMA_NOIE ? '&' :
-		    fail & MATCH_TDMA_NOTMASTER ? ':' :
-		    fail & MATCH_TDMA_NOSLOT ? '@' :
-		    fail & MATCH_TDMA_LOCAL ? '#' :
+		    fail & MATCH_TDMA_VERSION ? 'v' :
+		    fail & MATCH_TDMA_NOTMASTER ? 's' :
+		    fail & MATCH_TDMA_NOSLOT ? 'f' :
+		    fail & MATCH_TDMA_LOCAL ? 'l' :
 #endif
 		    fail ? '-' : '+', ether_sprintf(se->se_macaddr));
 		printf(" %s%c", ether_sprintf(se->se_bssid),
@@ -1076,8 +1081,7 @@ match_bss(struct ieee80211vap *vap,
 		    fail & MATCH_RATE ? '!' : ' ');
 		printf(" %4s%c",
 		    (se->se_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" :
-		    (se->se_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" :
-		    "????",
+		    (se->se_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" : "",
 		    fail & MATCH_CAPINFO ? '!' : ' ');
 		printf(" %3s%c ",
 		    (se->se_capinfo & IEEE80211_CAPINFO_PRIVACY) ?

Modified: head/sys/net80211/ieee80211_tdma.c
==============================================================================
--- head/sys/net80211/ieee80211_tdma.c	Wed Mar 18 18:46:50 2009	(r189979)
+++ head/sys/net80211/ieee80211_tdma.c	Wed Mar 18 19:28:17 2009	(r189980)
@@ -142,6 +142,7 @@ ieee80211_tdma_vattach(struct ieee80211v
 		return;
 	}
 	/* NB: default configuration is passive so no beacons */
+	ts->tdma_version = TDMA_VERSION;
 	ts->tdma_slotlen = TDMA_SLOTLEN_DEFAULT;
 	ts->tdma_slotcnt = TDMA_SLOTCNT_DEFAULT;
 	ts->tdma_bintval = TDMA_BINTVAL_DEFAULT;
@@ -371,71 +372,90 @@ tdma_recv_mgmt(struct ieee80211_node *ni
  * a TDMA information element.  The sender's identity
  * is provided so we can track who our peer is.  If pickslot
  * is non-zero we scan the slot allocation state in the ie
- * locate a free slot for our use.
+ * to locate a free slot for our use.
  */
 static int
 tdma_update(struct ieee80211vap *vap, const struct ieee80211_tdma_param *tdma,
 	struct ieee80211_node *ni, int pickslot)
 {
 	struct ieee80211_tdma_state *ts = vap->iv_tdma;
-	int slotlen, slotcnt, slot, bintval;
+	int slot, slotlen, update;
 
 	KASSERT(vap->iv_caps & IEEE80211_C_TDMA,
 	     ("not a tdma vap, caps 0x%x", vap->iv_caps));
 
-	slotlen = le16toh(tdma->tdma_slotlen);
-	slotcnt = tdma->tdma_slotcnt;
-	bintval = tdma->tdma_bintval;
-
-	/* XXX rate-limit printf's */
-	if (!(2 <= slotcnt && slotcnt <= IEEE80211_TDMA_MAXSLOTS)) {
-		printf("%s: bogus slot cnt %u\n", __func__, slotcnt);
-		return 0;
-	}
-	/* XXX magic constants */
-	if (slotlen < 2 || slotlen > (0xfffff/100)) {
-		printf("%s: bogus slot len %u\n", __func__, slotlen);
-		return 0;
-	}
-	if (bintval < 1) {
-		printf("%s: bogus beacon interval %u\n", __func__, bintval);
-		return 0;
-	}
+	update = 0;
+	if (tdma->tdma_slotcnt != ts->tdma_slotcnt) {
+		if (!TDMA_SLOTCNT_VALID(tdma->tdma_slotcnt)) {
+			printf("%s: bad slot cnt %u\n",
+			    __func__, tdma->tdma_slotcnt);
+			return 0;
+		}
+		update |= TDMA_UPDATE_SLOTCNT;
+ 	}
+	slotlen = le16toh(tdma->tdma_slotlen) * 100;
+	if (slotlen != ts->tdma_slotlen) {
+		if (!TDMA_SLOTLEN_VALID(slotlen)) {
+			printf("%s: bad slot len %u\n",
+			    __func__, slotlen);
+			return 0;
+		}
+		update |= TDMA_UPDATE_SLOTLEN;
+ 	}
+	if (tdma->tdma_bintval != ts->tdma_bintval) {
+		if (!TDMA_BINTVAL_VALID(tdma->tdma_bintval)) {
+			printf("%s: bad beacon interval %u\n",
+			    __func__, tdma->tdma_bintval);
+			return 0;
+		}
+		update |= TDMA_UPDATE_BINTVAL;
+ 	}
+	slot = ts->tdma_slot;
 	if (pickslot) {
 		/*
 		 * Pick unoccupied slot.  Note we never choose slot 0.
 		 */
-		for (slot = slotcnt-1; slot > 0; slot--)
+		for (slot = tdma->tdma_slotcnt-1; slot > 0; slot--)
 			if (isclr(tdma->tdma_inuse, slot))
 				break;
 		if (slot <= 0) {
 			printf("%s: no free slot, slotcnt %u inuse: 0x%x\n",
-				__func__, slotcnt, tdma->tdma_inuse[0]);
+				__func__, tdma->tdma_slotcnt,
+				tdma->tdma_inuse[0]);
 			/* XXX need to do something better */
 			return 0;
 		}
-	} else
-		slot = ts->tdma_slot;
+		if (slot != ts->tdma_slot)
+			update |= TDMA_UPDATE_SLOT;
+	}
+	if (ni != ts->tdma_peer) {
+		/* update everything */
+		update = TDMA_UPDATE_SLOT
+		       | TDMA_UPDATE_SLOTCNT
+		       | TDMA_UPDATE_SLOTLEN
+		       | TDMA_UPDATE_BINTVAL;
+	}
 
-	if (slotcnt != ts->tdma_slotcnt ||
-	    100*slotlen != ts->tdma_slotlen ||
-	    bintval != ts->tdma_bintval ||
-	    slot != ts->tdma_slot ||
-	    ts->tdma_peer != ni) {
+	if (update) {
 		/*
 		 * New/changed parameters; update runtime state.
 		 */
 		/* XXX overwrites user parameters */
-		ts->tdma_slotcnt = slotcnt;
-		ts->tdma_slotlen = 100*slotlen;
-		ts->tdma_slot = slot;
-		ts->tdma_bintval = bintval;
+		if (update & TDMA_UPDATE_SLOTCNT)
+			ts->tdma_slotcnt = tdma->tdma_slotcnt;
+		if (update & TDMA_UPDATE_SLOTLEN)
+			ts->tdma_slotlen = slotlen;
+		if (update & TDMA_UPDATE_SLOT)
+			ts->tdma_slot = slot;
+		if (update & TDMA_UPDATE_BINTVAL)
+			ts->tdma_bintval = tdma->tdma_bintval;
 		/* mark beacon to be updated before next xmit */
 		ieee80211_beacon_notify(vap, IEEE80211_BEACON_TDMA);
 
 		IEEE80211_DPRINTF(vap, IEEE80211_MSG_TDMA,
 		    "%s: slot %u slotcnt %u slotlen %u us bintval %u\n",
-		    __func__, slot, slotcnt, 100*slotlen, tdma->tdma_bintval);
+		    __func__, ts->tdma_slot, ts->tdma_slotcnt,
+		    100*ts->tdma_slotlen, ts->tdma_bintval);
 	}
 	/*
 	 * Notify driver.  Note we can be called before
@@ -445,7 +465,7 @@ tdma_update(struct ieee80211vap *vap, co
 	 * has been setup.  The next beacon will dtrt.
 	 */
 	if (vap->iv_state == IEEE80211_S_RUN)
-		vap->iv_ic->ic_tdma_update(ni, tdma);
+		vap->iv_ic->ic_tdma_update(ni, tdma, update);
 	/*
 	 * Dispatch join event on first beacon from new master.
 	 */
@@ -481,10 +501,23 @@ tdma_process_params(struct ieee80211_nod
 		    wh, "tdma", "too short, len %u", len);
 		return IEEE80211_REASON_IE_INVALID;
 	}
-	if (tdma->tdma_version != TDMA_VERSION) {
+	if (tdma->tdma_version != ts->tdma_version) {
+		IEEE80211_DISCARD_IE(vap,
+		    IEEE80211_MSG_ELEMID | IEEE80211_MSG_TDMA,
+		    wh, "tdma", "bad version %u (ours %u)",
+		    tdma->tdma_version, ts->tdma_version);
+		return IEEE80211_REASON_IE_INVALID;
+	}
+ 	/*
+	 * NB: ideally we'd check against tdma_slotcnt, but that
+	 * would require extra effort so do this easy check that
+	 * covers the work below; more stringent checks are done
+	 * before we make more extensive use of the ie contents.
+	 */
+	if (tdma->tdma_slot >= TDMA_MAXSLOTS) {
 		IEEE80211_DISCARD_IE(vap,
 		    IEEE80211_MSG_ELEMID | IEEE80211_MSG_TDMA,
-		    wh, "tdma", "bad version %u", tdma->tdma_version);
+		    wh, "tdma", "invalid slot %u", tdma->tdma_slot);
 		return IEEE80211_REASON_IE_INVALID;
 	}
 	/*
@@ -612,7 +645,7 @@ ieee80211_add_tdma(uint8_t *frm, struct 
 		.tdma_subtype	= TDMA_SUBTYPE_PARAM,
 		.tdma_version	= TDMA_VERSION,
 	};
-	const struct ieee80211_tdma_state *tdma = vap->iv_tdma;
+	const struct ieee80211_tdma_state *ts = vap->iv_tdma;
 	uint16_t slotlen;
 
 	KASSERT(vap->iv_caps & IEEE80211_C_TDMA,
@@ -620,13 +653,13 @@ ieee80211_add_tdma(uint8_t *frm, struct 
 
 	memcpy(frm, &param, sizeof(param));
 	frm += __offsetof(struct ieee80211_tdma_param, tdma_slot);
-	*frm++ = tdma->tdma_slot;
-	*frm++ = tdma->tdma_slotcnt;
+	*frm++ = ts->tdma_slot;
+	*frm++ = ts->tdma_slotcnt;
 	/* NB: convert units to fit in 16-bits */
-	slotlen = tdma->tdma_slotlen / 100;	/* 100us units */
+	slotlen = ts->tdma_slotlen / 100;	/* 100us units */
 	ADDSHORT(frm, slotlen);
-	*frm++ = tdma->tdma_bintval;
-	*frm++ = tdma->tdma_inuse[0];
+	*frm++ = ts->tdma_bintval;
+	*frm++ = ts->tdma_inuse[0];
 	frm += 10;				/* pad+timestamp */
 	return frm; 
 #undef ADDSHORT
@@ -717,8 +750,7 @@ ieee80211_tdma_ioctl_set80211(struct iee
 		}
 		break;
 	case IEEE80211_IOC_TDMA_SLOTCNT:
-		if (!(2 <= ireq->i_val &&
-		      ireq->i_val <= IEEE80211_TDMA_MAXSLOTS))
+		if (!TDMA_SLOTCNT_VALID(ireq->i_val))
 			return EINVAL;
 		if (ireq->i_val != ts->tdma_slotcnt) {
 			ts->tdma_slotcnt = ireq->i_val;
@@ -732,7 +764,7 @@ ieee80211_tdma_ioctl_set80211(struct iee
 		 * 0xfffff is the max duration for bursting
 		 * (implict by way of 16-bit data type for i_val)
 		 */
-		if (ireq->i_val < 150)
+		if (!TDMA_SLOTLEN_VALID(ireq->i_val))
 			return EINVAL;
 		if (ireq->i_val != ts->tdma_slotlen) {
 			ts->tdma_slotlen = ireq->i_val;
@@ -740,7 +772,7 @@ ieee80211_tdma_ioctl_set80211(struct iee
 		}
 		break;
 	case IEEE80211_IOC_TDMA_BINTERVAL:
-		if (ireq->i_val < 1)
+		if (!TDMA_BINTVAL_VALID(ireq->i_val))
 			return EINVAL;
 		if (ireq->i_val != ts->tdma_bintval) {
 			ts->tdma_bintval = ireq->i_val;

Modified: head/sys/net80211/ieee80211_tdma.h
==============================================================================
--- head/sys/net80211/ieee80211_tdma.h	Wed Mar 18 18:46:50 2009	(r189979)
+++ head/sys/net80211/ieee80211_tdma.h	Wed Mar 18 19:28:17 2009	(r189980)
@@ -33,11 +33,11 @@
  */
 struct ieee80211_tdma_state {
 	u_int	tdma_slotlen;		/* bss slot length (us) */
+	uint8_t	tdma_version;		/* protocol version to use */
 	uint8_t	tdma_slotcnt;		/* bss slot count */
 	uint8_t	tdma_bintval;		/* beacon interval (slots) */
 	uint8_t	tdma_slot;		/* station slot # */
 	uint8_t	tdma_inuse[1];		/* mask of slots in use */
-#define	IEEE80211_TDMA_MAXSLOTS	8
 	void	*tdma_peer;		/* peer station cookie */
 	uint8_t	tdma_active[1];		/* mask of active slots */
 	int	tdma_count;		/* active/inuse countdown */
@@ -49,6 +49,11 @@ struct ieee80211_tdma_state {
 		    struct mbuf *, int, int, int, uint32_t);
 	void	(*tdma_opdetach)(struct ieee80211vap *);
 };
+ 
+#define	TDMA_UPDATE_SLOT	0x0001	/* tdma_slot changed */
+#define	TDMA_UPDATE_SLOTCNT	0x0002	/* tdma_slotcnt changed */
+#define	TDMA_UPDATE_SLOTLEN	0x0004	/* tdma_slotlen changed */
+#define	TDMA_UPDATE_BINTVAL	0x0008	/* tdma_bintval changed */
 
 void	ieee80211_tdma_vattach(struct ieee80211vap *);
 

Modified: head/sys/net80211/ieee80211_var.h
==============================================================================
--- head/sys/net80211/ieee80211_var.h	Wed Mar 18 18:46:50 2009	(r189979)
+++ head/sys/net80211/ieee80211_var.h	Wed Mar 18 19:28:17 2009	(r189980)
@@ -229,7 +229,7 @@ struct ieee80211com {
 	void			(*ic_newassoc)(struct ieee80211_node *, int);
 	/* TDMA update notification */
 	void			(*ic_tdma_update)(struct ieee80211_node *,
-				    const struct ieee80211_tdma_param *);
+				    const struct ieee80211_tdma_param *, int);
 	/* node state management */
 	struct ieee80211_node*	(*ic_node_alloc)(struct ieee80211vap *,
 				    const uint8_t [IEEE80211_ADDR_LEN]);


More information about the svn-src-head mailing list