diff options
author | Johannes Berg <johannes.berg@intel.com> | 2022-09-02 16:12:43 +0200 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2022-09-06 10:13:41 +0200 |
commit | ffa9598ecb93630a45564b95ae17362b819b38de (patch) | |
tree | 438af9a1e68cee0cc8853f68a000fd387f4bad48 | |
parent | efe9c2bfd1a82894e455514a68dc794556fbd463 (diff) |
wifi: mac80211: add ieee80211_find_sta_by_link_addrs API
Add a new API function ieee80211_find_sta_by_link_addrs()
that looks up the STA and link ID based on interface and
station link addresses.
We're going to use it for mac80211-hwsim to track on the
AP side which links are active.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r-- | include/net/mac80211.h | 16 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 37 |
2 files changed, 53 insertions, 0 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 20a2f25a38fa..954cc029a9f9 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -5987,6 +5987,22 @@ struct ieee80211_sta *ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw, const u8 *localaddr); /** + * ieee80211_find_sta_by_link_addrs - find STA by link addresses + * @hw: pointer as obtained from ieee80211_alloc_hw() + * @addr: remote station's link address + * @localaddr: local link address, use %NULL for any (but avoid that) + * @link_id: pointer to obtain the link ID if the STA is found, + * may be %NULL if the link ID is not needed + * + * Obtain the STA by link address, must use RCU protection. + */ +struct ieee80211_sta * +ieee80211_find_sta_by_link_addrs(struct ieee80211_hw *hw, + const u8 *addr, + const u8 *localaddr, + unsigned int *link_id); + +/** * ieee80211_sta_block_awake - block station from waking up * @hw: the hardware * @pubsta: the station diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index ac88a894e5f9..bbf582a5702d 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -274,6 +274,43 @@ link_sta_info_get_bss(struct ieee80211_sub_if_data *sdata, const u8 *addr) return NULL; } +struct ieee80211_sta * +ieee80211_find_sta_by_link_addrs(struct ieee80211_hw *hw, + const u8 *addr, + const u8 *localaddr, + unsigned int *link_id) +{ + struct ieee80211_local *local = hw_to_local(hw); + struct link_sta_info *link_sta; + struct rhlist_head *tmp; + + for_each_link_sta_info(local, addr, link_sta, tmp) { + struct sta_info *sta = link_sta->sta; + struct ieee80211_link_data *link; + u8 _link_id = link_sta->link_id; + + if (!localaddr) { + if (link_id) + *link_id = _link_id; + return &sta->sta; + } + + link = rcu_dereference(sta->sdata->link[_link_id]); + if (!link) + continue; + + if (memcmp(link->conf->addr, localaddr, ETH_ALEN)) + continue; + + if (link_id) + *link_id = _link_id; + return &sta->sta; + } + + return NULL; +} +EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_link_addrs); + struct sta_info *sta_info_get_by_addrs(struct ieee80211_local *local, const u8 *sta_addr, const u8 *vif_addr) { |