The branch main has been updated by bz:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=5edde07c2aba02d0f7d30bbb0f203ec3e920e273

commit 5edde07c2aba02d0f7d30bbb0f203ec3e920e273
Author:     Bjoern A. Zeeb <[email protected]>
AuthorDate: 2022-12-31 01:18:16 +0000
Commit:     Bjoern A. Zeeb <[email protected]>
CommitDate: 2022-12-31 01:18:16 +0000

    LinuxKPI: 802.11: implement cfg80211_{get,put}_bss
    
    Implement cfg80211_{get,put}_bss currently doing malloc/free bits,
    so hopefully the drivers get the calls right.
    
    cfg80211_get_bss() sets up a lookup structure which may also take a
    result (first hit wins) and calls ieee80211_scan_iterate() comparing
    the various values in the iterator funcion.  Some of the checks are
    partially pointless (as it seems the drivers are not interested in
    these parts [ANY] but we keep them for documentation purposes should
    futher values arise in the future).
    
    We currently only iterate over the first VAP which will do for now.
    
    Sponsored by:   The FreeBSD Foundation
    MFC after:      10 days
---
 sys/compat/linuxkpi/common/include/net/cfg80211.h |  51 +++---
 sys/compat/linuxkpi/common/src/linux_80211.c      | 194 +++++++++++++++++++---
 2 files changed, 199 insertions(+), 46 deletions(-)

diff --git a/sys/compat/linuxkpi/common/include/net/cfg80211.h 
b/sys/compat/linuxkpi/common/include/net/cfg80211.h
index e6f1bd88309d..5f7755b44ba7 100644
--- a/sys/compat/linuxkpi/common/include/net/cfg80211.h
+++ b/sys/compat/linuxkpi/common/include/net/cfg80211.h
@@ -1118,6 +1118,10 @@ uint32_t 
linuxkpi_ieee80211_channel_to_frequency(uint32_t, enum nl80211_band);
 uint32_t linuxkpi_ieee80211_frequency_to_channel(uint32_t, uint32_t);
 struct linuxkpi_ieee80211_channel *
     linuxkpi_ieee80211_get_channel(struct wiphy *, uint32_t);
+struct cfg80211_bss *linuxkpi_cfg80211_get_bss(struct wiphy *,
+    struct linuxkpi_ieee80211_channel *, const uint8_t *,
+    const uint8_t *, size_t, enum ieee80211_bss_type, enum ieee80211_privacy);
+void linuxkpi_cfg80211_put_bss(struct wiphy *, struct cfg80211_bss *);
 void linuxkpi_cfg80211_bss_flush(struct wiphy *);
 
 /* -------------------------------------------------------------------------- 
*/
@@ -1189,6 +1193,32 @@ wiphy_rfkill_set_hw_state_reason(struct wiphy *wiphy, 
bool blocked,
 
 /* -------------------------------------------------------------------------- 
*/
 
+static inline struct cfg80211_bss *
+cfg80211_get_bss(struct wiphy *wiphy, struct linuxkpi_ieee80211_channel *chan,
+    const uint8_t *bssid, const uint8_t *ssid, size_t ssid_len,
+    enum ieee80211_bss_type bss_type, enum ieee80211_privacy privacy)
+{
+
+       return (linuxkpi_cfg80211_get_bss(wiphy, chan, bssid, ssid, ssid_len,
+          bss_type, privacy));
+}
+
+static inline void
+cfg80211_put_bss(struct wiphy *wiphy, struct cfg80211_bss *bss)
+{
+
+       linuxkpi_cfg80211_put_bss(wiphy, bss);
+}
+
+static inline void
+cfg80211_bss_flush(struct wiphy *wiphy)
+{
+
+       linuxkpi_cfg80211_bss_flush(wiphy);
+}
+
+/* -------------------------------------------------------------------------- 
*/
+
 static __inline bool
 rfkill_blocked(int rfkill)             /* argument type? */
 {
@@ -1383,20 +1413,6 @@ freq_reg_info(struct wiphy *wiphy, uint32_t center_freq)
        return (NULL);
 }
 
-static __inline struct cfg80211_bss *
-cfg80211_get_bss(struct wiphy *wiphy, struct linuxkpi_ieee80211_channel *chan,
-    const uint8_t *bssid, void *p, int x, uint32_t f1, uint32_t f2)
-{
-       TODO();
-       return (NULL);
-}
-
-static __inline void
-cfg80211_put_bss(struct wiphy *wiphy, struct cfg80211_bss *bss)
-{
-       TODO();
-}
-
 static __inline void
 wiphy_apply_custom_regulatory(struct wiphy *wiphy,
     const struct linuxkpi_ieee80211_regdomain *regd)
@@ -1658,13 +1674,6 @@ ieee80211_get_hdrlen_from_skb(struct sk_buff *skb)
        return (-1);
 }
 
