diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c --- a/sys/net80211/ieee80211.c +++ b/sys/net80211/ieee80211.c @@ -1949,6 +1949,7 @@ enum ieee80211_phymode mode; const struct ieee80211_rateset *rs; struct ieee80211_rateset allrates; + struct ieee80211_node_txrate tn; /* * Fill in media characteristics. @@ -1968,7 +1969,8 @@ rs = &ic->ic_sup_rates[mode]; for (i = 0; i < rs->rs_nrates; i++) { rate = rs->rs_rates[i]; - mword = ieee80211_rate2media(ic, rate, mode); + tn = IEEE80211_NODE_TXRATE_INIT_LEGACY(rate); + mword = ieee80211_rate2media(ic, &tn, mode); if (mword == 0) continue; addmedia(media, caps, addsta, mode, mword); @@ -1990,8 +1992,8 @@ } } for (i = 0; i < allrates.rs_nrates; i++) { - mword = ieee80211_rate2media(ic, allrates.rs_rates[i], - IEEE80211_MODE_AUTO); + tn = IEEE80211_NODE_TXRATE_INIT_LEGACY(allrates.rs_rates[i]); + mword = ieee80211_rate2media(ic, &tn, IEEE80211_MODE_AUTO); if (mword == 0) continue; /* NB: remove media options from mword */ @@ -2071,6 +2073,7 @@ int i, rate, mword; enum ieee80211_phymode mode; const struct ieee80211_rateset *rs; + struct ieee80211_node_txrate tn; /* NB: skip AUTO since it has no rates */ for (mode = IEEE80211_MODE_AUTO+1; mode < IEEE80211_MODE_11NA; mode++) { @@ -2079,7 +2082,8 @@ ic_printf(ic, "%s rates: ", ieee80211_phymode_name[mode]); rs = &ic->ic_sup_rates[mode]; for (i = 0; i < rs->rs_nrates; i++) { - mword = ieee80211_rate2media(ic, rs->rs_rates[i], mode); + tn = IEEE80211_NODE_TXRATE_INIT_LEGACY(rs->rs_rates[i]); + mword = ieee80211_rate2media(ic, &tn, mode); if (mword == 0) continue; rate = ieee80211_media2rate(mword); @@ -2278,6 +2282,7 @@ struct ieee80211vap *vap = ifp->if_softc; struct ieee80211com *ic = vap->iv_ic; enum ieee80211_phymode mode; + struct ieee80211_node_txrate tn; imr->ifm_status = IFM_AVALID; /* @@ -2299,14 +2304,15 @@ /* * A fixed rate is set, report that. */ - imr->ifm_active |= ieee80211_rate2media(ic, - vap->iv_txparms[mode].ucastrate, mode); + tn = IEEE80211_NODE_TXRATE_INIT_LEGACY( + vap->iv_txparms[mode].ucastrate); + imr->ifm_active |= ieee80211_rate2media(ic, &tn, mode); } else if (vap->iv_opmode == IEEE80211_M_STA) { /* * In station mode report the current transmit rate. */ - imr->ifm_active |= ieee80211_rate2media(ic, - ieee80211_node_get_txrate_dot11rate(vap->iv_bss), mode); + ieee80211_node_get_txrate(vap->iv_bss, &tn); + imr->ifm_active |= ieee80211_rate2media(ic, &tn, mode); } else imr->ifm_active |= IFM_AUTO; if (imr->ifm_status & IFM_ACTIVE) @@ -2399,7 +2405,8 @@ * or an MCS index. */ int -ieee80211_rate2media(struct ieee80211com *ic, int rate, enum ieee80211_phymode mode) +ieee80211_rate2media(struct ieee80211com *ic, + const struct ieee80211_node_txrate *tr, enum ieee80211_phymode mode) { static const struct ratemedia rates[] = { { 2 | IFM_IEEE80211_FH, IFM_IEEE80211_FH1 }, @@ -2536,29 +2543,39 @@ * Check 11ac/11n rates first for match as an MCS. */ if (mode == IEEE80211_MODE_VHT_5GHZ) { - if (rate & IFM_IEEE80211_VHT) { - rate &= ~IFM_IEEE80211_VHT; - m = findmedia(vhtrates, nitems(vhtrates), rate); + if (tr->type == IEEE80211_NODE_TXRATE_VHT) { + m = findmedia(vhtrates, nitems(vhtrates), tr->mcs); if (m != IFM_AUTO) return (m | IFM_IEEE80211_VHT); } } else if (mode == IEEE80211_MODE_11NA) { - if (rate & IEEE80211_RATE_MCS) { - rate &= ~IEEE80211_RATE_MCS; - m = findmedia(htrates, nitems(htrates), rate); + /* NB: 12 is ambiguous, it will be treated as an MCS */ + if ((tr->type == IEEE80211_NODE_TXRATE_LEGACY) && + (tr->dot11rate & IEEE80211_RATE_MCS)) { + m = findmedia(htrates, nitems(htrates), + tr->dot11rate & ~IEEE80211_RATE_MCS); if (m != IFM_AUTO) return m | IFM_IEEE80211_11NA; } } else if (mode == IEEE80211_MODE_11NG) { /* NB: 12 is ambiguous, it will be treated as an MCS */ - if (rate & IEEE80211_RATE_MCS) { - rate &= ~IEEE80211_RATE_MCS; - m = findmedia(htrates, nitems(htrates), rate); + if ((tr->type == IEEE80211_NODE_TXRATE_LEGACY) && + (tr->dot11rate & IEEE80211_RATE_MCS)) { + m = findmedia(htrates, nitems(htrates), + tr->dot11rate & ~IEEE80211_RATE_MCS); if (m != IFM_AUTO) return m | IFM_IEEE80211_11NG; } } - rate &= IEEE80211_RATE_VAL; + + /* + * At this point it needs to be a dot11rate (legacy) for the + * rest of the logic to work. + */ + if (tr->type != IEEE80211_NODE_TXRATE_LEGACY) + return (IFM_AUTO); + int rate = tr->dot11rate & IEEE80211_RATE_VAL; + switch (mode) { case IEEE80211_MODE_11A: case IEEE80211_MODE_HALF: /* XXX good 'nuf */ @@ -2716,3 +2733,4 @@ */ return (!ieee80211_is_key_global(vap, key)); } + diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c --- a/sys/net80211/ieee80211_ht.c +++ b/sys/net80211/ieee80211_ht.c @@ -317,9 +317,12 @@ ht_getrate(struct ieee80211com *ic, int index, enum ieee80211_phymode mode, int ratetype) { + struct ieee80211_node_txrate tr; int mword, rate; - mword = ieee80211_rate2media(ic, index | IEEE80211_RATE_MCS, mode); + tr = IEEE80211_NODE_TXRATE_INIT_HT(index); + + mword = ieee80211_rate2media(ic, &tr, mode); if (IFM_SUBTYPE(mword) != IFM_IEEE80211_MCS) return (0); switch (ratetype) { diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -790,7 +790,8 @@ int ieee80211_media_change(struct ifnet *); void ieee80211_media_status(struct ifnet *, struct ifmediareq *); int ieee80211_ioctl(struct ifnet *, u_long, caddr_t); -int ieee80211_rate2media(struct ieee80211com *, int, +int ieee80211_rate2media(struct ieee80211com *, + const struct ieee80211_node_txrate *, enum ieee80211_phymode); int ieee80211_media2rate(int); int ieee80211_mhz2ieee(u_int, u_int);