winfo: account noise for multiple radio from same wiphy
authorChristian Marangi <[email protected]>
Sun, 19 Oct 2025 11:17:55 +0000 (13:17 +0200)
committerChristian Marangi <[email protected]>
Sun, 19 Oct 2025 11:49:33 +0000 (13:49 +0200)
With the introduction of MLO, a wiphy might have multiple radio serving
it. The current code that parse the noise level use the IN_USE flag to
identify the affected radio but this changed with MLO as now multiple
radio can have IN_USE flag set.

This confuse the parsing as only the first radio is parsed with all the
other skipped, resulting in all the radio for the wiphy wrongly reporting
the noise of the first.

Rework the noise parsing logic to check if the frequency match the
current interface in addition to the IN_USE flag.

Suggested-by: Valeriy Kosikhin <[email protected]>
Tested-by: Aleksander Jan Bajkowski <[email protected]> # tested on Quantum W1700k
Co-developed-by: Valeriy Kosikhin <[email protected]>
Signed-off-by: Christian Marangi <[email protected]>
iwinfo_nl80211.c

index dc4ff93e4c635f1beeb50e049c707d24734556ff..97f2131ef8f24ff3452995a54cdb99aabfa7df77 100644 (file)
@@ -1658,9 +1658,14 @@ static int nl80211_get_signal(const char *ifname, int *buf)
        return -1;
 }
 
+struct nl80211_frequency_noise {
+       uint32_t frequency;
+       uint8_t noise;
+};
+
 static int nl80211_get_noise_cb(struct nl_msg *msg, void *arg)
 {
-       int8_t *noise = arg;
+       struct nl80211_frequency_noise *fn = arg;
        struct nlattr **tb = nl80211_parse(msg);
        struct nlattr *si[NL80211_SURVEY_INFO_MAX + 1];
 
@@ -1676,11 +1681,15 @@ static int nl80211_get_noise_cb(struct nl_msg *msg, void *arg)
                             tb[NL80211_ATTR_SURVEY_INFO], sp))
                return NL_SKIP;
 
-       if (!si[NL80211_SURVEY_INFO_NOISE])
+       if (!si[NL80211_SURVEY_INFO_NOISE] ||
+           !si[NL80211_SURVEY_INFO_FREQUENCY])
+               return NL_SKIP;
+
+       if (nla_get_u32(si[NL80211_SURVEY_INFO_FREQUENCY]) != fn->frequency)
                return NL_SKIP;
 
-       if (!*noise || si[NL80211_SURVEY_INFO_IN_USE])
-               *noise = (int8_t)nla_get_u8(si[NL80211_SURVEY_INFO_NOISE]);
+       if (!fn->noise || si[NL80211_SURVEY_INFO_IN_USE])
+               fn->noise = nla_get_u8(si[NL80211_SURVEY_INFO_NOISE]);
 
        return NL_SKIP;
 }
@@ -1688,13 +1697,16 @@ static int nl80211_get_noise_cb(struct nl_msg *msg, void *arg)
 
 static int nl80211_get_noise(const char *ifname, int *buf)
 {
-       int8_t noise = 0;
+       struct nl80211_frequency_noise fn = { };
+
+       if (nl80211_get_frequency(ifname, (int *)&fn.frequency) < 0)
+               goto out;
 
        if (nl80211_request(ifname, NL80211_CMD_GET_SURVEY, NLM_F_DUMP,
-                           nl80211_get_noise_cb, &noise))
+                           nl80211_get_noise_cb, &fn))
                goto out;
 
-       *buf = noise;
+       *buf = (int8_t)fn.noise;
        return 0;
 
 out: