@@ -2183,6 +2183,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.
@@ -2225,6 +2231,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 */
@@ -6866,8 +6866,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);
@@ -6875,6 +6878,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:
@@ -6928,7 +6966,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
@@ -7008,10 +7046,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];
@@ -7049,6 +7106,48 @@ 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++;
}
}
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@quicinc.com> --- include/net/cfg80211.h | 11 +++++ net/wireless/nl80211.c | 105 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 113 insertions(+), 3 deletions(-)