Date: Wed, 18 Mar 2009 19:28:17 +0000 (UTC) From: Sam Leffler <sam@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r189980 - in head/sys: dev/ath net80211 Message-ID: <200903181928.n2IJSHHm035494@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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, ¶m, 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]);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200903181928.n2IJSHHm035494>