From: Louis Kotze <loukot@gmail.com>
To: johannes@sipsolutions.net
Cc: linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org,
loukot@gmail.com
Subject: [PATCH v2 1/2] wifi: cfg80211: say why the auth/assoc BSS lookup failed
Date: Tue, 21 Jul 2026 20:11:57 +0200 [thread overview]
Message-ID: <20260721181158.3004022-2-loukot@gmail.com> (raw)
In-Reply-To: <20260721181158.3004022-1-loukot@gmail.com>
The BSS lookup for an authentication or association request can fail
for three distinct reasons: cfg80211 has no scan entry at all for the
BSSID/channel, an entry exists but is older than
IEEE80211_SCAN_RESULT_EXPIRE (and not held), or a fresh entry exists
but its use_for flags do not allow this use. All three currently
surface as the same generic extack message "Error fetching BSS for
link" on the MLO association path, and as a bare -ENOENT with no
message at all on the authentication and non-MLO association paths.
Since wpa_supplicant logs the extack message verbatim ("nl80211:
kernel reports: ..."), that message is often the only diagnostic a
user sees when an MLO association degrades to fewer links, and it
does not say whether rescanning would help. In practice the expired
case is common for MLO partner links: 6 GHz is passive-scan in many
regulatory domains, so the partner-link entry is routinely stale by
the time userspace requests the association even though the link is
perfectly usable.
Let __cfg80211_get_bss() take an optional extack and record, during
the same bss_lock walk that fails the lookup, whether any matching
entry was rejected only for being expired or only for not being
usable for the requested use, and set a distinct message for each
case. Reorder the checks in the walk so that an entry's identity
(type, privacy, channel, BSSID/SSID) is established before the
usability checks; this doesn't change which entry is returned since
an entry is only used when all checks pass. When matching entries
were rejected for both reasons, the use_for message wins: it is only
set for a current (non-expired) entry, so suggesting a rescan would
be misleading.
Also give the -EINVAL paths in nl80211_assoc_bss() proper messages
while at it, and keep pointing the bad_attr at the failing link on
the MLO path.
Signed-off-by: Louis Kotze <loukot@gmail.com>
---
v2: reworked per Johannes' feedback: the reason is captured inside
__cfg80211_get_bss() during the single bss_lock walk (no separate
re-walk helper, no race), reported via a new optional extack
parameter. The authentication path is now covered too, and the
patch grew a KUnit companion (patch 2). Retitled nl80211 -> cfg80211.
include/net/cfg80211.h | 7 +++++--
net/wireless/nl80211.c | 28 +++++++++++++++++-----------
net/wireless/scan.c | 35 +++++++++++++++++++++++++++--------
net/wireless/tests/scan.c | 2 +-
4 files changed, 50 insertions(+), 22 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index b8e9fbb89e69..15c08b24502f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -8424,6 +8424,8 @@ cfg80211_inform_bss(struct wiphy *wiphy,
* @bss_type: type of BSS, see &enum ieee80211_bss_type
* @privacy: privacy filter, see &enum ieee80211_privacy
* @use_for: indicates which use is intended
+ * @extack: (optional) extack that is filled with the reason when no
+ * usable entry was found; may be %NULL
*
* Return: Reference-counted BSS on success. %NULL on error.
*/
@@ -8433,7 +8435,8 @@ struct cfg80211_bss *__cfg80211_get_bss(struct wiphy *wiphy,
const u8 *ssid, size_t ssid_len,
enum ieee80211_bss_type bss_type,
enum ieee80211_privacy privacy,
- u32 use_for);
+ u32 use_for,
+ struct netlink_ext_ack *extack);
/**
* cfg80211_get_bss - get a BSS reference
@@ -8457,7 +8460,7 @@ cfg80211_get_bss(struct wiphy *wiphy, struct ieee80211_channel *channel,
{
return __cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len,
bss_type, privacy,
- NL80211_BSS_USE_FOR_NORMAL);
+ NL80211_BSS_USE_FOR_NORMAL, NULL);
}
static inline struct cfg80211_bss *
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 242071ad10d6..7fb6786a5e8e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -12889,9 +12889,11 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
}
- req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
- IEEE80211_BSS_TYPE_ESS,
- IEEE80211_PRIVACY_ANY);
+ req.bss = __cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
+ IEEE80211_BSS_TYPE_ESS,
+ IEEE80211_PRIVACY_ANY,
+ NL80211_BSS_USE_FOR_NORMAL,
+ info->extack);
if (!req.bss)
return -ENOENT;
@@ -13036,6 +13038,7 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
}
static struct cfg80211_bss *nl80211_assoc_bss(struct cfg80211_registered_device *rdev,
+ struct genl_info *info,
const u8 *ssid, int ssid_len,
struct nlattr **attrs,
int assoc_link_id, int link_id)
@@ -13045,8 +13048,10 @@ static struct cfg80211_bss *nl80211_assoc_bss(struct cfg80211_registered_device
const u8 *bssid;
u32 freq, use_for = 0;
- if (!attrs[NL80211_ATTR_MAC] || !attrs[NL80211_ATTR_WIPHY_FREQ])
+ if (!attrs[NL80211_ATTR_MAC] || !attrs[NL80211_ATTR_WIPHY_FREQ]) {
+ NL_SET_ERR_MSG(info->extack, "BSSID or frequency missing");
return ERR_PTR(-EINVAL);
+ }
bssid = nla_data(attrs[NL80211_ATTR_MAC]);
@@ -13055,8 +13060,10 @@ static struct cfg80211_bss *nl80211_assoc_bss(struct cfg80211_registered_device
freq += nla_get_u32(attrs[NL80211_ATTR_WIPHY_FREQ_OFFSET]);
chan = nl80211_get_valid_chan(&rdev->wiphy, freq);
- if (!chan)
+ if (!chan) {
+ NL_SET_ERR_MSG(info->extack, "invalid or disabled channel");
return ERR_PTR(-EINVAL);
+ }
if (assoc_link_id >= 0)
use_for = NL80211_BSS_USE_FOR_MLD_LINK;
@@ -13067,7 +13074,7 @@ static struct cfg80211_bss *nl80211_assoc_bss(struct cfg80211_registered_device
ssid, ssid_len,
IEEE80211_BSS_TYPE_ESS,
IEEE80211_PRIVACY_ANY,
- use_for);
+ use_for, info->extack);
if (!bss)
return ERR_PTR(-ENOENT);
@@ -13106,13 +13113,12 @@ static int nl80211_process_links(struct cfg80211_registered_device *rdev,
return -EINVAL;
}
links[link_id].bss =
- nl80211_assoc_bss(rdev, ssid, ssid_len, attrs,
+ nl80211_assoc_bss(rdev, info, ssid, ssid_len, attrs,
assoc_link_id, link_id);
if (IS_ERR(links[link_id].bss)) {
err = PTR_ERR(links[link_id].bss);
links[link_id].bss = NULL;
- NL_SET_ERR_MSG_ATTR(info->extack, link,
- "Error fetching BSS for link");
+ NL_SET_BAD_ATTR(info->extack, link);
return err;
}
@@ -13328,8 +13334,8 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
if (req.link_id >= 0)
return -EINVAL;
- req.bss = nl80211_assoc_bss(rdev, ssid, ssid_len, info->attrs,
- -1, -1);
+ req.bss = nl80211_assoc_bss(rdev, info, ssid, ssid_len,
+ info->attrs, -1, -1);
if (IS_ERR(req.bss))
return PTR_ERR(req.bss);
ap_addr = req.bss->bssid;
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 05b7dc6b766c..f26e8436dbc1 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1609,10 +1609,12 @@ struct cfg80211_bss *__cfg80211_get_bss(struct wiphy *wiphy,
const u8 *ssid, size_t ssid_len,
enum ieee80211_bss_type bss_type,
enum ieee80211_privacy privacy,
- u32 use_for)
+ u32 use_for,
+ struct netlink_ext_ack *extack)
{
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
struct cfg80211_internal_bss *bss, *res = NULL;
+ bool expired = false, unusable = false;
unsigned long now = jiffies;
int bss_privacy;
@@ -1634,22 +1636,39 @@ struct cfg80211_bss *__cfg80211_get_bss(struct wiphy *wiphy,
continue;
if (!is_valid_ether_addr(bss->pub.bssid))
continue;
- if ((bss->pub.use_for & use_for) != use_for)
+ if (!is_bss(&bss->pub, bssid, ssid, ssid_len))
continue;
+
/* Don't get expired BSS structs */
if (time_after(now, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE) &&
- !atomic_read(&bss->hold))
+ !atomic_read(&bss->hold)) {
+ expired = true;
+ continue;
+ }
+
+ if ((bss->pub.use_for & use_for) != use_for) {
+ unusable = true;
continue;
- if (is_bss(&bss->pub, bssid, ssid, ssid_len)) {
- res = bss;
- bss_ref_get(rdev, res);
- break;
}
+
+ res = bss;
+ bss_ref_get(rdev, res);
+ break;
}
spin_unlock_bh(&rdev->bss_lock);
- if (!res)
+ if (!res) {
+ if (unusable)
+ NL_SET_ERR_MSG(extack,
+ "BSS cannot be used for the requested operation");
+ else if (expired)
+ NL_SET_ERR_MSG(extack,
+ "BSS entry is expired, scan again");
+ else
+ NL_SET_ERR_MSG(extack,
+ "BSS not found in scan results");
return NULL;
+ }
trace_cfg80211_return_bss(&res->pub);
return &res->pub;
}
diff --git a/net/wireless/tests/scan.c b/net/wireless/tests/scan.c
index b1a9c1466d6c..2fc717317ac3 100644
--- a/net/wireless/tests/scan.c
+++ b/net/wireless/tests/scan.c
@@ -617,7 +617,7 @@ static void test_inform_bss_ml_sta(struct kunit *test)
link_bss = __cfg80211_get_bss(wiphy, NULL, sta_prof.bssid, NULL, 0,
IEEE80211_BSS_TYPE_ANY,
IEEE80211_PRIVACY_ANY,
- 0);
+ 0, NULL);
KUNIT_ASSERT_NOT_NULL(test, link_bss);
KUNIT_EXPECT_EQ(test, link_bss->signal, 0);
KUNIT_EXPECT_EQ(test, link_bss->beacon_interval,
--
2.55.0
next prev parent reply other threads:[~2026-07-21 18:12 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-11 4:34 [PATCH] wifi: nl80211: say why the association BSS lookup failed Louis Kotze
2026-07-21 15:31 ` Johannes Berg
2026-07-21 18:11 ` [PATCH v2 0/2] wifi: cfg80211: say why the auth/assoc " Louis Kotze
2026-07-21 18:11 ` Louis Kotze [this message]
2026-07-21 22:10 ` [PATCH v2 1/2] " Johannes Berg
2026-07-22 7:07 ` Louis Kotze
2026-07-22 7:07 ` [PATCH v3 0/2] " Louis Kotze
2026-07-22 7:07 ` [PATCH v3 1/2] " Louis Kotze
2026-07-22 7:07 ` [PATCH v3 2/2] wifi: cfg80211: tests: check BSS lookup failure reasons Louis Kotze
2026-07-21 18:11 ` [PATCH v2 " Louis Kotze
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260721181158.3004022-2-loukot@gmail.com \
--to=loukot@gmail.com \
--cc=johannes@sipsolutions.net \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-wireless@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.