From: Paolo Abeni <pabeni@redhat.com>
To: maxime.chevallier@bootlin.com
Cc: andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
kuba@kernel.org, pabeni@redhat.com, linux@armlinux.org.uk,
hkallweit1@gmail.com, alexis.lothore@bootlin.com,
mcoquelin.stm32@gmail.com, alexandre.torgue@foss.st.com,
kernel@esmil.dk, minda.chen@starfivetech.com,
neil.armstrong@linaro.org, khilman@baylibre.com,
jbrunet@baylibre.com, martin.blumenstingl@googlemail.com,
jan.petrous@oss.nxp.com, ovidiu.panait.rb@renesas.com,
Jose.Abreu@synopsys.com, nb@tipi-net.de, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com,
linux-arm-kernel@lists.infradead.org,
linux-stm32@st-md-mailman.stormreply.com, PKneuper@dspace.de,
david.laight.linux@gmail.com
Subject: Re: [PATCH net v3 4/6] net: stmmac: selftests: Capture all packets for vlan checks
Date: Tue, 15 Sep 2026 10:45:47 +0200 [thread overview]
Message-ID: <20260915084547.75267-1-pabeni@redhat.com> (raw)
In-Reply-To: <20260911212028.1497613-5-maxime.chevallier@bootlin.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.
Full review at: https://netdev-ai.bots.linux.dev/sashiko/
---
net: stmmac: selftests: Capture all packets for vlan checks
The VLAN selftests use vlan_vid_add() without a VLAN netdev, so the test
frame is marked PACKET_OTHERHOST and reaches the handler with a cleared
skb->vlan_tci. This patch reuses the DSA proxy mechanism to register an
ETH_P_ALL handler for the three VLAN tests so validation sees the tag.
A few questions about the new capture_all path below.
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c
> index 7f5837d1fed94..315c3cf82230e 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c
> @@ -242,6 +242,7 @@ struct stmmac_test_priv {
> __be16 packet_type;
> int (*func)(struct sk_buff *skb, struct net_device *ndev,
> struct packet_type *pt, struct net_device *orig_ndev);
> + bool capture_all;
> int double_vlan;
> int vlan_id;
> int ok;
> @@ -344,7 +345,7 @@ static void stmmac_sft_add_pack(struct packet_type *pt)
> {
> struct stmmac_test_priv *tpriv = pt->af_packet_priv;
>
> - if (netdev_uses_dsa(tpriv->pt.dev)) {
> + if (netdev_uses_dsa(tpriv->pt.dev) || tpriv->capture_all) {
> tpriv->packet_type = tpriv->pt.type;
> tpriv->func = tpriv->pt.func;
>
> /* DSA conduit will report ETH_P_XDSA, so our packet handler
> * won't match. Let's register a ETH_P_ALL match and filter
> * manually in stmmac_sft_filter.
> */
[Severity: Low]
This isn't a bug, but the comment now only describes one of the two reasons
for taking this branch. For the three VLAN tests pt.type is ETH_P_IP or
ETH_P_8021Q, which would match at ptype_specific just fine, so the
"DSA conduit will report ETH_P_XDSA" rationale does not apply there.
Could the comment also mention the capture_all reason (the tap has to run
at ptype_all so skb->vlan_tci is still populated), and could the new
capture_all field get a one-line comment stating that it must be set before
stmmac_sft_add_pack() is called?
> tpriv->pt.type = htons(ETH_P_ALL);
> tpriv->pt.func = stmmac_sft_filter;
> tpriv->pt.ignore_outgoing = true;
> }
[Severity: Medium]
With pt.type set to ETH_P_ALL on priv->dev, stmmac_test_vlan_validate() now
sees every ingress frame, and it declares the test failed before it has
established that the frame is a test frame:
if (tpriv->vlan_id) {
if (skb->vlan_proto != htons(proto))
goto out;
if (skb->vlan_tci != tpriv->vlan_id) {
/* Means filter did not work. */
tpriv->ok = false;
complete(&tpriv->comp);
goto out;
}
}
ehdr = (struct ethhdr *)skb_mac_header(skb);
if (!ether_addr_equal_unaligned(ehdr->h_dest, tpriv->packet->dst))
goto out;
The h_dest and magic checks come after this. Can any ordinary C-tagged
IPv4 frame on the link (any VID other than 0x123, at least 33 bytes of
linear data) now abort the VLAN Filter, Double VLAN Filter and VLAN Offload
tests with a spurious failure for i == 0? Before this patch the tag was
cleared for such frames, so the vlan_proto check bailed out first.
Would it make sense to move the vlan_tci comparison after the destination
MAC and magic checks so only test frames can set the verdict?
[Severity: Low]
This isn't a bug introduced by this patch, but the ETH_P_ALL tap widens the
set of frames that reach the header parsing in stmmac_test_vlan_validate(),
which derives offsets from the untrusted IPv4 ihl with only a fixed length
check:
if (skb_headlen(skb) < (STMMAC_TEST_PKT_SIZE - ETH_HLEN))
goto out;
...
uhdr = (struct udphdr *)((u8 *)ihdr + 4 * ihdr->ihl);
if (uhdr->dest != htons(tpriv->packet->dport))
goto out;
shdr = (struct stmmachdr *)((u8 *)uhdr + sizeof(*uhdr));
That check covers 33 bytes, which does not include the UDP header, the
extra +4 double-VLAN offset, or an ihl larger than 5. A frame with ihl = 15
makes uhdr->dest be read well past the validated area (and past skb->len for
a small frame). The same arithmetic exists in
stmmac_test_loopback_validate(), so this predates the patch, but would a
pskb_may_pull() style length check based on the actual ihl be worth adding
here?
> @@ -999,6 +1000,7 @@ static int __stmmac_test_vlanfilt(struct stmmac_priv *priv)
> tpriv->pt.dev = priv->dev;
> tpriv->pt.af_packet_priv = tpriv;
> tpriv->packet = &attr;
> + tpriv->capture_all = true;
[Severity: Medium]
This is a pre-existing issue, but the patch makes it observable. The
"Means filter did not work" path in stmmac_test_vlan_validate() reports
failure through the same tpriv->ok = false state that a timeout produces,
and the loop here treats that state as the expected outcome for i > 0:
wait_for_completion_timeout(&tpriv->comp, STMMAC_LB_TIMEOUT);
ret = tpriv->ok ? 0 : -ETIMEDOUT;
if (ret && !i) {
goto vlan_del;
} else if (!ret && i) {
ret = -EINVAL;
goto vlan_del;
} else {
ret = 0;
}
So a frame admitted with a non-configured VID (0x124..0x126) is
indistinguishable from a correctly dropped frame, and the test still passes
even if the hardware admits every VID. Before this patch the mismatch
branch was unreachable because skb->vlan_tci was always cleared; now it is
reachable but its verdict is discarded. Could the return value of
wait_for_completion_timeout() be checked, or a separate "packet was
admitted" flag be used, so the two cases can be told apart? The same
pattern is in __stmmac_test_dvlanfilt().
[Severity: Medium]
Also pre-existing rather than introduced here: tpriv->ok, tpriv->comp and
the on-stack attr are shared between the softirq validator and this loop
with no serialization, and init_completion() is only called once, outside
the loop. With capture_all, an extra complete() is now reachable from the
"filter did not work" path for any tagged frame with a different VID.
Since complete() increments comp.done and wait_for_completion_timeout()
consumes only one, does a surplus completion in one iteration make the next
wait_for_completion_timeout() return immediately and take the verdict from a
stale tpriv->ok? Would a reinit_completion() at the top of each iteration
help here?
> @@ -1093,6 +1095,7 @@ static int __stmmac_test_dvlanfilt(struct stmmac_priv *priv)
> tpriv->pt.dev = priv->dev;
> tpriv->pt.af_packet_priv = tpriv;
> tpriv->packet = &attr;
> + tpriv->capture_all = true;
[Severity: High]
Does this actually fix the Double VLAN Filter test on the cores that can run
it? The test requires priv->dma_cap.vlhash, i.e. the xmac cores, where
probe sets priv->hw->hw_vlan_en = true and stmmac_hw_setup() programs
VLAN_TAG_STRIP_ALL together with VLAN_TAG_CTRL_EVLRXS, while
vlan_vid_add(ETH_P_8021AD, ...) enables S-VLAN recognition.
The MAC-stripped outer tag is then reported by vlan_rx_hw() in
stmmac_vlan.c:
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
which hardcodes ETH_P_8021Q, while the validator with double_vlan set wants
ETH_P_8021AD:
proto = tpriv->double_vlan ? ETH_P_8021AD : ETH_P_8021Q;
...
if (skb->vlan_proto != htons(proto))
goto out;
So the frame does reach the validator now, but the vlan_proto check takes
"goto out" without calling complete(), and the test still returns -ETIMEDOUT
for i == 0 on working hardware unless RX VLAN stripping is turned off. Is
the intent that vlan_rx_hw() report the real tag protocol, or that the
validator accept ETH_P_8021Q for the stripped outer tag?
> @@ -1371,6 +1374,7 @@ static int stmmac_test_vlanoff_common(struct stmmac_priv *priv, bool svlan)
> tpriv->pt.af_packet_priv = tpriv;
> tpriv->packet = &attr;
> tpriv->vlan_id = 0x123;
> + tpriv->capture_all = true;
> stmmac_sft_add_pack(&tpriv->pt);
>
> ret = vlan_vid_add(priv->dev, htons(proto), tpriv->vlan_id);
[Severity: High]
Can this dereference a NULL pointer in softirq context? attr is
zero-initialized, so attr.dst is NULL, and the ETH_P_ALL handler is
published by stmmac_sft_add_pack() before attr.dst is assigned:
tpriv->capture_all = true;
stmmac_sft_add_pack(&tpriv->pt);
ret = vlan_vid_add(priv->dev, htons(proto), tpriv->vlan_id);
if (ret)
goto cleanup;
attr.dst = priv->dev->dev_addr;
vlan_vid_add() is not instantaneous here: it does
pm_runtime_resume_and_get() and a register poll in vlan_write_filter(). A
frame arriving in that window with vlan_proto ETH_P_8021Q and vlan_tci equal
to the hard-coded 0x123 passes the tag checks and falls into:
ehdr = (struct ethhdr *)skb_mac_header(skb);
if (!ether_addr_equal_unaligned(ehdr->h_dest, tpriv->packet->dst))
goto out;
which reads 6 bytes from address 0. stmmac_test_loopback_validate() guards
the same comparison with "if (dst)", so the pointer does not look like an
invariant. The same ordering exists in __stmmac_test_vlanfilt() and
__stmmac_test_dvlanfilt(), where attr.dst is only set inside the loop.
Would assigning attr.dst before stmmac_sft_add_pack(), or adding the NULL
check to this validator, close that window?
--
This is an AI-generated review.
next prev parent reply other threads:[~2026-09-15 8:46 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-11 21:20 [PATCH net v3 0/6] net: stmmac: More selftest-related fixes Maxime Chevallier
2026-09-11 21:20 ` [PATCH net v3 1/6] net: stmmac: selftests: Support running selftests on DSA conduits Maxime Chevallier
2026-09-15 8:45 ` Paolo Abeni
2026-09-15 9:22 ` Maxime Chevallier
2026-09-11 21:20 ` [PATCH net v3 2/6] net: stmmac: selftests: Validate EEE based on the actual LPI timer value Maxime Chevallier
2026-09-11 21:20 ` [PATCH net v3 3/6] net: stmmac: selftests: Check the dev->features for S-TAG offload testing Maxime Chevallier
2026-09-11 21:20 ` [PATCH net v3 4/6] net: stmmac: selftests: Capture all packets for vlan checks Maxime Chevallier
2026-09-15 8:45 ` Paolo Abeni [this message]
2026-09-15 11:54 ` Maxime Chevallier
2026-09-11 21:20 ` [PATCH net v3 5/6] net: stmmac: size the RX buffers from the frame length, not the MTU Maxime Chevallier
2026-09-15 8:45 ` Paolo Abeni
2026-09-11 21:20 ` [PATCH net v3 6/6] net: stmmac: selftests: Account for alignment shift on dwmac1000 for Jumbo test Maxime Chevallier
2026-09-15 8:50 ` [PATCH net v3 0/6] net: stmmac: More selftest-related fixes Paolo Abeni
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=20260915084547.75267-1-pabeni@redhat.com \
--to=pabeni@redhat.com \
--cc=Jose.Abreu@synopsys.com \
--cc=PKneuper@dspace.de \
--cc=alexandre.torgue@foss.st.com \
--cc=alexis.lothore@bootlin.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=david.laight.linux@gmail.com \
--cc=edumazet@google.com \
--cc=hkallweit1@gmail.com \
--cc=jan.petrous@oss.nxp.com \
--cc=jbrunet@baylibre.com \
--cc=kernel@esmil.dk \
--cc=khilman@baylibre.com \
--cc=kuba@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-stm32@st-md-mailman.stormreply.com \
--cc=linux@armlinux.org.uk \
--cc=martin.blumenstingl@googlemail.com \
--cc=maxime.chevallier@bootlin.com \
--cc=mcoquelin.stm32@gmail.com \
--cc=minda.chen@starfivetech.com \
--cc=nb@tipi-net.de \
--cc=neil.armstrong@linaro.org \
--cc=netdev@vger.kernel.org \
--cc=ovidiu.panait.rb@renesas.com \
--cc=thomas.petazzoni@bootlin.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
all inboxes | Powered by JetHome®