Report the time since the last beacon was received from a peer station in station info using the NL attribute NL80211_STA_INFO_BEACON_SEEN_MSEC_AGO. This applies to non-AP STA, mesh and adhoc modes. In non-AP MLD STA mode, this attribute is reported per link and additionally, it is reported at the MLD level, the timestamp of the most recently received beacon across all affiliated AP STA links to give a unified view of beacon reception status. Signed-off-by: Maharaja Kennadyrajan --- net/mac80211/mesh.c | 4 ++++ net/mac80211/mesh.h | 4 ++++ net/mac80211/mesh_plink.c | 18 ++++++++++++++++++ net/mac80211/mlme.c | 2 ++ net/mac80211/sta_info.c | 31 ++++++++++++++++++++++++++++++- net/mac80211/sta_info.h | 3 +++ 6 files changed, 61 insertions(+), 1 deletion(-) diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index a4a715f6f1c3..a6b83633ec33 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -1508,6 +1508,10 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, if (ifmsh->csa_role != IEEE80211_MESH_CSA_ROLE_INIT && !sdata->vif.bss_conf.csa_active) ieee80211_mesh_process_chnswitch(sdata, elems, true); + + if (stype == IEEE80211_STYPE_BEACON) + mesh_last_beacon_seen_msec_ago(sdata, mgmt, elems, + rx_status); } if (ifmsh->sync_ops) diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 3f9664e4e00c..3e13834a5804 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -327,6 +327,10 @@ int mesh_path_send_to_gates(struct mesh_path *mpath); int mesh_gate_num(struct ieee80211_sub_if_data *sdata); u32 airtime_link_metric_get(struct ieee80211_local *local, struct sta_info *sta); +void mesh_last_beacon_seen_msec_ago(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, + struct ieee802_11_elems *ie, + struct ieee80211_rx_status *rx_status); /* Mesh plinks */ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index cb45a5d2009d..d84a49372d20 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -613,6 +613,24 @@ mesh_sta_info_get(struct ieee80211_sub_if_data *sdata, return sta; } +void mesh_last_beacon_seen_msec_ago(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, + struct ieee802_11_elems *elems, + struct ieee80211_rx_status *rx_status) +{ + struct sta_info *sta; + + /* mesh_sta_info_get api returns with rcu_read_lock */ + sta = mesh_sta_info_get(sdata, mgmt->sa, elems, rx_status); + if (!sta) + goto unlock_rcu; + + sta->deflink.last_beacon_seen_msec_ago = jiffies; + +unlock_rcu: + rcu_read_unlock(); +} + /* * mesh_neighbour_update - update or initialize new mesh neighbor. * diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 1008eb8e9b13..5194c0f4f887 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -7567,6 +7567,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link, goto free; } + link_sta->last_beacon_seen_msec_ago = jiffies; + if (WARN_ON(!bss_conf->chanreq.oper.chan)) goto free; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 8c550aab9bdc..aa3501ec2096 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -2954,6 +2954,15 @@ static void sta_set_link_sinfo(struct sta_info *sta, link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG); } + + if (!(link_sinfo->filled & + BIT_ULL(NL80211_STA_INFO_BEACON_SEEN_MSEC_AGO))) { + link_sinfo->last_beacon_seen_msec_ago = + jiffies_to_msecs(jiffies - + link_sta_info->last_beacon_seen_msec_ago); + link_sinfo->filled |= + BIT_ULL(NL80211_STA_INFO_BEACON_SEEN_MSEC_AGO); + } } void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, @@ -2961,7 +2970,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, { struct ieee80211_sub_if_data *sdata = sta->sdata; struct ieee80211_local *local = sdata->local; - u32 thr = 0; + u32 thr = 0, last_beacon_seen_msec_ago = 0; int i, ac, cpu, link_id; struct ieee80211_sta_rx_stats *last_rxstats; @@ -3204,6 +3213,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, if (sta->sta.valid_links) { struct ieee80211_link_data *link; struct link_sta_info *link_sta; + bool init = false; ether_addr_copy(sinfo->mld_addr, sta->addr); for_each_valid_link(sinfo, link_id) { @@ -3218,7 +3228,26 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, sinfo->valid_links = sta->sta.valid_links; sta_set_link_sinfo(sta, sinfo->links[link_id], link, tidstats); + if (!init || + link_sta->last_beacon_seen_msec_ago > + last_beacon_seen_msec_ago) + last_beacon_seen_msec_ago = + link_sta->last_beacon_seen_msec_ago; + init = true; } + } else { + last_beacon_seen_msec_ago = + sta->deflink.last_beacon_seen_msec_ago; + } + + if (!(sinfo->filled & + BIT_ULL(NL80211_STA_INFO_BEACON_SEEN_MSEC_AGO)) && + last_beacon_seen_msec_ago) { + sinfo->last_beacon_seen_msec_ago = + jiffies_to_msecs(jiffies - + last_beacon_seen_msec_ago); + sinfo->filled |= + BIT_ULL(NL80211_STA_INFO_BEACON_SEEN_MSEC_AGO); } } diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 5288d5286651..a4f976d58a93 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -510,6 +510,7 @@ struct ieee80211_fragment_cache { * during finalize * @debugfs_dir: debug filesystem directory dentry * @pub: public (driver visible) link STA data + * @last_beacon_seen_msec_ago: timestamp of last received beacon in jiffies * TODO Move other link params from sta_info as required for MLD operation */ struct link_sta_info { @@ -565,6 +566,8 @@ struct link_sta_info { struct dentry *debugfs_dir; #endif + unsigned long last_beacon_seen_msec_ago; + struct ieee80211_link_sta *pub; }; -- 2.17.1