Commit c8dcfd8a authored by Felix Fietkau's avatar Felix Fietkau Committed by John W. Linville

cfg80211: add a field for the bitrate of the last rx data packet from a station

Also fix a typo in the STATION_INFO_TX_BITRATE description
Signed-off-by: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent e7a2a4f5
...@@ -1243,6 +1243,8 @@ enum nl80211_rate_info { ...@@ -1243,6 +1243,8 @@ enum nl80211_rate_info {
* @NL80211_STA_INFO_LLID: the station's mesh LLID * @NL80211_STA_INFO_LLID: the station's mesh LLID
* @NL80211_STA_INFO_PLID: the station's mesh PLID * @NL80211_STA_INFO_PLID: the station's mesh PLID
* @NL80211_STA_INFO_PLINK_STATE: peer link state for the station * @NL80211_STA_INFO_PLINK_STATE: peer link state for the station
* @NL80211_STA_INFO_RX_BITRATE: last unicast data frame rx rate, nested
* attribute, like NL80211_STA_INFO_TX_BITRATE.
* @__NL80211_STA_INFO_AFTER_LAST: internal * @__NL80211_STA_INFO_AFTER_LAST: internal
* @NL80211_STA_INFO_MAX: highest possible station info attribute * @NL80211_STA_INFO_MAX: highest possible station info attribute
*/ */
...@@ -1261,6 +1263,7 @@ enum nl80211_sta_info { ...@@ -1261,6 +1263,7 @@ enum nl80211_sta_info {
NL80211_STA_INFO_TX_RETRIES, NL80211_STA_INFO_TX_RETRIES,
NL80211_STA_INFO_TX_FAILED, NL80211_STA_INFO_TX_FAILED,
NL80211_STA_INFO_SIGNAL_AVG, NL80211_STA_INFO_SIGNAL_AVG,
NL80211_STA_INFO_RX_BITRATE,
/* keep last */ /* keep last */
__NL80211_STA_INFO_AFTER_LAST, __NL80211_STA_INFO_AFTER_LAST,
......
...@@ -413,7 +413,7 @@ struct station_parameters { ...@@ -413,7 +413,7 @@ struct station_parameters {
* @STATION_INFO_PLID: @plid filled * @STATION_INFO_PLID: @plid filled
* @STATION_INFO_PLINK_STATE: @plink_state filled * @STATION_INFO_PLINK_STATE: @plink_state filled
* @STATION_INFO_SIGNAL: @signal filled * @STATION_INFO_SIGNAL: @signal filled
* @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled * @STATION_INFO_TX_BITRATE: @txrate fields are filled
* (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs) * (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
* @STATION_INFO_RX_PACKETS: @rx_packets filled * @STATION_INFO_RX_PACKETS: @rx_packets filled
* @STATION_INFO_TX_PACKETS: @tx_packets filled * @STATION_INFO_TX_PACKETS: @tx_packets filled
...@@ -421,6 +421,7 @@ struct station_parameters { ...@@ -421,6 +421,7 @@ struct station_parameters {
* @STATION_INFO_TX_FAILED: @tx_failed filled * @STATION_INFO_TX_FAILED: @tx_failed filled
* @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled * @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled
* @STATION_INFO_SIGNAL_AVG: @signal_avg filled * @STATION_INFO_SIGNAL_AVG: @signal_avg filled
* @STATION_INFO_RX_BITRATE: @rxrate fields are filled
*/ */
enum station_info_flags { enum station_info_flags {
STATION_INFO_INACTIVE_TIME = 1<<0, STATION_INFO_INACTIVE_TIME = 1<<0,
...@@ -437,6 +438,7 @@ enum station_info_flags { ...@@ -437,6 +438,7 @@ enum station_info_flags {
STATION_INFO_TX_FAILED = 1<<11, STATION_INFO_TX_FAILED = 1<<11,
STATION_INFO_RX_DROP_MISC = 1<<12, STATION_INFO_RX_DROP_MISC = 1<<12,
STATION_INFO_SIGNAL_AVG = 1<<13, STATION_INFO_SIGNAL_AVG = 1<<13,
STATION_INFO_RX_BITRATE = 1<<14,
}; };
/** /**
...@@ -506,6 +508,7 @@ struct station_info { ...@@ -506,6 +508,7 @@ struct station_info {
s8 signal; s8 signal;
s8 signal_avg; s8 signal_avg;
struct rate_info txrate; struct rate_info txrate;
struct rate_info rxrate;
u32 rx_packets; u32 rx_packets;
u32 tx_packets; u32 tx_packets;
u32 tx_retries; u32 tx_retries;
......
...@@ -1968,13 +1968,41 @@ static int parse_station_flags(struct genl_info *info, ...@@ -1968,13 +1968,41 @@ static int parse_station_flags(struct genl_info *info,
return 0; return 0;
} }
static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
int attr)
{
struct nlattr *rate;
u16 bitrate;
rate = nla_nest_start(msg, attr);
if (!rate)
goto nla_put_failure;
/* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
bitrate = cfg80211_calculate_bitrate(info);
if (bitrate > 0)
NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
if (info->flags & RATE_INFO_FLAGS_MCS)
NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS, info->mcs);
if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
if (info->flags & RATE_INFO_FLAGS_SHORT_GI)
NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
nla_nest_end(msg, rate);
return true;
nla_put_failure:
return false;
}
static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
int flags, struct net_device *dev, int flags, struct net_device *dev,
const u8 *mac_addr, struct station_info *sinfo) const u8 *mac_addr, struct station_info *sinfo)
{ {
void *hdr; void *hdr;
struct nlattr *sinfoattr, *txrate; struct nlattr *sinfoattr;
u16 bitrate;
hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
if (!hdr) if (!hdr)
...@@ -2013,24 +2041,14 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, ...@@ -2013,24 +2041,14 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG, NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG,
sinfo->signal_avg); sinfo->signal_avg);
if (sinfo->filled & STATION_INFO_TX_BITRATE) { if (sinfo->filled & STATION_INFO_TX_BITRATE) {
txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE); if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
if (!txrate) NL80211_STA_INFO_TX_BITRATE))
goto nla_put_failure;
}
if (sinfo->filled & STATION_INFO_RX_BITRATE) {
if (!nl80211_put_sta_rate(msg, &sinfo->rxrate,
NL80211_STA_INFO_RX_BITRATE))
goto nla_put_failure; goto nla_put_failure;
/* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
bitrate = cfg80211_calculate_bitrate(&sinfo->txrate);
if (bitrate > 0)
NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
sinfo->txrate.mcs);
if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)
NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
nla_nest_end(msg, txrate);
} }
if (sinfo->filled & STATION_INFO_RX_PACKETS) if (sinfo->filled & STATION_INFO_RX_PACKETS)
NLA_PUT_U32(msg, NL80211_STA_INFO_RX_PACKETS, NLA_PUT_U32(msg, NL80211_STA_INFO_RX_PACKETS,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment