From: Jakub Kicinski <kuba@kernel.org>
To: hilalrahmatullah11@gmail.com
Cc: Jakub Kicinski <kuba@kernel.org>,
davem@davemloft.net, edumazet@google.com, pabeni@redhat.com,
horms@kernel.org, donald.hunter@gmail.com,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH net v3] wifi: nl80211: document sta-info nested attribute
Date: Tue, 18 Aug 2026 10:07:32 -0700 [thread overview]
Message-ID: <20260818170732.4018358-1-kuba@kernel.org> (raw)
In-Reply-To: <20260816101216.20947-1-hilalrahmatullah11@gmail.com>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
wifi: nl80211: document sta-info nested attribute
This converts NL80211_ATTR_STA_INFO in the nl80211 YAML spec from an
opaque binary blob into a real nest, and adds the sta-info-attrs,
rate-info-attrs, sta-bss-param-attrs and tid-stats-attrs sets plus the
supporting enum definitions. A few questions below about how some of the
new entries line up with what net/wireless/nl80211.c actually puts on the
wire.
> diff --git a/Documentation/netlink/specs/nl80211.yaml b/Documentation/netlink/specs/nl80211.yaml
> index 802097128bdae..4ad391db4a76d 100644
> --- a/Documentation/netlink/specs/nl80211.yaml
> +++ b/Documentation/netlink/specs/nl80211.yaml
[ ... ]
> @@ -297,7 +361,8 @@ attribute-sets:
> type: u32
> -
> name: sta-info
> - type: binary # TODO: nest
> + type: nest
> + nested-attributes: sta-info-attrs
> -
> name: wiphy-bands
> type: nest
[ ... ]
> @@ -1601,6 +1666,102 @@ attribute-sets:
> name: nan
> type: nest
> nested-attributes: frame-type-attrs
> + -
> + name: rate-info-attrs
> + enum-name: nl80211-rate-info
> + name-prefix: nl80211-rate-info-
> + attributes:
[ ... ]
> + -
> + name: 16-mhz-width
> + type: flag
[Severity: Medium]
The set stops at 16-mhz-width, which gets implicit value 29 and lines up
one-for-one with the enum up to that point. But enum nl80211_rate_info in
include/uapi/linux/nl80211.h in this same tree continues:
NL80211_RATE_INFO_16_MHZ_WIDTH,
NL80211_RATE_INFO_UHR_MCS,
NL80211_RATE_INFO_UHR_ELR,
NL80211_RATE_INFO_UHR_IM,
and nl80211_put_sta_rate() emits them inside the same nest:
} else if (info->flags & RATE_INFO_FLAGS_UHR_MCS) {
if (nla_put_u8(msg, NL80211_RATE_INFO_UHR_MCS, info->mcs))
...
if (info->flags & RATE_INFO_FLAGS_UHR_ELR &&
nla_put_flag(msg, NL80211_RATE_INFO_UHR_ELR))
With values 30, 31 and 32 missing from the spec, does a get-station or
dump-station on UHR capable hardware abort in the decoder? In
tools/net/ynl/pyynl/lib/ynl.py the lookup path is:
attr_spec = attr_space.attrs_by_val[attr.type]
except (KeyError, UnboundLocalError) as err:
if not self.process_unknown:
raise YnlException(f"Space '{space}' has no attribute "
so unless process_unknown is set the whole reply fails rather than
returning the station data. Should uhr-mcs, uhr-elr and uhr-im be added
here?
> -
> name: sar-attributes
> enum-name: nl80211-sar-attrs
[ ... ]
> @@ -1631,6 +1792,170 @@ attribute-sets:
> -
> name: end-freq
> type: u32
[ ... ]
> + -
> + name: sta-info-attrs
> + enum-name: nl80211-sta-info
> + name-prefix: nl80211-sta-info-
> + attributes:
[ ... ]
> + -
> + name: rx-bytes64
> + type: u64
> + -
> + name: tx-bytes64
> + type: u64
> + -
> + name: chain-signal
> + type: u8
> + -
> + name: chain-signal-avg
> + type: u8
[Severity: Medium]
Are these two really scalars on the wire? nl80211_send_station() routes
both through nl80211_put_signal():
if (sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) {
if (!nl80211_put_signal(msg, sinfo->chains, sinfo->chain_signal, NL80211_STA_INFO_CHAIN_SIGNAL))
and nl80211_put_signal() builds a nest keyed by chain index:
attr = nla_nest_start_noflag(msg, id);
...
if (nla_put_u8(msg, i, signal[i]))
so the payload is at least nla_total_size(1), never one byte. The per-link
fill path does the same thing with link_sinfo->chains, and
include/uapi/linux/nl80211.h documents it as:
* @NL80211_STA_INFO_CHAIN_SIGNAL: per-chain signal strength of last PPDU
* Contains a nested array of signal strength attributes (u8, dBm)
With type: u8 the decoder takes the scalar path in
tools/net/ynl/pyynl/lib/ynl.py:
def as_scalar(self, attr_type, byte_order=None):
format_ = self.get_format(attr_type, byte_order)
return format_.unpack(self.raw)[0]
which has no length tolerance, so unpacking an eight byte nest as 'B'
raises struct.error and the reply decode is aborted with "Error decoding
'chain-signal' from 'sta-info-attrs'". While NL80211_ATTR_STA_INFO was
type: binary the blob was never walked, so does making it a nest turn this
into a live failure for every station report from hardware that sets
sinfo->chains? Would an indexed array of u8 (sub-attribute type is the
0-based chain index) describe it correctly?
> + -
> + name: expected-throughput
> + type: u32
> + -
> + name: rx-drop-misc
> + type: u64
> + -
> + name: beacon-rx
> + type: u64
> + -
> + name: beacon-signal-avg
> + type: u8
> + -
> + name: tid-stats
> + type: indexed-array
> + sub-type: nest
> + nested-attributes: tid-stats-attrs
> + -
> + name: rx-duration
> + type: u64
> + -
> + name: pad
> + type: binary
[Severity: Low]
This isn't a bug, but should this (and the pad entry added to
tid-stats-attrs below) use type: pad instead of type: binary?
NL80211_STA_INFO_PAD is only ever used as the padattr argument:
nla_put_u64_64bit(msg, NL80211_STA_INFO_ ## attr, \
sinfo->memb, NL80211_STA_INFO_PAD))
and NL80211_TID_STATS_PAD is used the same way by PUT_TIDVAL_U64. The
tooling special-cases the dedicated type in
tools/net/ynl/pyynl/lib/ynl.py:
if attr_spec["type"] == 'pad':
continue
so as binary the filler shows up as a decoded pad field and the generated
documentation claims it carries binary content. Other in-tree specs
(tc.yaml, rt-link.yaml, ethtool.yaml, nftables.yaml) use type: pad for
these. Note the existing NL80211_ATTR_PAD entry in this file already uses
type: binary, so this matches an existing wart in the family rather than
introducing a functional break.
> + -
> + name: ack-signal
> + type: u8
> + -
> + name: ack-signal-avg
> + type: u8
[Severity: Medium]
Should ack-signal-avg be s8? The emitter uses the signed helper:
PUT_SINFO(ACK_SIGNAL, ack_signal, u8);
PUT_SINFO(ACK_SIGNAL_AVG, avg_ack_signal, s8);
which expands to nla_put_s8(), the per-link path does
PUT_LINK_SINFO(ACK_SIGNAL_AVG, avg_ack_signal, s8), struct station_info
declares avg_ack_signal as s8, and the uapi header says:
* @NL80211_STA_INFO_ACK_SIGNAL_AVG: avg signal strength of ACK frames (s8, dBm)
The payload is one byte either way, so there is no parse error, just a
value reported as 214 instead of -42. s8 is accepted by the schema
(the attr-type enum in Documentation/netlink/genetlink-legacy.yaml lists
it).
Related, and weaker: signal, signal-avg, ack-signal and beacon-signal-avg
are put with nla_put_u8() so u8 matches the emitter literally, but the
underlying station_info members are s8 dBm values, so spec-driven decoders
will print them as large positive numbers. Is that intended here?
> + -
> + name: rx-mpdus
> + type: u32
[ ... ]
> @@ -1672,6 +1997,30 @@ attribute-sets:
> -
> name: nan
> type: flag
> + -
> + name: tid-stats-attrs
> + enum-name: nl80211-tid-stats
> + name-prefix: nl80211-tid-stats-
> + attributes:
[ ... ]
> + -
> + name: pad
> + type: binary
> + -
> + name: txq-stats
> + type: nest
> + nested-attributes: txq-stats-attrs
> -
> name: txq-stats-attrs
> name-prefix: nl80211-txq-stats-
Cross-instance finding from sashiko-gemini (9bc2ddddefa645796d23dda3f200d5d56cc1ca9a67d79f78de96c69e6ca35525):
[Severity: High]
The newly added enums (`eht-gi`, `he-gi`, `eht-ru-alloc`, `he-ru-alloc`, `mesh-power-mode`, `plink-state`) lack the `name-prefix` property, causing YNL to emit incorrect C constants.
--
pw-bot: cr
prev parent reply other threads:[~2026-08-18 17:07 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-16 10:12 [PATCH net v3] wifi: nl80211: document sta-info nested attribute Hilal Rahmatullah
2026-08-17 15:47 ` Jakub Kicinski
2026-08-18 17:07 ` Jakub Kicinski [this message]
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=20260818170732.4018358-1-kuba@kernel.org \
--to=kuba@kernel.org \
--cc=davem@davemloft.net \
--cc=donald.hunter@gmail.com \
--cc=edumazet@google.com \
--cc=hilalrahmatullah11@gmail.com \
--cc=horms@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox