diff options
-rw-r--r-- | sys/net80211/ieee80211.c | 182 | ||||
-rw-r--r-- | sys/net80211/ieee80211_node.h | 4 | ||||
-rw-r--r-- | sys/net80211/ieee80211_proto.c | 35 | ||||
-rw-r--r-- | sys/net80211/ieee80211_var.h | 7 |
4 files changed, 202 insertions, 26 deletions
diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c index 0355126b2cf..e67312c2ffa 100644 --- a/sys/net80211/ieee80211.c +++ b/sys/net80211/ieee80211.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee80211.c,v 1.49 2015/11/15 10:21:58 stsp Exp $ */ +/* $OpenBSD: ieee80211.c,v 1.50 2015/11/15 12:34:07 stsp Exp $ */ /* $NetBSD: ieee80211.c,v 1.19 2004/06/06 05:45:29 dyoung Exp $ */ /*- @@ -111,6 +111,10 @@ ieee80211_channel_init(struct ifnet *ifp) ic->ic_modecaps |= 1<<IEEE80211_MODE_11G; if (IEEE80211_IS_CHAN_T(c)) ic->ic_modecaps |= 1<<IEEE80211_MODE_TURBO; +#ifndef IEEE80211_NO_HT + if (IEEE80211_IS_CHAN_N(c)) + ic->ic_modecaps |= 1<<IEEE80211_MODE_11N; +#endif } } /* validate ic->ic_curmode */ @@ -351,6 +355,34 @@ ieee80211_media_init(struct ifnet *ifp, if (ic->ic_caps & IEEE80211_C_MONITOR) ADD(ic, mword, IFM_IEEE80211_MONITOR); } + +#ifndef IEEE80211_NO_HT + if (ic->ic_modecaps & (1 << IEEE80211_MODE_11N)) { + mopt = IFM_IEEE80211_11N; + ADD(ic, IFM_AUTO, mopt); +#ifndef IEEE80211_STA_ONLY + if (ic->ic_caps & IEEE80211_C_IBSS) + ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_IBSS); + if (ic->ic_caps & IEEE80211_C_HOSTAP) + ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_HOSTAP); +#endif + for (i = 0; i < IEEE80211_HT_NUM_MCS; i++) { + if (!isset(ic->ic_sup_mcs, i)) + continue; + ADD(ic, IFM_IEEE80211_HT_MCS0 + i, mopt); +#ifndef IEEE80211_STA_ONLY + if (ic->ic_caps & IEEE80211_C_IBSS) + ADD(ic, IFM_IEEE80211_HT_MCS0 + i, + mopt | IFM_IEEE80211_IBSS); + if (ic->ic_caps & IEEE80211_C_HOSTAP) + ADD(ic, IFM_IEEE80211_HT_MCS0 + i, + mopt | IFM_IEEE80211_HOSTAP); +#endif + } + ic->ic_flags |= IEEE80211_F_HTON; /* enable 11n by default */ + } +#endif /* IEEE80211_NO_HT */ + ieee80211_media_status(ifp, &imr); ifmedia_set(&ic->ic_media, imr.ifm_active); @@ -400,6 +432,11 @@ ieee80211_media_change(struct ifnet *ifp) case IFM_IEEE80211_11G: newphymode = IEEE80211_MODE_11G; break; +#ifndef IEEE80211_NO_HT + case IFM_IEEE80211_11N: + newphymode = IEEE80211_MODE_11N; + break; +#endif case IFM_AUTO: newphymode = IEEE80211_MODE_AUTO; break; @@ -425,7 +462,21 @@ ieee80211_media_change(struct ifnet *ifp) * Next, the fixed/variable rate. */ i = -1; - if (IFM_SUBTYPE(ime->ifm_media) != IFM_AUTO) { + if (IFM_SUBTYPE(ime->ifm_media) >= IFM_IEEE80211_HT_MCS0 && + IFM_SUBTYPE(ime->ifm_media) <= IFM_IEEE80211_HT_MCS76) { +#ifndef IEEE80211_NO_HT + if ((ic->ic_modecaps & (1 << IEEE80211_MODE_11N)) == 0) + return EINVAL; + if (newphymode != IEEE80211_MODE_AUTO || + newphymode != IEEE80211_MODE_11N) + return EINVAL; + i = ieee80211_media2mcs(ime->ifm_media); + if (i == -1 || isclr(ic->ic_sup_mcs, i)) + return EINVAL; +#else + return EINVAL; +#endif + } else if (IFM_SUBTYPE(ime->ifm_media) != IFM_AUTO) { /* * Convert media subtype to rate. */ @@ -484,11 +535,17 @@ ieee80211_media_change(struct ifnet *ifp) */ if (newopmode == IEEE80211_M_HOSTAP && newphymode == IEEE80211_MODE_AUTO) { - for (j = IEEE80211_MODE_11A; j < IEEE80211_MODE_MAX; j++) - if (ic->ic_modecaps & (1<<j)) { - newphymode = j; - break; - } +#ifndef IEEE80211_NO_HT + if (ic->ic_modecaps & (1 << IEEE80211_MODE_11N)) + newphymode = IEEE80211_MODE_11N; + else +#endif + if (ic->ic_modecaps & (1 << IEEE80211_MODE_11A)) + newphymode = IEEE80211_MODE_11A; + else if (ic->ic_modecaps & (1 << IEEE80211_MODE_11G)) + newphymode = IEEE80211_MODE_11G; + else + newphymode = IEEE80211_MODE_11B; } #endif @@ -503,12 +560,33 @@ ieee80211_media_change(struct ifnet *ifp) } /* - * Committed to changes, install the rate setting. + * Committed to changes, install the MCS/rate setting. */ - if (ic->ic_fixed_rate != i) { - ic->ic_fixed_rate = i; /* set fixed tx rate */ - error = ENETRESET; + ic->ic_flags &= ~IEEE80211_F_HTON; +#ifndef IEEE80211_NO_HT + if ((ic->ic_modecaps & (1 << IEEE80211_MODE_11N)) && + (newphymode == IEEE80211_MODE_AUTO || + newphymode == IEEE80211_MODE_11N)) + ic->ic_flags |= IEEE80211_F_HTON; +#endif + if ((ic->ic_flags & IEEE80211_F_HTON) == 0) { +#ifndef IEEE80211_NO_HT + ic->ic_fixed_mcs = -1; +#endif + if (ic->ic_fixed_rate != i) { + ic->ic_fixed_rate = i; /* set fixed tx rate */ + error = ENETRESET; + } + } +#ifndef IEEE80211_NO_HT + else { + ic->ic_fixed_rate = -1; + if (ic->ic_fixed_mcs != i) { + ic->ic_fixed_mcs = i; /* set fixed mcs */ + error = ENETRESET; + } } +#endif /* * Handle operating mode change. @@ -560,9 +638,16 @@ ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr) switch (ic->ic_opmode) { case IEEE80211_M_STA: ni = ic->ic_bss; - /* calculate rate subtype */ - imr->ifm_active |= ieee80211_rate2media(ic, - ni->ni_rates.rs_rates[ni->ni_txrate], ic->ic_curmode); +#ifndef IEEE80211_NO_HT + if (ic->ic_curmode == IEEE80211_MODE_11N) + imr->ifm_active |= ieee80211_mcs2media(ic, + ni->ni_txmcs, ic->ic_curmode); + else +#endif + /* calculate rate subtype */ + imr->ifm_active |= ieee80211_rate2media(ic, + ni->ni_rates.rs_rates[ni->ni_txrate], + ic->ic_curmode); break; #ifndef IEEE80211_STA_ONLY case IEEE80211_M_IBSS: @@ -595,6 +680,11 @@ ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr) imr->ifm_active |= IFM_IEEE80211_11A | IFM_IEEE80211_TURBO; break; +#ifndef IEEE80211_NO_HT + case IEEE80211_MODE_11N: + imr->ifm_active |= IFM_IEEE80211_11N; + break; +#endif } } @@ -672,6 +762,9 @@ ieee80211_setmode(struct ieee80211com *ic, enum ieee80211_phymode mode) IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */ IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_11G */ IEEE80211_CHAN_T, /* IEEE80211_MODE_TURBO */ +#ifndef IEEE80211_NO_HT + IEEE80211_CHAN_HT, /* IEEE80211_MODE_11N */ +#endif }; const struct ieee80211_channel *c; u_int modeflags; @@ -771,10 +864,12 @@ ieee80211_next_mode(struct ifnet *ifp) * Get the next supported mode */ for (++ic->ic_curmode; - ic->ic_curmode <= IEEE80211_MODE_TURBO; + ic->ic_curmode <= IEEE80211_MODE_MAX; ic->ic_curmode++) { /* Wrap around and ignore turbo mode */ - if (ic->ic_curmode >= IEEE80211_MODE_TURBO) { + if (ic->ic_curmode == IEEE80211_MODE_TURBO) + continue; + if (ic->ic_curmode >= IEEE80211_MODE_MAX) { ic->ic_curmode = IEEE80211_MODE_AUTO; break; } @@ -811,6 +906,11 @@ ieee80211_chan2mode(struct ieee80211com *ic, * characteristics. We assume that turbo-only channels * are not considered when the channel set is constructed. */ +#ifndef IEEE80211_NO_HT + if (IEEE80211_IS_CHAN_N(chan)) + return IEEE80211_MODE_11N; + else +#endif if (IEEE80211_IS_CHAN_T(chan)) return IEEE80211_MODE_TURBO; else if (IEEE80211_IS_CHAN_5GHZ(chan)) @@ -821,6 +921,56 @@ ieee80211_chan2mode(struct ieee80211com *ic, return IEEE80211_MODE_11B; } +#ifndef IEEE80211_NO_HT +/* + * Convert IEEE80211 MCS index to ifmedia subtype. + */ +uint64_t +ieee80211_mcs2media(struct ieee80211com *ic, int mcs, + enum ieee80211_phymode mode) +{ + switch (mode) { + case IEEE80211_MODE_11A: + case IEEE80211_MODE_TURBO: + case IEEE80211_MODE_11B: + case IEEE80211_MODE_11G: + /* these modes use rates, not MCS */ + panic("unexpected mode %d", mode); + break; + case IEEE80211_MODE_AUTO: + case IEEE80211_MODE_11N: + if (mcs >= 0 && mcs < IEEE80211_HT_NUM_MCS) + return (IFM_IEEE80211_11N | + (IFM_IEEE80211_HT_MCS0 + mcs)); + break; + } + + return IFM_AUTO; +} + +/* + * Convert ifmedia subtype to IEEE80211 MCS index. + */ +int +ieee80211_media2mcs(uint64_t mword) +{ + uint64_t subtype; + + subtype = IFM_SUBTYPE(mword); + + if (subtype == IFM_AUTO) + return -1; + else if (subtype == IFM_MANUAL || subtype == IFM_NONE) + return 0; + + if (subtype >= IFM_IEEE80211_HT_MCS0 && + subtype <= IFM_IEEE80211_HT_MCS76) + return (int)(subtype - IFM_IEEE80211_HT_MCS0); + + return -1; +} +#endif /* IEEE80211_NO_HT */ + /* * convert IEEE80211 rate value to ifmedia subtype. * ieee80211 rate is in unit of 0.5Mbps. diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h index 0f27250066e..59f17633cc4 100644 --- a/sys/net80211/ieee80211_node.h +++ b/sys/net80211/ieee80211_node.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee80211_node.h,v 1.48 2015/11/15 10:07:03 stsp Exp $ */ +/* $OpenBSD: ieee80211_node.h,v 1.49 2015/11/15 12:34:07 stsp Exp $ */ /* $NetBSD: ieee80211_node.h,v 1.9 2004/04/30 22:57:32 dyoung Exp $ */ /*- @@ -241,6 +241,8 @@ struct ieee80211_node { /* Block Ack records */ struct ieee80211_tx_ba ni_tx_ba[IEEE80211_NUM_TID]; struct ieee80211_rx_ba ni_rx_ba[IEEE80211_NUM_TID]; + + int ni_txmcs; /* current MCS used for TX */ #endif /* others */ diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c index 411a7632630..9f1d6ebbf9e 100644 --- a/sys/net80211/ieee80211_proto.c +++ b/sys/net80211/ieee80211_proto.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee80211_proto.c,v 1.54 2015/11/15 11:14:17 stsp Exp $ */ +/* $OpenBSD: ieee80211_proto.c,v 1.55 2015/11/15 12:34:07 stsp Exp $ */ /* $NetBSD: ieee80211_proto.c,v 1.8 2004/04/30 23:58:20 dyoung Exp $ */ /*- @@ -75,6 +75,7 @@ const char * const ieee80211_phymode_name[] = { "11b", /* IEEE80211_MODE_11B */ "11g", /* IEEE80211_MODE_11G */ "turbo", /* IEEE80211_MODE_TURBO */ + "11n", /* IEEE80211_MODE_11N */ }; int ieee80211_newstate(struct ieee80211com *, enum ieee80211_state, int); @@ -96,6 +97,9 @@ ieee80211_proto_attach(struct ifnet *ifp) #endif ic->ic_fragthreshold = 2346; /* XXX not used yet */ ic->ic_fixed_rate = -1; /* no fixed rate */ +#ifndef IEEE80211_NO_HT + ic->ic_fixed_mcs = -1; /* no fixed mcs */ +#endif ic->ic_protmode = IEEE80211_PROT_CTSONLY; /* protocol state change handler */ @@ -891,8 +895,15 @@ justcleanup: /* initialize bss for probe request */ IEEE80211_ADDR_COPY(ni->ni_macaddr, etherbroadcastaddr); IEEE80211_ADDR_COPY(ni->ni_bssid, etherbroadcastaddr); - ni->ni_rates = ic->ic_sup_rates[ - ieee80211_chan2mode(ic, ni->ni_chan)]; +#ifndef IEEE80211_NO_HT + if (ic->ic_curmode == IEEE80211_MODE_11N) + ni->ni_rates = ic->ic_sup_rates[ + IEEE80211_IS_CHAN_2GHZ(ni->ni_chan) ? + IEEE80211_MODE_11G : IEEE80211_MODE_11A]; + else +#endif + ni->ni_rates = ic->ic_sup_rates[ + ieee80211_chan2mode(ic, ni->ni_chan)]; ni->ni_associd = 0; ni->ni_rstamp = 0; switch (ostate) { @@ -1013,16 +1024,24 @@ justcleanup: ni->ni_esslen); rate = ni->ni_rates.rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL; - printf(" channel %d start %u%sMb", - ieee80211_chan2ieee(ic, ni->ni_chan), - rate / 2, (rate & 1) ? ".5" : ""); - printf(" %s preamble %s slot time%s\n", + printf(" channel %d", + ieee80211_chan2ieee(ic, ni->ni_chan)); +#ifndef IEEE80211_NO_HT + if (ni->ni_flags & IEEE80211_NODE_HT) + printf(" start MCS %u", ni->ni_txmcs); + else +#endif + printf(" start %u%sMb", + rate / 2, (rate & 1) ? ".5" : ""); + printf(" %s preamble %s slot time%s%s\n", (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ? "short" : "long", (ic->ic_flags & IEEE80211_F_SHSLOT) ? "short" : "long", (ic->ic_flags & IEEE80211_F_USEPROT) ? - " protection enabled" : ""); + " protection enabled" : "", + (ni->ni_flags & IEEE80211_NODE_HT) ? + " HT enabled" : ""); } if (!(ic->ic_flags & IEEE80211_F_RSNON)) { /* diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index eceffc80841..b2a1193060c 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee80211_var.h,v 1.66 2015/11/15 01:05:25 stsp Exp $ */ +/* $OpenBSD: ieee80211_var.h,v 1.67 2015/11/15 12:34:07 stsp Exp $ */ /* $NetBSD: ieee80211_var.h,v 1.7 2004/05/06 03:07:10 dyoung Exp $ */ /*- @@ -400,6 +400,11 @@ int ieee80211_fix_rate(struct ieee80211com *, struct ieee80211_node *, int); uint64_t ieee80211_rate2media(struct ieee80211com *, int, enum ieee80211_phymode); int ieee80211_media2rate(uint64_t); +#ifndef IEEE80211_NO_HT +uint64_t ieee80211_mcs2media(struct ieee80211com *, int, + enum ieee80211_phymode); +int ieee80211_media2mcs(uint64_t); +#endif u_int8_t ieee80211_rate2plcp(u_int8_t, enum ieee80211_phymode); u_int8_t ieee80211_plcp2rate(u_int8_t, enum ieee80211_phymode); u_int ieee80211_mhz2ieee(u_int, u_int); |