From owner-p4-projects@FreeBSD.ORG Sat Aug 23 01:15:51 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id AF7BE1065678; Sat, 23 Aug 2008 01:15:50 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 738B91065676 for ; Sat, 23 Aug 2008 01:15:50 +0000 (UTC) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 612258FC12 for ; Sat, 23 Aug 2008 01:15:50 +0000 (UTC) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.2/8.14.2) with ESMTP id m7N1Fo0C092983 for ; Sat, 23 Aug 2008 01:15:50 GMT (envelope-from sam@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.2/8.14.1/Submit) id m7N1Fopw092981 for perforce@freebsd.org; Sat, 23 Aug 2008 01:15:50 GMT (envelope-from sam@freebsd.org) Date: Sat, 23 Aug 2008 01:15:50 GMT Message-Id: <200808230115.m7N1Fopw092981@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to sam@freebsd.org using -f From: Sam Leffler To: Perforce Change Reviews Cc: Subject: PERFORCE change 148145 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 23 Aug 2008 01:15:51 -0000 http://perforce.freebsd.org/chv.cgi?CH=148145 Change 148145 by sam@sam_ebb on 2008/08/23 01:15:17 Revamp ht ie handling a bit: o change ieee80211_parse_htcap and ieee80211_parse_htinfo to save only internal state obtained from the ie's; no dynamic state such as ni_chw is altered o add ieee80211_ht_updateparams to parse ht cap+info ie's and update dynamic node state o change ieee80211_ht_node_init to not take an htcap ie that is parsed; instead have the caller make a separate call as one caller wants to parse the ie while another wants to parse both cap+info ie's and update state so can better do this with ieee80211_ht_updateparams These changes fix sta mode state handling where the node's channel width was shifted to ht20/ht40 prematurely. Affected files ... .. //depot/projects/vap/sys/net80211/ieee80211_hostap.c#23 edit .. //depot/projects/vap/sys/net80211/ieee80211_ht.c#37 edit .. //depot/projects/vap/sys/net80211/ieee80211_ht.h#18 edit .. //depot/projects/vap/sys/net80211/ieee80211_sta.c#13 edit Differences ... ==== //depot/projects/vap/sys/net80211/ieee80211_hostap.c#23 (text+ko) ==== @@ -2038,7 +2038,8 @@ vap->iv_stats.is_ht_assoc_norate++; return; } - ieee80211_ht_node_init(ni, htcap); + ieee80211_ht_node_init(ni); + ieee80211_parse_htcap(ni, htcap); } else if (ni->ni_flags & IEEE80211_NODE_HT) ieee80211_ht_node_cleanup(ni); /* ==== //depot/projects/vap/sys/net80211/ieee80211_ht.c#37 (text+ko) ==== @@ -782,7 +782,7 @@ * work for temporary and/or legacy sta's. */ void -ieee80211_ht_node_init(struct ieee80211_node *ni, const uint8_t *htcap) +ieee80211_ht_node_init(struct ieee80211_node *ni) { struct ieee80211_tx_ampdu *tap; int ac; @@ -795,7 +795,6 @@ */ ieee80211_ht_node_cleanup(ni); } - ieee80211_parse_htcap(ni, htcap); for (ac = 0; ac < WME_NUM_AC; ac++) { tap = &ni->ni_tx_ampdu[ac]; tap->txa_ac = ac; @@ -1144,8 +1143,6 @@ void ieee80211_parse_htcap(struct ieee80211_node *ni, const uint8_t *ie) { - struct ieee80211vap *vap = ni->ni_vap; - if (ie[0] == IEEE80211_ELEMID_VENDOR) { /* * Station used Vendor OUI ie to associate; @@ -1160,43 +1157,53 @@ ni->ni_htcap = LE_READ_2(ie + __offsetof(struct ieee80211_ie_htcap, hc_cap)); ni->ni_htparam = ie[__offsetof(struct ieee80211_ie_htcap, hc_param)]; - /* XXX needed or will ieee80211_parse_htinfo always be called? */ - ni->ni_chw = (ni->ni_htcap & IEEE80211_HTCAP_CHWIDTH40) && - (vap->iv_flags_ext & IEEE80211_FEXT_USEHT40) ? 40 : 20; +} + +static void +htinfo_parse(struct ieee80211_node *ni, + const struct ieee80211_ie_htinfo *htinfo) +{ + uint16_t w; + + ni->ni_htctlchan = htinfo->hi_ctrlchannel; + ni->ni_ht2ndchan = SM(htinfo->hi_byte1, IEEE80211_HTINFO_2NDCHAN); + w = LE_READ_2(&htinfo->hi_byte2); + ni->ni_htopmode = SM(w, IEEE80211_HTINFO_OPMODE); + w = LE_READ_2(&htinfo->hi_byte45); + ni->ni_htstbc = SM(w, IEEE80211_HTINFO_BASIC_STBCMCS); } /* - * Process an 802.11n HT info ie and update the node state. - * Note that we handle use this information to identify the - * correct channel (HT20, HT40+, HT40-, legacy). The caller - * is responsible for insuring any required channel change is - * done (e.g. in sta mode when parsing the contents of a - * beacon frame). + * Parse an 802.11n HT info ie and save useful information + * to the node state. Note this does not effect any state + * changes such as for channel width change. */ void ieee80211_parse_htinfo(struct ieee80211_node *ni, const uint8_t *ie) { + if (ie[0] == IEEE80211_ELEMID_VENDOR) + ie += 4; + htinfo_parse(ni, (const struct ieee80211_ie_htinfo *) ie); +} + +/* + * Handle 11n channel switch. Use the received HT ie's to + * identify the right channel to use. If we cannot locate it + * in the channel table then fallback to legacy operation. + * Note that we use this information to identify the node's + * channel only; the caller is responsible for insuring any + * required channel change is done (e.g. in sta mode when + * parsing the contents of a beacon frame). + */ +static void +htinfo_update_chw(struct ieee80211_node *ni, + const struct ieee80211_ie_htinfo *htinfo) +{ struct ieee80211com *ic = ni->ni_ic; struct ieee80211vap *vap = ni->ni_vap; - const struct ieee80211_ie_htinfo *htinfo; struct ieee80211_channel *c; - uint16_t w; int htflags, chanflags; - if (ie[0] == IEEE80211_ELEMID_VENDOR) - ie += 4; - htinfo = (const struct ieee80211_ie_htinfo *) ie; - ni->ni_htctlchan = htinfo->hi_ctrlchannel; - ni->ni_ht2ndchan = SM(htinfo->hi_byte1, IEEE80211_HTINFO_2NDCHAN); - w = LE_READ_2(&htinfo->hi_byte2); - ni->ni_htopmode = SM(w, IEEE80211_HTINFO_OPMODE); - w = LE_READ_2(&htinfo->hi_byte45); - ni->ni_htstbc = SM(w, IEEE80211_HTINFO_BASIC_STBCMCS); - /* - * Handle 11n channel switch. Use the received HT ie's to - * identify the right channel to use. If we cannot locate it - * in the channel table then fallback to legacy operation. - */ /* NB: honor operating mode constraint */ htflags = (vap->iv_flags_ext & IEEE80211_FEXT_HT) ? IEEE80211_CHAN_HT20 : 0; @@ -1209,6 +1216,7 @@ } chanflags = (ni->ni_chan->ic_flags &~ IEEE80211_CHAN_HT) | htflags; if (chanflags != ni->ni_chan->ic_flags) { + /* XXX not right for ht40- */ c = ieee80211_find_channel(ic, ni->ni_chan->ic_freq, chanflags); if (c == NULL && (htflags & IEEE80211_CHAN_HT40)) { /* @@ -1216,10 +1224,12 @@ * to HT20 operation. This should not happen. */ c = findhtchan(ic, ni->ni_chan, IEEE80211_CHAN_HT20); +#if 0 IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC | IEEE80211_MSG_11N, ni, "no HT40 channel (freq %u), falling back to HT20", ni->ni_chan->ic_freq); +#endif /* XXX stat */ } if (c != NULL && c != ni->ni_chan) { @@ -1237,6 +1247,21 @@ } /* + * Parse and update HT-related state extracted from + * the HT cap and info ie's. + */ +void +ieee80211_ht_updateparams(struct ieee80211_node *ni, + const uint8_t *htcapie, const uint8_t *htinfoie) +{ + ieee80211_parse_htcap(ni, htcapie); + if (htinfoie[0] == IEEE80211_ELEMID_VENDOR) + htinfoie += 4; + htinfo_parse(ni, (const struct ieee80211_ie_htinfo *) htinfoie); + htinfo_update_chw(ni, (const struct ieee80211_ie_htinfo *) htinfoie); +} + +/* * Install received HT rate set by parsing the HT cap ie. */ int ==== //depot/projects/vap/sys/net80211/ieee80211_ht.h#18 (text+ko) ==== @@ -165,7 +165,7 @@ struct mbuf *ieee80211_decap_amsdu(struct ieee80211_node *, struct mbuf *); int ieee80211_ampdu_reorder(struct ieee80211_node *, struct mbuf *); void ieee80211_recv_bar(struct ieee80211_node *, struct mbuf *); -void ieee80211_ht_node_init(struct ieee80211_node *, const uint8_t *); +void ieee80211_ht_node_init(struct ieee80211_node *); void ieee80211_ht_node_cleanup(struct ieee80211_node *); void ieee80211_ht_node_age(struct ieee80211_node *); @@ -178,6 +178,8 @@ void ieee80211_ht_timeout(struct ieee80211com *); void ieee80211_parse_htcap(struct ieee80211_node *, const uint8_t *); void ieee80211_parse_htinfo(struct ieee80211_node *, const uint8_t *); +void ieee80211_ht_updateparams(struct ieee80211_node *, const uint8_t *, + const uint8_t *); void ieee80211_recv_action(struct ieee80211_node *, const uint8_t *, const uint8_t *); int ieee80211_ampdu_request(struct ieee80211_node *, ==== //depot/projects/vap/sys/net80211/ieee80211_sta.c#13 (text+ko) ==== @@ -1269,8 +1269,8 @@ if (scan.ath != NULL) ieee80211_parse_athparams(ni, scan.ath, wh); if (scan.htcap != NULL && scan.htinfo != NULL) { - ieee80211_parse_htcap(ni, scan.htcap); - ieee80211_parse_htinfo(ni, scan.htinfo); + ieee80211_ht_updateparams(ni, + scan.htcap, scan.htinfo); /* XXX state changes? */ } if (scan.tim != NULL) { @@ -1503,8 +1503,8 @@ */ if (htcap != NULL && htinfo != NULL && (vap->iv_flags_ext & IEEE80211_FEXT_HT)) { - ieee80211_ht_node_init(ni, htcap); - ieee80211_parse_htinfo(ni, htinfo); + ieee80211_ht_node_init(ni); + ieee80211_ht_updateparams(ni, htcap, htinfo); ieee80211_setup_htrates(ni, htcap, IEEE80211_F_JOIN | IEEE80211_F_DOBRS); ieee80211_setup_basic_htrates(ni, htinfo);