-static __inline void
-cfg80211_bss_flush(struct wiphy *wiphy)
-{
-
-       linuxkpi_cfg80211_bss_flush(wiphy);
-}
-
 static __inline bool
 cfg80211_channel_is_psc(struct linuxkpi_ieee80211_channel *channel)
 {
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c 
b/sys/compat/linuxkpi/common/src/linux_80211.c
index 949f9157fe35..3741996eff1c 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -544,31 +544,6 @@ linuxkpi_ieee80211_get_channel(struct wiphy *wiphy, 
uint32_t freq)
        return (NULL);
 }
 
-void
-linuxkpi_cfg80211_bss_flush(struct wiphy *wiphy)
-{
-       struct lkpi_hw *lhw;
-       struct ieee80211com *ic;
-       struct ieee80211vap *vap;
-
-       lhw = wiphy_priv(wiphy);
-       ic = lhw->ic;
-
-       /*
-        * If we haven't called ieee80211_ifattach() yet
-        * or there is no VAP, there are no scans to flush.
-        */
-       if (ic == NULL ||
-           (lhw->sc_flags & LKPI_MAC80211_DRV_STARTED) == 0)
-               return;
-
-       /* Should only happen on the current one? Not seen it late enough. */
-       IEEE80211_LOCK(ic);
-       TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
-               ieee80211_scan_flush(vap);
-       IEEE80211_UNLOCK(ic);
-}
-
 #ifdef LKPI_80211_HW_CRYPTO
 static int
 _lkpi_iv_key_set_delete(struct ieee80211vap *vap, const struct ieee80211_key 
*k,
@@ -4586,6 +4561,175 @@ linuxkpi_ieee80211_beacon_loss(struct ieee80211_vif 
*vif)
        ieee80211_beacon_miss(vap->iv_ic);
 }
 
