diff --git a/sys/net80211/ieee80211_ddb.c b/sys/net80211/ieee80211_ddb.c --- a/sys/net80211/ieee80211_ddb.c +++ b/sys/net80211/ieee80211_ddb.c @@ -306,8 +306,9 @@ if (ni->ni_rx_ampdu[i].rxa_flags) _db_show_rxampdu("\t", i, &ni->ni_rx_ampdu[i]); - db_printf("\tinact %u inact_reload %u txrate %u\n", - ni->ni_inact, ni->ni_inact_reload, ni->ni_txrate); + db_printf("\tinact %u inact_reload %u txrate type %d rate %u\n", + ni->ni_inact, ni->ni_inact_reload, ni->ni_txrate.type, + ni->ni_txrate.dot11rate); #ifdef IEEE80211_SUPPORT_MESH _db_show_ssid("\tmeshid ", 0, ni->ni_meshidlen, ni->ni_meshid); db_printf(" mlstate %b mllid 0x%x mlpid 0x%x mlrcnt %u mltval %u\n", diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h --- a/sys/net80211/ieee80211_node.h +++ b/sys/net80211/ieee80211_node.h @@ -139,6 +139,16 @@ } } +#define IEEE80211_NODE_TXRATE_LEGACY 0x1 +#define IEEE80211_NODE_TXRATE_VHT 0x2 + +struct ieee80211_node_txrate { + uint8_t type; /* IEEE80211_NODE_TXRATE_* */ + uint8_t nss; /* VHT - number of spatial streams */ + uint8_t mcs; /* VHT - MCS */ + uint8_t dot11rate; /* Legacy/HT - dot11rate / ratecode */ +}; + /* * Node specific information. Note that drivers are expected * to derive from this structure to add device-specific per-node @@ -275,7 +285,7 @@ /* others */ short ni_inact; /* inactivity mark count */ short ni_inact_reload;/* inactivity reload value */ - int ni_txrate; /* legacy rate/MCS */ + struct ieee80211_node_txrate ni_txrate; /* current transmit rate */ struct ieee80211_psq ni_psq; /* power save queue */ struct ieee80211_nodestats ni_stats; /* per-node statistics */ @@ -499,6 +509,11 @@ int8_t ieee80211_getrssi(struct ieee80211vap *); void ieee80211_getsignal(struct ieee80211vap *, int8_t *, int8_t *); +/* + * Node transmit rate specific manipulation. + * + * This should eventually be refactored into its own type. + */ uint8_t ieee80211_node_get_txrate_dot11rate(struct ieee80211_node *); void ieee80211_node_set_txrate_dot11rate(struct ieee80211_node *, uint8_t); void ieee80211_node_set_txrate_ht_mcsrate(struct ieee80211_node *, uint8_t); diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c --- a/sys/net80211/ieee80211_node.c +++ b/sys/net80211/ieee80211_node.c @@ -2667,8 +2667,10 @@ ni->ni_esslen, ni->ni_essid, (ni->ni_chan != IEEE80211_CHAN_ANYC) ? ni->ni_chan->ic_freq : 0, (ni->ni_chan != IEEE80211_CHAN_ANYC) ? ni->ni_chan->ic_flags : 0); - printf("\tinact %u inact_reload %u txrate %u\n", - ni->ni_inact, ni->ni_inact_reload, ni->ni_txrate); + printf("\tinact %u inact_reload %u txrate type %d dot11rate %u\n", + ni->ni_inact, ni->ni_inact_reload, + ni->ni_txrate.type, + ni->ni_txrate.dot11rate); printf("\thtcap %x htparam %x htctlchan %u ht2ndchan %u\n", ni->ni_htcap, ni->ni_htparam, ni->ni_htctlchan, ni->ni_ht2ndchan); @@ -3138,27 +3140,73 @@ *rssi = ieee80211_getrssi(vap); } +/** + * @brief return a dot11rate / ratecode representing the current transmit rate + * + * This is the API call for legacy / 802.11n drivers and rate control APIs + * which expect a dot11rate / ratecode representation for legacy and HT MCS + * rates. + * + * Drivers which support VHT should not use this API, as it will log an error + * and return a low rate if a VHT rate is selected. + * + * @param ni the ieee80211_node to return the transmit rate for + * @returns the dot11rate / ratecode for legacy/MCS, or the + * lowest available dot11rate if it's VHT (and shouldn't + * have been called.) + */ uint8_t ieee80211_node_get_txrate_dot11rate(struct ieee80211_node *ni) { - - return (ni->ni_txrate); + switch (ni->ni_txrate.type) { + case IEEE80211_NODE_TXRATE_LEGACY: + return (ni->ni_txrate.dot11rate); + break; + case IEEE80211_NODE_TXRATE_VHT: + default: + printf("%s: called for VHT / unknown rate (type %d)!\n", + __func__, ni->ni_txrate.type); + return (12); /* OFDM6 for now */ + } } +/** + * @brief set the dot11rate / ratecode representing the current transmit rate + * + * This is the API call for legacy / 802.11n drivers and rate control APIs + * which expect a dot11rate / ratecode representation for legacy and HT MCS + * rates. + * + * @param ni the ieee80211_node to return the transmit rate for + * @param dot11rate the dot11rate rate code to use + */ void ieee80211_node_set_txrate_dot11rate(struct ieee80211_node *ni, uint8_t dot11Rate) { - - ni->ni_txrate = dot11Rate; + ni->ni_txrate.type = IEEE80211_NODE_TXRATE_LEGACY; + ni->ni_txrate.mcs = ni->ni_txrate.nss = 0; + ni->ni_txrate.dot11rate = dot11Rate; } +/** + * @brief set the dot11rate / ratecode representing the current HT transmit rate + * + * This is the API call for 802.11n drivers and rate control APIs + * which expect a dot11rate / ratecode representation for legacy and HT MCS + * rates. It expects an MCS rate code from 0 .. 76. + * + * @param ni the ieee80211_node to return the transmit rate for + * @param mcs the MCS rate to select + */ void ieee80211_node_set_txrate_ht_mcsrate(struct ieee80211_node *ni, uint8_t mcs) { - ni->ni_txrate = IEEE80211_RATE_MCS | mcs; + ni->ni_txrate.type = IEEE80211_NODE_TXRATE_LEGACY; + ni->ni_txrate.mcs = ni->ni_txrate.nss = 0; + ni->ni_txrate.dot11rate = IEEE80211_RATE_MCS | mcs; } @@ -3172,9 +3220,27 @@ { uint16_t mbps; - if (ni->ni_txrate & IEEE80211_RATE_MCS) { + /* + * TODO: only handle legacy/HT rates, VHT will need + * to use other logic. + */ + switch (ni->ni_txrate.type) { + case IEEE80211_NODE_TXRATE_LEGACY: + break; + case IEEE80211_NODE_TXRATE_VHT: + default: + printf("%s: called for VHT / unknown rate (type %d)!\n", + __func__, ni->ni_txrate.type); + return (0); + } + + + /* Legacy / MCS rates */ + + if (ni->ni_txrate.dot11rate & IEEE80211_RATE_MCS) { const struct ieee80211_mcs_rates *mcs = - &ieee80211_htrates[ni->ni_txrate &~ IEEE80211_RATE_MCS]; + &ieee80211_htrates[ni->ni_txrate.dot11rate &~ + IEEE80211_RATE_MCS]; if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) { if (ni->ni_flags & IEEE80211_NODE_SGI40) mbps = mcs->ht40_rate_800ns; @@ -3187,7 +3253,7 @@ mbps = mcs->ht20_rate_400ns; } } else - mbps = ni->ni_txrate; + mbps = ni->ni_txrate.dot11rate; return (mbps); }