Currently, the accumulable statistics for multi-link operation(MLO) are handled. Other statistics, such as signal and rates, are managed at the link level. Therefore, add signal, rates, inactive time, dtim_period and beacon_interval at the MLO level to provide an comprehensive overview of the station. The signal could be the best of all links- e.g. if Link 1 has a signal strength of -70 dBm and Link 2 has -65 dBm, the signal for MLO will be -65 dBm. The rate could be determined based on the most recently updated link- e.g. if link 1 has a rate of 300 Mbps and link 2 has a rate of 450 Mbps, the MLO rate can be calculated based on the inactivity of each link. If the inactive time for link 1 is 20 seconds and for link 2 is 10 seconds, the MLO rate will be the most recently updated rate, which is link 2's rate of 450 Mbps. The inactive time, dtim_period and beacon_interval can be taken as the least value of field from link level. Signed-off-by: Sarika Sharma <quic_sarishar@xxxxxxxxxxx> --- include/net/cfg80211.h | 11 +++++ net/wireless/nl80211.c | 101 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 109 insertions(+), 3 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 6eed887a93b1..46f24b0c058e 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2180,6 +2180,12 @@ struct link_station_info { * @tx_bytes: total bytes (size of MPDUs) transmitted to this station * @tx_retries: cumulative retry counts (MPDUs) * @tx_failed: number of failed transmissions (MPDUs) (retries exceeded, no ACK) + * @inactive_time: time since last station activity (tx/rx) in milliseconds + * @bss_param: current BSS parameters + * @signal: The signal strength, type depends on the wiphy's signal_type. + * For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_. + * @txrate: last updated unicast bitrate from this station + * @rxrate: last updated unicast bitrate to this station * @valid_links: bitmap of valid links, or 0 for non-MLO. Drivers fill this * information in cfg80211_new_sta(), cfg80211_del_sta_sinfo(), * get_station() and dump_station() callbacks. @@ -2222,6 +2228,11 @@ struct station_info { u64 tx_bytes; u32 tx_retries; u32 tx_failed; + u32 inactive_time; + struct sta_bss_parameters bss_param; + s8 signal; + struct rate_info txrate; + struct rate_info rxrate; u16 valid_links; /* TODO: Need to check and add protection access to links memory */ diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 58ef0c5df670..2be3318ac17c 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -6861,8 +6861,11 @@ static int nl80211_fill_link_station(struct sk_buff *msg, } static int nl80211_fill_mld_station(struct sk_buff *msg, - struct station_info *sinfo) + struct station_info *sinfo, + struct cfg80211_registered_device *rdev) { + struct nlattr *bss_param; + PUT_SINFO(RX_PACKETS, rx_packets, u32); PUT_SINFO(TX_PACKETS, tx_packets, u32); PUT_SINFO_U64(RX_BYTES, rx_bytes); @@ -6870,6 +6873,41 @@ static int nl80211_fill_mld_station(struct sk_buff *msg, PUT_SINFO(TX_RETRIES, tx_retries, u32); PUT_SINFO(TX_FAILED, tx_failed, u32); + switch (rdev->wiphy.signal_type) { + case CFG80211_SIGNAL_TYPE_MBM: + PUT_SINFO(SIGNAL, signal, u8); + break; + default: + break; + } + + PUT_SINFO(INACTIVE_TIME, inactive_time, u32); + + if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE) && + !nl80211_put_sta_rate(msg, &sinfo->txrate, + NL80211_STA_INFO_TX_BITRATE)) + goto nla_put_failure; + + if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE) && + !nl80211_put_sta_rate(msg, &sinfo->rxrate, + NL80211_STA_INFO_RX_BITRATE)) + goto nla_put_failure; + + if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_BSS_PARAM)) { + bss_param = nla_nest_start_noflag(msg, + NL80211_STA_INFO_BSS_PARAM); + if (!bss_param) + goto nla_put_failure; + + if (nla_put_u8(msg, NL80211_STA_BSS_PARAM_DTIM_PERIOD, + sinfo->bss_param.dtim_period) || + nla_put_u16(msg, NL80211_STA_BSS_PARAM_BEACON_INTERVAL, + sinfo->bss_param.beacon_interval)) + goto nla_put_failure; + + nla_nest_end(msg, bss_param); + } + return 0; nla_put_failure: @@ -6923,7 +6961,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, goto nla_put_failure; if (sinfo->is_per_link_stats_support && sinfo->valid_links) { - if (nl80211_fill_mld_station(msg, sinfo)) + if (nl80211_fill_mld_station(msg, sinfo, rdev)) goto nla_put_failure; /* Closing nested STA_INFO as MLO links ATTR should not @@ -7001,10 +7039,29 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid, #undef PUT_SINFO #undef PUT_SINFO_U64 +static void cfg80211_sta_set_mld_rate_info(struct rate_info *sinfo_rate, + struct rate_info *link_sinfo_rate) +{ + sinfo_rate->flags = link_sinfo_rate->flags; + sinfo_rate->legacy = link_sinfo_rate->legacy; + sinfo_rate->mcs = link_sinfo_rate->mcs; + sinfo_rate->nss = link_sinfo_rate->nss; + sinfo_rate->bw = link_sinfo_rate->bw; + sinfo_rate->he_gi = link_sinfo_rate->he_gi; + sinfo_rate->he_dcm = link_sinfo_rate->he_dcm; + sinfo_rate->he_ru_alloc = link_sinfo_rate->he_ru_alloc; + sinfo_rate->n_bonded_ch = link_sinfo_rate->n_bonded_ch; + sinfo_rate->eht_gi = link_sinfo_rate->eht_gi; + sinfo_rate->eht_ru_alloc = link_sinfo_rate->eht_ru_alloc; +} + static void cfg80211_sta_set_mld_sinfo(struct station_info *sinfo) { struct link_station_info *link_sinfo; - int link_id; + int link_id, init = 0;; + u32 link_inactive_time; + + sinfo->signal = -99; for_each_valid_link(sinfo, link_id) { link_sinfo = sinfo->links[link_id]; @@ -7042,6 +7099,44 @@ static void cfg80211_sta_set_mld_sinfo(struct station_info *sinfo) sinfo->tx_failed += link_sinfo->tx_failed; sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); } + + /* Update MLO signal as per best of all link signal */ + if ((link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_SIGNAL)) && + (link_sinfo->signal > sinfo->signal)) { + sinfo->signal = link_sinfo->signal; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL); + } + + /* Update MLO inactive_time, bss_param based on least + * value for corresponding field of link. + */ + if ((link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME)) && + (!init || link_inactive_time > link_sinfo->inactive_time)) { + link_inactive_time = link_sinfo->inactive_time; + sinfo->inactive_time = link_sinfo->inactive_time; + sinfo->filled |= NL80211_STA_INFO_INACTIVE_TIME; + } + + if (link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_BSS_PARAM) && + (!init || sinfo->bss_param.dtim_period > link_sinfo->bss_param.dtim_period)) { + sinfo->bss_param.dtim_period = link_sinfo->bss_param.dtim_period; + sinfo->filled |= NL80211_STA_BSS_PARAM_DTIM_PERIOD; + sinfo->bss_param.beacon_interval = link_sinfo->bss_param.beacon_interval; + sinfo->filled |= NL80211_STA_BSS_PARAM_BEACON_INTERVAL; + } + + /* Update MLO rates as per last updated link rate */ + if ((link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)) && + (!init || link_inactive_time > link_sinfo->inactive_time)) { + cfg80211_sta_set_mld_rate_info(&sinfo->txrate, &link_sinfo->txrate); + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); + } + if ((link_sinfo->filled & BIT_ULL(NL80211_STA_INFO_RX_BITRATE)) && + (!init || link_inactive_time > link_sinfo->inactive_time)) { + cfg80211_sta_set_mld_rate_info(&sinfo->rxrate, &link_sinfo->rxrate); + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE); + } + init++; } } -- 2.34.1