+/* -------------------------------------------------------------------------- 
*/
+
+struct lkpi_cfg80211_bss {
+       u_int refcnt;
+       struct cfg80211_bss bss;
+};
+
+struct lkpi_cfg80211_get_bss_iter_lookup {
+       struct wiphy *wiphy;
+       struct linuxkpi_ieee80211_channel *chan;
+       const uint8_t *bssid;
+       const uint8_t *ssid;
+       size_t ssid_len;
+       enum ieee80211_bss_type bss_type;
+       enum ieee80211_privacy privacy;
+
+       /*
+        * Something to store a copy of the result as the net80211 scan cache
+        * is not refoucnted so a scan entry might go away any time.
+        */
+       bool match;
+       struct cfg80211_bss *bss;
+};
+
+static void
+lkpi_cfg80211_get_bss_iterf(void *arg, const struct ieee80211_scan_entry *se)
+{
+       struct lkpi_cfg80211_get_bss_iter_lookup *lookup;
+       size_t ielen;
+
+       lookup = arg;
+
+       /* Do not try to find another match. */
+       if (lookup->match)
+               return;
+
+       /* Nothing to store result. */
+       if (lookup->bss == NULL)
+               return;
+
+       if (lookup->privacy != IEEE80211_PRIVACY_ANY) {
+               /* if (se->se_capinfo & IEEE80211_CAPINFO_PRIVACY) */
+               /* We have no idea what to compare to as the drivers only 
request ANY */
+               return;
+       }
+
+       if (lookup->bss_type != IEEE80211_BSS_TYPE_ANY) {
+               /* if (se->se_capinfo & 
(IEEE80211_CAPINFO_IBSS|IEEE80211_CAPINFO_ESS)) */
+               /* We have no idea what to compare to as the drivers only 
request ANY */
+               return;
+       }
+
+       if (lookup->chan != NULL) {
+               struct linuxkpi_ieee80211_channel *chan;
+
+               chan = linuxkpi_ieee80211_get_channel(lookup->wiphy,
+                   se->se_chan->ic_freq);
+               if (chan == NULL || chan != lookup->chan)
+                       return;
+       }
+
+       if (lookup->bssid && !IEEE80211_ADDR_EQ(lookup->bssid, se->se_bssid))
+               return;
+
+       if (lookup->ssid) {
+               if (lookup->ssid_len != se->se_ssid[1] ||
+                   se->se_ssid[1] == 0)
+                       return;
+               if (memcmp(lookup->ssid, se->se_ssid+2, lookup->ssid_len) != 0)
+                       return;
+       }
+
+       ielen = se->se_ies.len;
+
+       lookup->bss->ies = malloc(sizeof(*lookup->bss->ies) + ielen,
+           M_LKPI80211, M_NOWAIT | M_ZERO);
+       if (lookup->bss->ies == NULL)
+               return;
+
+       lookup->bss->ies->data = (uint8_t *)lookup->bss->ies + 
sizeof(*lookup->bss->ies);
+       lookup->bss->ies->len = ielen;
+       if (ielen)
+               memcpy(lookup->bss->ies->data, se->se_ies.data, ielen);
+
+       lookup->match = true;
+}
+
+struct cfg80211_bss *
+linuxkpi_cfg80211_get_bss(struct wiphy *wiphy, struct 
linuxkpi_ieee80211_channel *chan,
+    const uint8_t *bssid, const uint8_t *ssid, size_t ssid_len,
+    enum ieee80211_bss_type bss_type, enum ieee80211_privacy privacy)
+{
+       struct lkpi_cfg80211_bss *lbss;
+       struct lkpi_cfg80211_get_bss_iter_lookup lookup;
+       struct lkpi_hw *lhw;
+       struct ieee80211vap *vap;
+
+       lhw = wiphy_priv(wiphy);
+
+       /* Let's hope we can alloc. */
+       lbss = malloc(sizeof(*lbss), M_LKPI80211, M_NOWAIT | M_ZERO);
+       if (lbss == NULL) {
+               ic_printf(lhw->ic, "%s: alloc failed.\n", __func__);
+               return (NULL);
+       }
+
+       lookup.wiphy = wiphy;
+       lookup.chan = chan;
+       lookup.bssid = bssid;
+       lookup.ssid = ssid;
+       lookup.ssid_len = ssid_len;
+       lookup.bss_type = bss_type;
+       lookup.privacy = privacy;
+       lookup.match = false;
+       lookup.bss = &lbss->bss;
+
+       IMPROVE("Iterate over all VAPs comparing perm_addr and addresses?");
+       vap = TAILQ_FIRST(&lhw->ic->ic_vaps);
+       ieee80211_scan_iterate(vap, lkpi_cfg80211_get_bss_iterf, &lookup);
+       if (!lookup.match) {
+               free(lbss, M_LKPI80211);
+               return (NULL);
+       }
+
+       refcount_init(&lbss->refcnt, 1);
+       return (&lbss->bss);
+}
+
+void
+linuxkpi_cfg80211_put_bss(struct wiphy *wiphy, struct cfg80211_bss *bss)
+{
+       struct lkpi_cfg80211_bss *lbss;
+
+       lbss = container_of(bss, struct lkpi_cfg80211_bss, bss);
+
+       /* Free everything again on refcount ... */
+       if (refcount_release(&lbss->refcnt)) {
+               free(lbss->bss.ies, M_LKPI80211);
+               free(lbss, M_LKPI80211);
+       }
+}
+
+void
+linuxkpi_cfg80211_bss_flush(struct wiphy *wiphy)
+{
+       struct lkpi_hw *lhw;
+       struct ieee80211com *ic;
+       struct ieee80211vap *vap;
+
+       lhw = wiphy_priv(wiphy);
+       ic = lhw->ic;
+
+       /*
+        * If we haven't called ieee80211_ifattach() yet
+        * or there is no VAP, there are no scans to flush.
+        */
+       if (ic == NULL ||
+           (lhw->sc_flags & LKPI_MAC80211_DRV_STARTED) == 0)
+               return;
+
+       /* Should only happen on the current one? Not seen it late enough. */
+       IEEE80211_LOCK(ic);
+       TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
+               ieee80211_scan_flush(vap);
+       IEEE80211_UNLOCK(ic);
+}
+
+/* -------------------------------------------------------------------------- 
*/
+
 MODULE_VERSION(linuxkpi_wlan, 1);
 MODULE_DEPEND(linuxkpi_wlan, linuxkpi, 1, 1, 1);
 MODULE_DEPEND(linuxkpi_wlan, wlan, 1, 1, 1);

Reply via email to