wifi: mac80211: add ieee80211_find_sta_by_link_addrs API
authorJohannes Berg <johannes.berg@intel.com>
Fri, 2 Sep 2022 14:12:43 +0000 (16:12 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 6 Sep 2022 08:13:41 +0000 (10:13 +0200)
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>
include/net/mac80211.h
net/mac80211/sta_info.c

index 20a2f25a38fac1b1fd58a421372a4e1908152204..954cc029a9f9d1c0b35cf139515e0baf0da99601 100644 (file)
@@ -5986,6 +5986,22 @@ struct ieee80211_sta *ieee80211_find_sta_by_ifaddr(struct ieee80211_hw *hw,
                                               const u8 *addr,
                                               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
index ac88a894e5f943fc7d526e385ebd73258b6d9e67..bbf582a5702d58225a70e31b269cf042ee4e5c7d 100644 (file)
@@ -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)
 {